*/
package org.opendaylight.controller.config.api;
-import javax.management.ObjectName;
-
import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+
+import javax.management.ObjectName;
/**
* Each new {@link org.opendaylight.controller.config.spi.Module} can receive
<T> T resolveInstance(Class<T> expectedType, ObjectName objectName,
JmxAttribute jmxAttribute);
+ // TODO finish javadoc
+
+ /**
+ * To be used during commit phase to resolve identity-ref config attributes.
+ *
+ * @return actual class object generated from identity
+ */
+ <T extends BaseIdentity> Class<? extends T> resolveIdentity(IdentityAttributeRef identityRef, Class<T> expectedBaseClass);
+
+ <T extends BaseIdentity> void validateIdentity(IdentityAttributeRef identityRef, Class<T> expectedBaseClass, JmxAttribute jmxAttribute);
+
}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.config.api;
+
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+
+import java.beans.ConstructorProperties;
+
+public final class IdentityAttributeRef {
+
+ public static final String QNAME_ATTR_NAME = "qNameOfIdentity";
+
+ private final String qNameOfIdentity;
+
+ @ConstructorProperties(QNAME_ATTR_NAME)
+ public IdentityAttributeRef(String qNameOfIdentity) {
+ if (qNameOfIdentity == null)
+ throw new NullPointerException("Parameter " + QNAME_ATTR_NAME + " is null");
+ this.qNameOfIdentity = qNameOfIdentity;
+ }
+
+ public String getqNameOfIdentity() {
+ return qNameOfIdentity;
+ }
+
+ public <T extends BaseIdentity> Class<? extends T> resolveIdentity(DependencyResolver resolver, Class<T> baseIdentity) {
+ return resolver.resolveIdentity(this, baseIdentity);
+ }
+
+ public <T extends BaseIdentity> void validateIdentity(DependencyResolver resolver, Class<T> baseIdentity, JmxAttribute jmxAttribute) {
+ resolver.validateIdentity(this, baseIdentity, jmxAttribute);
+ }
+
+ @Override
+ public String toString() {
+ final StringBuffer sb = new StringBuffer("IdentityAttributeRef{");
+ sb.append("qNameOfIdentity='").append(qNameOfIdentity).append('\'');
+ sb.append('}');
+ return sb.toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof IdentityAttributeRef)) return false;
+
+ IdentityAttributeRef that = (IdentityAttributeRef) o;
+
+ if (!qNameOfIdentity.equals(that.qNameOfIdentity)) return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return qNameOfIdentity.hashCode();
+ }
+
+}
import org.opendaylight.controller.config.manager.impl.util.ModuleQNameUtil;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final ModuleFactoriesResolver resolver;
private final MBeanServer configMBeanServer;
+ private final CodecRegistry codecRegistry;
@GuardedBy("this")
private long version = 0;
// constructor
public ConfigRegistryImpl(ModuleFactoriesResolver resolver,
- MBeanServer configMBeanServer) {
+ MBeanServer configMBeanServer, CodecRegistry codecRegistry) {
this(resolver, configMBeanServer,
- new BaseJMXRegistrator(configMBeanServer));
+ new BaseJMXRegistrator(configMBeanServer), codecRegistry);
}
// constructor
public ConfigRegistryImpl(ModuleFactoriesResolver resolver,
MBeanServer configMBeanServer,
- BaseJMXRegistrator baseJMXRegistrator) {
+ BaseJMXRegistrator baseJMXRegistrator, CodecRegistry codecRegistry) {
this.resolver = resolver;
this.beanToOsgiServiceManager = new BeanToOsgiServiceManager();
this.configMBeanServer = configMBeanServer;
this.baseJMXRegistrator = baseJMXRegistrator;
+ this.codecRegistry = codecRegistry;
this.registryMBeanServer = MBeanServerFactory
.createMBeanServer("ConfigRegistry" + configMBeanServer.getDefaultDomain());
this.transactionsMBeanServer = MBeanServerFactory
readableSRRegistry, txLookupRegistry, allCurrentFactories);
ConfigTransactionControllerInternal transactionController = new ConfigTransactionControllerImpl(
- txLookupRegistry, version,
+ txLookupRegistry, version, codecRegistry,
versionCounter, allCurrentFactories, transactionsMBeanServer,
configMBeanServer, blankTransaction, writableRegistry);
try {
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
import org.opendaylight.yangtools.concepts.Identifiable;
+import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
private final ServiceReferenceWritableRegistry writableSRRegistry;
public ConfigTransactionControllerImpl(ConfigTransactionLookupRegistry txLookupRegistry,
- long parentVersion, long currentVersion,
- Map<String, Map.Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories,
+ long parentVersion, CodecRegistry codecRegistry, long currentVersion,
+ Map<String, Entry<ModuleFactory, BundleContext>> currentlyRegisteredFactories,
MBeanServer transactionsMBeanServer, MBeanServer configMBeanServer,
boolean blankTransaction, ServiceReferenceWritableRegistry writableSRRegistry) {
-
this.txLookupRegistry = txLookupRegistry;
String transactionName = txLookupRegistry.getTransactionIdentifier().getName();
this.controllerON = ObjectNameUtil.createTransactionControllerON(transactionName);
this.currentlyRegisteredFactories = currentlyRegisteredFactories;
this.factoriesHolder = new HierarchicalConfigMBeanFactoriesHolder(currentlyRegisteredFactories);
this.transactionStatus = new TransactionStatus();
- this.dependencyResolverManager = new DependencyResolverManager(transactionName, transactionStatus, writableSRRegistry);
+ this.dependencyResolverManager = new DependencyResolverManager(transactionName, transactionStatus, writableSRRegistry, codecRegistry);
this.transactionsMBeanServer = transactionsMBeanServer;
this.configMBeanServer = configMBeanServer;
this.blankTransaction = blankTransaction;
package org.opendaylight.controller.config.manager.impl.dependencyresolver;
import org.opendaylight.controller.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.IdentityAttributeRef;
import org.opendaylight.controller.config.api.JmxAttribute;
import org.opendaylight.controller.config.api.JmxAttributeValidationException;
import org.opendaylight.controller.config.api.ModuleIdentifier;
import org.opendaylight.controller.config.manager.impl.TransactionStatus;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.opendaylight.yangtools.yang.binding.BaseIdentity;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
+import org.opendaylight.yangtools.yang.data.impl.codec.IdentityCodec;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import javax.annotation.concurrent.GuardedBy;
import javax.management.ObjectName;
*/
final class DependencyResolverImpl implements DependencyResolver,
Comparable<DependencyResolverImpl> {
+ private static final Logger logger = LoggerFactory.getLogger(DependencyResolverImpl.class);
+
private final ModulesHolder modulesHolder;
private final ModuleIdentifier name;
private final TransactionStatus transactionStatus;
@GuardedBy("this")
private final Set<ModuleIdentifier> dependencies = new HashSet<>();
private final ServiceReferenceReadableRegistry readableRegistry;
+ private final CodecRegistry codecRegistry;
DependencyResolverImpl(ModuleIdentifier currentModule,
- TransactionStatus transactionStatus, ModulesHolder modulesHolder,
- ServiceReferenceReadableRegistry readableRegistry) {
-
+ TransactionStatus transactionStatus, ModulesHolder modulesHolder,
+ ServiceReferenceReadableRegistry readableRegistry, CodecRegistry codecRegistry) {
+ this.codecRegistry = codecRegistry;
this.name = currentModule;
this.transactionStatus = transactionStatus;
this.modulesHolder = modulesHolder;
throw new NullPointerException("Parameter 'jmxAttribute' is null");
JmxAttributeValidationException.checkNotNull(dependentReadOnlyON,
- "is null, " + "expected dependency implementing "
+ "is null, expected dependency implementing "
+ expectedServiceInterface, jmxAttribute);
JmxAttribute jmxAttribute) {
if (expectedType == null || dependentReadOnlyON == null || jmxAttribute == null) {
throw new IllegalArgumentException(format(
- "Null parameters not allowed, got {} {} {}", expectedType,
+ "Null parameters not allowed, got %s %s %s", expectedType,
dependentReadOnlyON, jmxAttribute));
}
dependentReadOnlyON = translateServiceRefIfPossible(dependentReadOnlyON);
}
}
+ @Override
+ public <T extends BaseIdentity> Class<? extends T> resolveIdentity(IdentityAttributeRef identityRef, Class<T> expectedBaseClass) {
+ final QName qName = QName.create(identityRef.getqNameOfIdentity());
+ IdentityCodec<?> identityCodec = codecRegistry.getIdentityCodec();
+ Class<? extends BaseIdentity> deserialized = identityCodec.deserialize(qName);
+ if (deserialized == null) {
+ throw new RuntimeException("Unable to retrieve identity class for " + qName + ", null response from "
+ + codecRegistry);
+ }
+ if (expectedBaseClass.isAssignableFrom(deserialized)) {
+ return (Class<T>) deserialized;
+ } else {
+ logger.error("Cannot resolve class of identity {} : deserialized class {} is not a subclass of {}.",
+ identityRef, deserialized, expectedBaseClass);
+ throw new IllegalArgumentException("Deserialized identity " + deserialized + " cannot be cast to " + expectedBaseClass);
+ }
+ }
+
+ @Override
+ public <T extends BaseIdentity> void validateIdentity(IdentityAttributeRef identityRef, Class<T> expectedBaseClass, JmxAttribute jmxAttribute) {
+ try {
+ resolveIdentity(identityRef, expectedBaseClass);
+ } catch(Exception e) {
+ throw JmxAttributeValidationException.wrap(e, jmxAttribute);
+ }
+ }
+
@Override
public int compareTo(DependencyResolverImpl o) {
transactionStatus.checkCommitted();
.getOrCreate(dependencyName);
if (chainForDetectingCycles2.contains(dependencyName)) {
throw new IllegalStateException(format(
- "Cycle detected, {} contains {}",
+ "Cycle detected, %s contains %s",
chainForDetectingCycles2, dependencyName));
}
int subDepth;
import org.opendaylight.controller.config.manager.impl.TransactionStatus;
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
import javax.annotation.concurrent.GuardedBy;
import javax.management.InstanceAlreadyExistsException;
private final ModulesHolder modulesHolder;
private final TransactionStatus transactionStatus;
private final ServiceReferenceReadableRegistry readableRegistry;
+ private final CodecRegistry codecRegistry;
public DependencyResolverManager(String transactionName,
- TransactionStatus transactionStatus, ServiceReferenceReadableRegistry readableRegistry) {
+ TransactionStatus transactionStatus, ServiceReferenceReadableRegistry readableRegistry, CodecRegistry codecRegistry) {
this.modulesHolder = new ModulesHolder(transactionName);
this.transactionStatus = transactionStatus;
this.readableRegistry = readableRegistry;
+ this.codecRegistry = codecRegistry;
}
@Override
DependencyResolverImpl dependencyResolver = moduleIdentifiersToDependencyResolverMap.get(name);
if (dependencyResolver == null) {
transactionStatus.checkNotCommitted();
- dependencyResolver = new DependencyResolverImpl(name, transactionStatus, modulesHolder, readableRegistry);
+ dependencyResolver = new DependencyResolverImpl(name, transactionStatus, modulesHolder, readableRegistry, codecRegistry);
moduleIdentifiersToDependencyResolverMap.put(name, dependencyResolver);
}
return dependencyResolver;
// TODO push codecRegistry/IdentityCodec to dependencyResolver
configRegistry = new ConfigRegistryImpl(
- bundleContextBackedModuleFactoriesResolver, configMBeanServer);
+ bundleContextBackedModuleFactoriesResolver, configMBeanServer, codecRegistry);
// register config registry to OSGi
configRegistryServiceRegistration = context.registerService(ConfigRegistryImpl.class, configRegistry, null);
factory, factory);
configRegistry = new ConfigRegistryImpl(resolver,
- ManagementFactory.getPlatformMBeanServer());
+ ManagementFactory.getPlatformMBeanServer(), null);
configRegistry.beginConfig();
fail();
import org.opendaylight.controller.config.spi.Module;
import org.opendaylight.controller.config.util.ConfigRegistryJMXClient;
import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceRegistration;
import org.slf4j.Logger;
baseJmxRegistrator = new BaseJMXRegistrator(internalJmxRegistrator);
configRegistry = new ConfigRegistryImpl(resolver,
- platformMBeanServer, baseJmxRegistrator);
+ platformMBeanServer, baseJmxRegistrator, getCodecRegistry());
try {
configRegistryJMXRegistrator.registerToJMX(configRegistry);
return new ClassBasedModuleFactory(implementationName, configBeanClass);
}
+ protected CodecRegistry getCodecRegistry() {
+ return mock(CodecRegistry.class);
+ }
+
public static interface BundleContextServiceRegistrationHandler {
}
- private class RegisterServiceAnswer implements Answer {
+ private class RegisterServiceAnswer implements Answer<ServiceRegistration<?>> {
@Override
- public Object answer(InvocationOnMock invocation) throws Throwable {
+ public ServiceRegistration<?> answer(InvocationOnMock invocation) throws Throwable {
Object[] args = invocation.getArguments();
Preconditions.checkArgument(args.length == 3, "Unexpected arguments size (expected 3 was %s)", args.length);
@Before
public void setUp() throws Exception {
configRegistryImpl = new ConfigRegistryImpl(null,
- ManagementFactory.getPlatformMBeanServer());
+ ManagementFactory.getPlatformMBeanServer(), null);
Field field = configRegistryImpl.getClass().getDeclaredField(
"baseJMXRegistrator");
field.setAccessible(true);
testedTxController = new ConfigTransactionControllerImpl(
- txLookupRegistry, 1, 1,
+ txLookupRegistry, 1, null, 1,
currentlyRegisteredFactories, transactionsMBeanServer,
ManagementFactory.getPlatformMBeanServer(), false, writableRegistry);
TransactionModuleJMXRegistrator transactionModuleJMXRegistrator123 = testedTxController
public void setUp() {
transactionStatus = mock(TransactionStatus.class);
ServiceReferenceReadableRegistry mockedRegistry = mock(ServiceReferenceReadableRegistry.class);
- tested = new DependencyResolverManager("txName", transactionStatus, mockedRegistry);
+ tested = new DependencyResolverManager("txName", transactionStatus, mockedRegistry, null);
doNothing().when(transactionStatus).checkCommitStarted();
doNothing().when(transactionStatus).checkNotCommitted();
}
import com.google.common.collect.Collections2;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.IdentityAttributeRef;
import org.opendaylight.controller.config.api.RuntimeBeanRegistratorAwareModule;
import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
import org.opendaylight.controller.config.api.runtime.RuntimeBean;
import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Constructor;
import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Field;
import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.Header;
+import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.IdentityRefModuleField;
import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.MethodDeclaration;
import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.MethodDefinition;
import org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model.ModuleField;
import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
import org.opendaylight.yangtools.sal.binding.model.api.ParameterizedType;
import org.opendaylight.yangtools.sal.binding.model.api.Type;
+import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
import javax.management.openmbean.SimpleType;
import java.util.ArrayList;
}
// FIXME: put into Type.toString
- static String serializeType(Type type) {
+ static String serializeType(Type type, boolean addWildcards) {
if (type instanceof ParameterizedType){
ParameterizedType parameterizedType = (ParameterizedType) type;
StringBuffer sb = new StringBuffer();
sb.append(parameterizedType.getRawType().getFullyQualifiedName());
- sb.append("<");
+ sb.append(addWildcards ? "<? extends " : "<");
boolean first = true;
for(Type parameter: parameterizedType.getActualTypeArguments()) {
if (first) {
}
}
+ static String serializeType(Type type) {
+ return serializeType(type, false);
+ }
+
+ private static boolean isIdentityRefType(Type type) {
+ return type instanceof IdentityrefTypeDefinition;
+ }
+
private static String getReturnType(AttributeIfc attributeIfc) {
String returnType;
processAttrs(attrs, packageName);
}
+ private final static String dependencyResolverVarName = "dependencyResolver";
+ private final static String dependencyResolverInjectMethodName = "injectDependencyResolver";
+
private void processAttrs(Map<String, AttributeIfc> attrs, String packageName) {
fields = Lists.newArrayList();
methods = Lists.newArrayList();
+ // FIXME conflict if "dependencyResolver" field from yang
+ Field depRes = new Field(DependencyResolver.class.getName(), dependencyResolverVarName);
+ fields.add(depRes);
+ methods.add(new MethodDefinition("void", dependencyResolverInjectMethodName, Lists.newArrayList(depRes),
+ "this." + dependencyResolverVarName + " = " + dependencyResolverVarName + ";"));
+
for (Entry<String, AttributeIfc> attrEntry : attrs.entrySet()) {
String innerName = attrEntry.getKey();
String varName = BindingGeneratorUtil
String fullyQualifiedName, nullableDefault = null;
if (attrEntry.getValue() instanceof TypedAttribute) {
Type type = ((TypedAttribute) attrEntry.getValue()).getType();
- fullyQualifiedName = serializeType(type);
if(attrEntry.getValue() instanceof JavaAttribute) {
nullableDefault = ((JavaAttribute)attrEntry.getValue()).getNullableDefaultWrappedForCode();
+ if(((JavaAttribute)attrEntry.getValue()).isIdentityRef()) {
+
+ String fieldType = serializeType(type, true);
+ String innerType = getInnerTypeFromIdentity(type);
+ methods.add(new MethodDefinition(fieldType, "resolve" + attrEntry.getKey(), Collections.<Field>emptyList(),
+ "return " + varName + ".resolveIdentity(" + dependencyResolverVarName + "," + innerType + ".class);"));
+ type = identityRefType;
+ }
}
+ fullyQualifiedName = serializeType(type);
} else {
fullyQualifiedName = FullyQualifiedNameHelper
.getFullyQualifiedName(packageName, attrEntry.getValue().getUpperCaseCammelCase());
}
- fields.add(new Field(fullyQualifiedName, varName, nullableDefault));
+ fields.add(new Field(fullyQualifiedName, varName, nullableDefault, needsDepResolver(attrEntry.getValue())));
String getterName = "get" + innerName;
MethodDefinition getter = new MethodDefinition(
}
}
+
private static class MXBeanInterfaceAttributesProcessor {
private final List<MethodDeclaration> methods = Lists.newArrayList();
String returnType;
AttributeIfc attributeIfc = attrEntry.getValue();
+ boolean isIdentityRef = false;
if (attributeIfc instanceof TypedAttribute) {
TypedAttribute typedAttribute = (TypedAttribute) attributeIfc;
returnType = serializeType(typedAttribute.getType());
+
+ if (attributeIfc instanceof JavaAttribute && ((JavaAttribute)attrEntry.getValue()).isIdentityRef()) {
+ returnType = serializeType(identityRefType);
+ }
+
} else {
throw new UnsupportedOperationException(
"Attribute not supported: "
MethodDeclaration setter = new MethodDeclaration("void",
setterName, Lists.newArrayList(new Field(returnType,
varName)));
+
methods.add(getter);
methods.add(setter);
}
}
+ private static final Type identityRefType = new Type() {
+ public final Class<IdentityAttributeRef> IDENTITY_ATTRIBUTE_REF_CLASS = IdentityAttributeRef.class;
+
+ @Override
+ public String getPackageName() {
+ return IDENTITY_ATTRIBUTE_REF_CLASS.getPackage().getName();
+ }
+
+ @Override
+ public String getName() {
+ return IDENTITY_ATTRIBUTE_REF_CLASS.getSimpleName();
+ }
+
+ @Override
+ public String getFullyQualifiedName() {
+ return IDENTITY_ATTRIBUTE_REF_CLASS.getName();
+ }
+ };
+
private static class AbstractFactoryAttributesProcessor {
private final List<Field> fields = Lists.newArrayList();
- private static final String STRING_FULLY_QUALIFIED_NAME = "java.util.List";
void processAttributes(Map<String, AttributeIfc> attributes,
String packageName) {
if (attributeIfc instanceof TypedAttribute) {
TypedAttribute typedAttribute = (TypedAttribute) attributeIfc;
type = serializeType(typedAttribute.getType());
- } else if (attributeIfc instanceof TOAttribute) {
- String fullyQualifiedName = FullyQualifiedNameHelper
- .getFullyQualifiedName(packageName, attributeIfc.getUpperCaseCammelCase());
-
- type = fullyQualifiedName;
- } else if (attributeIfc instanceof ListAttribute) { //FIXME: listAttribute might extend TypedAttribute
- String fullyQualifiedName = null;
- AttributeIfc innerAttr = ((ListAttribute) attributeIfc)
- .getInnerAttribute();
- if (innerAttr instanceof JavaAttribute) {
- fullyQualifiedName = ((JavaAttribute) innerAttr)
- .getType().getFullyQualifiedName();
- nullableDefaultWrapped = ((JavaAttribute) innerAttr).getNullableDefaultWrappedForCode();
- } else if (innerAttr instanceof TOAttribute) {
- fullyQualifiedName = FullyQualifiedNameHelper
- .getFullyQualifiedName(packageName, innerAttr.getUpperCaseCammelCase());
- }
-
- type = STRING_FULLY_QUALIFIED_NAME.concat("<")
- .concat(fullyQualifiedName).concat(">");
-
} else {
throw new UnsupportedOperationException(
"Attribute not supported: "
private static class AbstractModuleAttributesProcessor {
- private static final String STRING_FULLY_QUALIFIED_NAME = "java.util.List";
-
private final List<ModuleField> moduleFields = Lists.newArrayList();
private final List<MethodDefinition> methods = Lists.newArrayList();
for (Entry<String, AttributeIfc> attrEntry : attributes.entrySet()) {
String type, nullableDefaultWrapped = null;
AttributeIfc attributeIfc = attrEntry.getValue();
+ boolean isIdentity = false;
+ boolean needsDepResolver = needsDepResolver(attrEntry.getValue());
if (attributeIfc instanceof TypedAttribute) {
TypedAttribute typedAttribute = (TypedAttribute) attributeIfc;
type = serializeType(typedAttribute.getType());
if (attributeIfc instanceof JavaAttribute) {
nullableDefaultWrapped = ((JavaAttribute) attributeIfc).getNullableDefaultWrappedForCode();
+ if(((JavaAttribute)attrEntry.getValue()).isIdentityRef()) {
+ isIdentity = true;
+ type = serializeType(typedAttribute.getType(), true);
+ }
}
-
- } else if (attributeIfc instanceof TOAttribute) {
- String fullyQualifiedName = FullyQualifiedNameHelper
- .getFullyQualifiedName(packageName, attributeIfc.getUpperCaseCammelCase());
-
- type = fullyQualifiedName;
- } else if (attributeIfc instanceof ListAttribute) {
- String fullyQualifiedName = null;
- AttributeIfc innerAttr = ((ListAttribute) attributeIfc)
- .getInnerAttribute();
- if (innerAttr instanceof JavaAttribute) {
- fullyQualifiedName = ((JavaAttribute) innerAttr)
- .getType().getFullyQualifiedName();
- nullableDefaultWrapped = ((JavaAttribute) innerAttr).getNullableDefaultWrappedForCode();
- } else if (innerAttr instanceof TOAttribute) {
- fullyQualifiedName = FullyQualifiedNameHelper
- .getFullyQualifiedName(packageName, innerAttr.getUpperCaseCammelCase());
- }
-
- type = STRING_FULLY_QUALIFIED_NAME.concat("<")
- .concat(fullyQualifiedName).concat(">");
} else {
throw new UnsupportedOperationException(
"Attribute not supported: "
String varName = BindingGeneratorUtil
.parseToValidParamName(attrEntry.getKey());
- moduleFields.add(new ModuleField(type, varName, attributeIfc
- .getUpperCaseCammelCase(), nullableDefaultWrapped, isDependency, dependency, isListOfDependencies));
+
+ ModuleField field;
+
+ if (isIdentity) {
+ String identityBaseClass = getInnerTypeFromIdentity(((TypedAttribute) attributeIfc).getType());
+ IdentityRefModuleField identityField = new IdentityRefModuleField(type, varName,
+ attributeIfc.getUpperCaseCammelCase(), identityBaseClass);
+
+ String getterName = "get"
+ + attributeIfc.getUpperCaseCammelCase() + "Identity";
+ MethodDefinition additionalGetter = new MethodDefinition(type, getterName, Collections.<Field> emptyList(),
+ Collections.<Annotation> emptyList(), "return " + identityField.getIdentityClassName()
+ + ";");
+ methods.add(additionalGetter);
+
+ String setterName = "set"
+ + attributeIfc.getUpperCaseCammelCase();
+
+ String setterBody = "this." + identityField.getIdentityClassName() + " = " + identityField.getIdentityClassName() + ";";
+ MethodDefinition additionalSetter = new MethodDefinition("void",
+ setterName,
+ Lists.newArrayList(new Field(type, identityField.getIdentityClassName())),
+ Collections.<Annotation> emptyList(), setterBody);
+ additionalSetter.setJavadoc(attributeIfc.getNullableDescription());
+
+ methods.add(additionalSetter);
+
+ type = serializeType(identityRefType);
+ field = identityField;
+ } else {
+ field = new ModuleField(type, varName, attributeIfc.getUpperCaseCammelCase(),
+ nullableDefaultWrapped, isDependency, dependency, isListOfDependencies, needsDepResolver);
+ }
+ moduleFields.add(field);
String getterName = "get"
+ attributeIfc.getUpperCaseCammelCase();
MethodDefinition getter = new MethodDefinition(type,
getterName, Collections.<Field> emptyList(),
Lists.newArrayList(overrideAnnotation), "return "
- + varName + ";");
+ + varName + ";");
+
+ methods.add(getter);
String setterName = "set"
+ attributeIfc.getUpperCaseCammelCase();
annotations, setterBody);
setter.setJavadoc(attributeIfc.getNullableDescription());
- methods.add(getter);
methods.add(setter);
}
}
}
+
+ private static boolean needsDepResolver(AttributeIfc value) {
+ if(value instanceof TOAttribute)
+ return true;
+ if(value instanceof ListAttribute) {
+ AttributeIfc innerAttribute = ((ListAttribute) value).getInnerAttribute();
+ return needsDepResolver(innerAttribute);
+ }
+
+ return false;
+ }
+
+ private static String getInnerTypeFromIdentity(Type type) {
+ Preconditions.checkArgument(type instanceof ParameterizedType);
+ Type[] args = ((ParameterizedType) type).getActualTypeArguments();
+ Preconditions.checkArgument(args.length ==1);
+ return serializeType(args[0]);
+ }
}
private final String name;
private final String definition;
private final List<String> modifiers;
+ private final boolean needsDepResolver;
public Field(String type, String name) {
- this(Lists.<String> newArrayList(), type, name, null);
+ this(Lists.<String> newArrayList(), type, name, null, false);
}
public Field(String type, String name, String definition) {
- this(Lists.<String> newArrayList(), type, name, definition);
+ this(Lists.<String> newArrayList(), type, name, definition, false);
}
public Field(List<String> modifiers, String type, String name) {
- this(modifiers, type, name, null);
+ this(modifiers, type, name, null, false);
}
public Field(List<String> modifiers, String type, String name,
String definition) {
+ this(modifiers, type, name, definition, false);
+ }
+
+ public Field(List<String> modifiers, String type, String name,
+ String definition, boolean needsDepResolver) {
this.modifiers = modifiers;
this.type = type;
this.name = name;
this.definition = definition;
+ this.needsDepResolver = needsDepResolver;
+ }
+
+ public Field(String type, String name, String definition, boolean needsDepResolver) {
+ this(Lists.<String> newArrayList(), type, name, definition, needsDepResolver);
+ }
+
+ public boolean isNeedsDepResolver() {
+ return needsDepResolver;
}
public String getType() {
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.controller.config.yangjmxgenerator.plugin.ftl.model;
+
+import org.opendaylight.controller.config.api.IdentityAttributeRef;
+
+public class IdentityRefModuleField extends ModuleField {
+
+ public static final String IDENTITY_CLASS_FIELD_SUFFIX = "IdentityClass";
+ private final String identityBaseClass;
+
+ public IdentityRefModuleField(String type, String name, String attributeName, String identityBaseClass) {
+ super(type, name, attributeName, null, false, null, false, false);
+ this.identityBaseClass = identityBaseClass;
+ }
+
+ public String getIdentityBaseClass() {
+ return identityBaseClass;
+ }
+
+ @Override
+ public boolean isIdentityRef() {
+ return true;
+ }
+
+ public String getType() {
+ return IdentityAttributeRef.class.getName();
+ }
+
+ public String getIdentityClassType() {
+ return super.getType();
+ }
+
+ public String getIdentityClassName() {
+ return addIdentityClassFieldSuffix(getName());
+ }
+
+ public static String addIdentityClassFieldSuffix(String prefix) {
+ return prefix + IDENTITY_CLASS_FIELD_SUFFIX;
+ }
+}
private final boolean dependent, isListOfDependencies;
private final Dependency dependency;
- private ModuleField(List<String> modifiers, String type, String name,
- String attributeName, String nullableDefault, boolean isDependency,
- Dependency dependency, boolean isListOfDependencies) {
- super(modifiers, type, name);
+ private ModuleField(List<String> modifiers, String type, String name, String attributeName, String nullableDefault,
+ boolean isDependency, Dependency dependency, boolean isListOfDependencies, boolean needsDepResolver) {
+ super(modifiers, type, name, null, needsDepResolver);
this.dependent = isDependency;
this.dependency = dependency;
this.attributeName = attributeName;
this.isListOfDependencies = isListOfDependencies;
}
- public ModuleField(String type, String name, String attributeName,
- String nullableDefault, boolean isDependency, Dependency dependency, boolean isListOfDependencies) {
- this(Collections.<String> emptyList(), type, name, attributeName,
- nullableDefault, isDependency, dependency, isListOfDependencies);
+ public ModuleField(String type, String name, String attributeName, String nullableDefault, boolean isDependency,
+ Dependency dependency, boolean isListOfDependencies, boolean needsDepResolve) {
+ this(Collections.<String> emptyList(), type, name, attributeName, nullableDefault, isDependency, dependency,
+ isListOfDependencies, needsDepResolve);
+ }
+
+ public boolean isIdentityRef() {
+ return false;
}
public Dependency getDependency() {
</#if>
</#list>
+ // caches of resolved IdentityRefs
+ <#list moduleFields as field>
+ <#if field.identityRef==true>
+ private ${field.identityClassType} ${field.identityClassName};
+ </#if>
+ </#list>
@Override
public final ${instanceType} getInstance(){
}
</#if>
</#if>
+
+ <#if field.needsDepResolver==true>
+ if(${field.name} != null) {
+ <#if field.type?starts_with("java.util.List")>
+ for(${field.type?substring(field.type?index_of("<") + 1, field.type?index_of(">"))} candidate : ${field.name}) {
+ candidate.injectDependencyResolver(dependencyResolver);
+ }
+ <#else>
+ ${field.name}.injectDependencyResolver(dependencyResolver);
+ </#if>
+ }
+ </#if>
+
+ <#if field.identityRef==true>
+ if(${field.name} != null) {
+ set${field.attributeName}(${field.name}.resolveIdentity(dependencyResolver, ${field.identityBaseClass}.class));
+ }
+ </#if>
</#list>
if(oldInstance!=null && canReuseInstance(oldModule)) {
is(true));
assertThat(peerTO.getFullyQualifiedName(), is(PACKAGE_NAME
+ ".Peer"));
- assertThat(peerTO.getMethods().size(), is(4));
+ assertThat(peerTO.getMethods().size(), is(5));
Method getPort = findFirstMethodByName(peerTO.getMethods(),
"getPort");
assertNotNull(getPort);
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>config-api</artifactId>
- <scope>test</scope>
</dependency>
<dependency>
<groupId>org.opendaylight.yangtools</groupId>
package org.opendaylight.controller.config.yangjmxgenerator.attribute;
import com.google.common.base.Preconditions;
+import org.opendaylight.controller.config.api.IdentityAttributeRef;
import org.opendaylight.controller.config.yangjmxgenerator.TypeProviderWrapper;
import org.opendaylight.yangtools.sal.binding.model.api.Type;
import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
import javax.management.openmbean.ArrayType;
TypeProviderWrapper typeProviderWrapper) {
super(leaf);
this.type = typeProviderWrapper.getType(leaf);
+
this.typeDefinition = leaf.getType();
this.typeProviderWrapper = typeProviderWrapper;
this.nullableDefault = leaf.getDefault();
return getCompositeTypeForUnion(baseTypeDefinition);
} else if (isDerivedType(baseType, getType())) {
return getCompositeType(baseType, baseTypeDefinition);
+ } else if (isIdentityRef()) {
+ return getCompositeTypeForIdentity();
}
return getSimpleType(getType());
}
+ public boolean isIdentityRef() {
+ return typeDefinition instanceof IdentityrefTypeDefinition;
+ }
+
private OpenType<?> getCompositeTypeForUnion(TypeDefinition<?> baseTypeDefinition) {
Preconditions.checkArgument(baseTypeDefinition instanceof UnionTypeDefinition,
"Expected %s instance but was %s", UnionTypeDefinition.class, baseTypeDefinition);
}
}
+ public OpenType<?> getCompositeTypeForIdentity() {
+ String[] itemNames = new String[]{IdentityAttributeRef.QNAME_ATTR_NAME};
+ String description = getNullableDescription() == null ? getAttributeYangName() : getNullableDescription();
+ OpenType<?>[] itemTypes = new OpenType[]{SimpleType.STRING};
+
+ try {
+ return new CompositeType(getUpperCaseCammelCase(), description, itemNames, itemNames, itemTypes);
+ } catch (OpenDataException e) {
+ throw new RuntimeException("Unable to create " + CompositeType.class + " with inner element of type "
+ + itemTypes, e);
+ }
+ }
+
private OpenType<?> getArrayType() {
String innerTypeFullyQName = getInnerType(getType());
SimpleType<?> innerSimpleType = SimpleTypeResolver.getSimpleType(innerTypeFullyQName);
}
private boolean isDerivedType(Type baseType, Type currentType) {
- return baseType.equals(currentType) == false;
+ return baseType.equals(currentType) == false;
}
private static String getInnerType(Type type) {
</parent>
<artifactId>yang-test</artifactId>
+ <packaging>bundle</packaging>
<description>Artifact that contains only generated code from yang files. Suitable for testing.
</description>
</execution>
</executions>
</plugin>
+
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ </instructions>
+ </configuration>
+ </plugin>
</plugins>
</build>
</project>
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.config.yang.test.impl;
+
+/**
+*
+*/
+public final class IdentityTestModule extends org.opendaylight.controller.config.yang.test.impl.AbstractIdentityTestModule
+ {
+
+ public IdentityTestModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver) {
+ super(identifier, dependencyResolver);
+ }
+
+ public IdentityTestModule(org.opendaylight.controller.config.api.ModuleIdentifier identifier, org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,
+ IdentityTestModule oldModule, java.lang.AutoCloseable oldInstance) {
+
+ super(identifier, dependencyResolver, oldModule, oldInstance);
+ }
+
+ @Override
+ protected void customValidation(){
+ // Add custom validation for module attributes here.
+ }
+
+ @Override
+ public java.lang.AutoCloseable createInstance() {
+ System.err.println(getAfi());
+ System.err.println(getAfiIdentity());
+
+ getAfiIdentity();
+ for (Identities identities : getIdentities()) {
+ identities.resolveAfi();
+ identities.resolveSafi();
+ }
+ getIdentitiesContainer().resolveAfi();
+
+ return new AutoCloseable() {
+ @Override
+ public void close() throws Exception {
+ }
+ };
+
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.config.yang.test.impl;
+
+/**
+*
+*/
+public class IdentityTestModuleFactory extends org.opendaylight.controller.config.yang.test.impl.AbstractIdentityTestModuleFactory
+{
+
+
+}
--- /dev/null
+ System.err.println(getAfi());
+ System.err.println(getAfiIdentity());
+
+ getAfiIdentity();
+ for (Identities identities : getIdentities()) {
+ identities.resolveAfi();
+ identities.resolveSafi();
+ }
+ getIdentitiesContainer().resolveAfi();
+
+ return new AutoCloseable() {
+ @Override
+ public void close() throws Exception {
+ }
+ };
config:java-name-prefix NetconfTestImpl;
}
+ identity impl-identity-test {
+ base config:module-type;
+ config:provided-service test:testing;
+ config:java-name-prefix IdentityTest;
+ }
+
+ identity test-identity1 {
+
+ }
+
+ identity test-identity2 {
+ base test-identity1;
+ }
+
+ augment "/config:modules/config:module/config:configuration" {
+ case impl-identity-test {
+ when "/config:modules/config:module/config:type = 'impl-identity-test'";
+
+ leaf afi {
+ type identityref {
+ base test-identity1;
+ }
+ }
+
+ container identities-container {
+ leaf afi {
+ type identityref {
+ base test-identity1;
+ }
+ }
+ }
+
+ list identities {
+ leaf afi {
+ type identityref {
+ base test-identity1;
+ }
+ }
+ leaf safi {
+ type identityref {
+ base test-identity1;
+ }
+ }
+
+ container identities-inner {
+ leaf afi {
+ type identityref {
+ base test-identity1;
+ }
+ }
+ }
+ }
+
+ }
+ }
+
+ augment "/config:modules/config:module/config:state" {
+ case impl-identity-test {
+ when "/config:modules/config:module/config:type = 'impl-identity-test'";
+
+ }
+ }
+
augment "/config:modules/config:module/config:configuration" {
case impl {
package org.opendaylight.controller.config.yang.test.impl;
import com.google.common.collect.Lists;
+
import junit.framework.Assert;
+
import org.junit.Before;
import org.junit.Test;
+import org.opendaylight.controller.config.api.IdentityAttributeRef;
import org.opendaylight.controller.config.api.jmx.CommitStatus;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.test.impl.rev130403.TestIdentity1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.test.impl.rev130403.TestIdentity2;
+import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
+import org.opendaylight.yangtools.yang.data.impl.codec.IdentityCodec;
import javax.management.InstanceAlreadyExistsException;
import javax.management.ObjectName;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
public class NetconfTestImplModuleTest extends AbstractConfigTest {
factory = new NetconfTestImplModuleFactory();
super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory,
- new DepTestImplModuleFactory()));
+ new DepTestImplModuleFactory(), new IdentityTestModuleFactory()));
+ }
+
+ @Override
+ protected CodecRegistry getCodecRegistry() {
+ final IdentityCodec<?> codec = mock(IdentityCodec.class);
+ doReturn(TestIdentity1.class).when(codec).deserialize(TestIdentity1.QNAME);
+ doReturn(TestIdentity2.class).when(codec).deserialize(TestIdentity2.QNAME);
+
+ final CodecRegistry ret = super.getCodecRegistry();
+ doReturn(codec).when(ret).getIdentityCodec();
+ return ret;
+ }
+
+ @Test
+ public void testIdentities() throws Exception {
+ ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+
+ ObjectName nameCreated = transaction.createModule(IdentityTestModuleFactory.NAME, instanceName);
+ IdentityTestModuleMXBean mxBean = transaction.newMXBeanProxy(nameCreated, IdentityTestModuleMXBean.class);
+
+ final IdentitiesContainer c = new IdentitiesContainer();
+ c.setAfi(new IdentityAttributeRef(TestIdentity2.QNAME.toString()));
+ mxBean.setIdentitiesContainer(c);
+ transaction.commit();
}
@Test
return caseJavaBinaryAttribute(openType);
} else if(((JavaAttribute)attributeIfc).isUnion()) {
return caseJavaUnionAttribute(openType);
+ } else if(((JavaAttribute)attributeIfc).isIdentityRef()) {
+ return caseJavaIdentityRefAttribute(openType);
} else
return caseJavaAttribute(openType);
} catch (UnknownOpenTypeException e) {
throw getIllegalArgumentException(attributeIfc);
}
+ protected T caseJavaIdentityRefAttribute(OpenType<?> openType) {
+ return caseJavaAttribute(openType);
+ }
+
protected T caseJavaUnionAttribute(OpenType<?> openType) {
return caseJavaAttribute(openType);
}
import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListDependenciesAttribute;
import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.AttributeIfcSwitchStatement;
+import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
import javax.management.openmbean.ArrayType;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
+import java.util.Date;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Set;
public class ObjectXmlReader extends AttributeIfcSwitchStatement<AttributeReadingStrategy> {
private String key;
+ private Map<String, Map<Date, EditConfig.IdentityMapping>> identityMap;
- public Map<String, AttributeReadingStrategy> prepareReading(Map<String, AttributeIfc> yangToAttrConfig) {
+ public Map<String, AttributeReadingStrategy> prepareReading(Map<String, AttributeIfc> yangToAttrConfig, Map<String, Map<Date,EditConfig.IdentityMapping>> identityMap) {
Map<String, AttributeReadingStrategy> strategies = Maps.newHashMap();
+ this.identityMap = identityMap;
for (Entry<String, AttributeIfc> attributeEntry : yangToAttrConfig.entrySet()) {
AttributeReadingStrategy strat = prepareReadingStrategy(attributeEntry.getKey(), attributeEntry.getValue());
return new SimpleCompositeAttributeReadingStrategy(lastAttribute.getNullableDefault(), mappingKey);
}
+ @Override
+ protected AttributeReadingStrategy caseJavaIdentityRefAttribute(OpenType<?> openType) {
+ Preconditions.checkState(openType instanceof CompositeType);
+ Set<String> keys = ((CompositeType) openType).keySet();
+ Preconditions.checkState(keys.size() == 1, "Unexpected number of elements for open type %s, should be 1", openType);
+ String mappingKey = keys.iterator().next();
+ return new SimpleIdentityRefAttributeReadingStrategy(lastAttribute.getNullableDefault(), mappingKey, identityMap);
+ }
+
@Override
protected AttributeReadingStrategy caseDependencyAttribute(SimpleType<?> openType) {
return new ObjectNameAttributeReadingStrategy(lastAttribute.getNullableDefault());
String textContent = "";
try{
- textContent = xmlElement.getTextContent();
+ textContent = readElementContent(xmlElement);
}catch(IllegalStateException | NullPointerException e) {
// yuma sends <attribute /> for empty value instead of <attribute></attribute>
logger.warn("Ignoring exception caused by failure to read text element", e);
postprocessParsedValue(textContent));
}
+ protected String readElementContent(XmlElement xmlElement) {
+ return xmlElement.getTextContent();
+ }
+
@Override
protected Object postprocessNullableDefault(String nullableDefault) {
return nullableDefault;
super(nullableDefault);
}
+ @Override
protected Object postprocessParsedValue(String textContent) {
BaseEncoding en = BaseEncoding.base64();
byte[] decode = en.decode(textContent);
this.key = key;
}
+ @Override
protected Object postprocessParsedValue(String textContent) {
HashMap<String,String> map = Maps.newHashMap();
map.put(key, textContent);
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml;
+
+import java.net.URI;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
+import org.opendaylight.controller.netconf.util.xml.XmlElement;
+import org.opendaylight.yangtools.yang.common.QName;
+
+
+public class SimpleIdentityRefAttributeReadingStrategy extends SimpleAttributeReadingStrategy {
+
+ private final String key;
+ private final Map<String, Map<Date, EditConfig.IdentityMapping>> identityMap;
+
+ public SimpleIdentityRefAttributeReadingStrategy(String nullableDefault, String key, Map<String, Map<Date,EditConfig.IdentityMapping>> identityMap) {
+ super(nullableDefault);
+ this.key = key;
+ this.identityMap = identityMap;
+ }
+
+ @Override
+ protected String readElementContent(XmlElement xmlElement) {
+ // TODO test
+ Map.Entry<String, String> namespaceOfTextContent = xmlElement.findNamespaceOfTextContent();
+ String content = xmlElement.getTextContent();
+
+ String prefix = namespaceOfTextContent.getKey() + ":";
+ Preconditions.checkArgument(content.startsWith(prefix), "Identity ref should be prefixed");
+
+ String localName = content.substring(prefix.length());
+ String namespace = namespaceOfTextContent.getValue();
+
+ Date revision = null;
+ Map<Date, EditConfig.IdentityMapping> revisions = identityMap.get(namespace);
+ if(revisions.keySet().size() > 1) {
+ for (Date date : revisions.keySet()) {
+ if(revisions.get(date).containsIdName(localName)) {
+ Preconditions.checkState(revision == null, "Duplicate identity %s, in namespace %s, with revisions: %s, %s detected. Cannot map attribute",
+ localName, namespace, revision, date);
+ revision = date;
+ }
+ }
+ } else
+ revision = revisions.keySet().iterator().next();
+
+
+ return QName.create(URI.create(namespace), revision, localName).toString();
+ }
+
+ @Override
+ protected Object postprocessParsedValue(String textContent) {
+ HashMap<String,String> map = Maps.newHashMap();
+ map.put(key, textContent);
+ return map;
+ }
+
+ @Override
+ protected Object postprocessNullableDefault(String nullableDefault) {
+ return nullableDefault == null ? null : postprocessParsedValue(nullableDefault);
+ }
+}
this.key = key;
}
+ @Override
protected Object postprocessParsedValue(String textContent) {
char[] charArray = textContent.toCharArray();
List<String> chars = Lists.newArrayListWithCapacity(charArray.length);
return new ArrayAttributeWritingStrategy(innerStrategy);
}
+ @Override
+ protected AttributeWritingStrategy caseJavaIdentityRefAttribute(OpenType<?> openType) {
+ return new SimpleIdentityRefAttributeWritingStrategy(document, key);
+ }
+
@Override
protected AttributeWritingStrategy caseJavaCompositeAttribute(CompositeType openType) {
return new SimpleCompositeAttributeWritingStrategy(document, key);
public void writeElement(Element parentElement, String namespace, Object value) {
value = preprocess(value);
Util.checkType(value, String.class);
- Element innerNode = XmlUtil.createTextElement(document, key, (String) value);
+ Element innerNode = createElement(document, key, (String) value);
XmlUtil.addNamespaceAttr(innerNode, namespace);
parentElement.appendChild(innerNode);
}
+ protected Element createElement(Document document, String key, String value) {
+ return XmlUtil.createTextElement(document, key, (String) value);
+ }
+
protected Object preprocess(Object value) {
return value;
}
--- /dev/null
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.toxml;
+
+import java.util.Map;
+
+import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
+import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.w3c.dom.Document;
+
+import com.google.common.base.Preconditions;
+import org.w3c.dom.Element;
+
+public class SimpleIdentityRefAttributeWritingStrategy extends SimpleAttributeWritingStrategy {
+
+ private static final char QNAME_SEPARATOR = ':';
+ private static final String PREFIX = "prefix";
+
+ /**
+ * @param document
+ * @param key
+ */
+ public SimpleIdentityRefAttributeWritingStrategy(Document document, String key) {
+ super(document, key);
+ }
+
+ protected Object preprocess(Object value) {
+ Util.checkType(value, Map.class);
+ Preconditions.checkArgument(((Map)value).size() == 1, "Unexpected number of values in %s, expected 1", value);
+ Object stringValue = ((Map) value).values().iterator().next();
+ Util.checkType(stringValue, String.class);
+
+ return stringValue;
+ }
+
+ @Override
+ protected Element createElement(Document doc, String key, String value) {
+ QName qName = QName.create(value);
+ String identity = qName.getLocalName();
+ Element element = XmlUtil.createPrefixedTextElement(doc, key, PREFIX, identity);
+
+ String identityNamespace = qName.getNamespace().toString();
+ XmlUtil.addPrefixedNamespaceAttr(element, PREFIX, identityNamespace);
+ return element;
+ }
+}
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import javax.management.ObjectName;
import java.util.Collection;
import java.util.Collections;
+import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Map<String /* Name of module entry from yang file */, ModuleConfig>> moduleConfigs;
private final Map<String, ModuleConfig> moduleNamesToConfigs;
+ private final Map<String, Map<Date, EditConfig.IdentityMapping>> identityMap;
+
public Config(Map<String, Map<String, ModuleConfig>> moduleConfigs) {
+ this(moduleConfigs, Collections.<String, Map<Date, EditConfig.IdentityMapping>>emptyMap());
+ }
+
+ public Config(Map<String, Map<String, ModuleConfig>> moduleConfigs, Map<String, Map<Date,EditConfig.IdentityMapping>> identityMap) {
this.moduleConfigs = moduleConfigs;
Map<String, ModuleConfig> moduleNamesToConfigs = new HashMap<>();
for (Entry<String, Map<String, ModuleConfig>> entry : moduleConfigs.entrySet()) {
moduleNamesToConfigs.putAll(entry.getValue());
}
this.moduleNamesToConfigs = Collections.unmodifiableMap(moduleNamesToConfigs);
+ this.identityMap = identityMap;
}
public static Map<String, Map<String, Collection<ObjectName>>> getMappedInstances(Set<ObjectName> instancesToMap,
@Override
public ModuleElementResolved resolveElement(ModuleConfig moduleMapping, XmlElement moduleElement, ServiceRegistryWrapper serviceTracker, String instanceName, String moduleNamespace, EditStrategyType defaultStrategy) {
return moduleMapping.fromXml(moduleElement, serviceTracker,
- instanceName, moduleNamespace, defaultStrategy);
+ instanceName, moduleNamespace, defaultStrategy, identityMap);
}
};
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.resolving.ObjectResolver;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.toxml.AttributeWritingStrategy;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.toxml.ObjectXmlWriter;
+import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import javax.management.ObjectName;
import javax.management.openmbean.OpenType;
+import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
}
public InstanceConfigElementResolved fromXml(XmlElement moduleElement, ServiceRegistryWrapper services, String moduleNamespace,
- EditStrategyType defaultStrategy, Multimap<String, String> providedServices) {
+ EditStrategyType defaultStrategy, Multimap<String, String> providedServices, Map<String, Map<Date,EditConfig.IdentityMapping>> identityMap) {
Map<String, AttributeConfigElement> retVal = Maps.newHashMap();
- Map<String, AttributeReadingStrategy> strats = new ObjectXmlReader().prepareReading(yangToAttrConfig);
+ Map<String, AttributeReadingStrategy> strats = new ObjectXmlReader().prepareReading(yangToAttrConfig, identityMap);
List<XmlElement> recognisedChildren = Lists.newArrayList();
XmlElement type = moduleElement.getOnlyChildElementWithSameNamespace(XmlNetconfConstants.TYPE_KEY);
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
+import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import javax.management.ObjectName;
import java.util.Collection;
+import java.util.Date;
+import java.util.Map;
public class ModuleConfig {
}
public ModuleElementResolved fromXml(XmlElement moduleElement, ServiceRegistryWrapper depTracker, String instanceName,
- String moduleNamespace, EditStrategyType defaultStrategy) {
+ String moduleNamespace, EditStrategyType defaultStrategy, Map<String, Map<Date,EditConfig.IdentityMapping>> identityMap) {
- InstanceConfigElementResolved ice = instanceConfig.fromXml(moduleElement, depTracker, moduleNamespace, defaultStrategy, providedServices);
+ InstanceConfigElementResolved ice = instanceConfig.fromXml(moduleElement, depTracker, moduleNamespace, defaultStrategy, providedServices, identityMap);
return new ModuleElementResolved(instanceName, ice);
}
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.opendaylight.controller.config.api.ServiceReferenceReadableRegistry;
+import org.opendaylight.yangtools.yang.common.QName;
import javax.management.InstanceNotFoundException;
import javax.management.ObjectName;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
public class ServiceRegistryWrapper {
ObjectName on = serviceMapping.get(serviceQName).get(refName);
Services.ServiceInstance si = Services.ServiceInstance.fromObjectName(on);
- // FIXME use QName's new String constructor, after it is fixed
-// QName qname;
-// try {
-// qname = new QName(serviceQName);
-// } catch (ParseException e) {
-// throw new IllegalStateException("Unable to parse qname of a service " + serviceQName, e);
-// }
- Pattern p = Pattern.compile("\\(([^\\(\\?]+)\\?[^\\?\\)]*\\)([^\\)]+)");
- Matcher matcher = p.matcher(serviceQName);
- Preconditions.checkArgument(matcher.matches());
- String namespace = matcher.group(1);
- String localName = matcher.group(2);
-
-// String namespace = qname.getNamespace().toString();
+ QName qname = QName.create(serviceQName);
+ String namespace = qname.getNamespace().toString();
Map<String, Map<String, String>> serviceToRefs = retVal.get(namespace);
if(serviceToRefs==null) {
serviceToRefs = Maps.newHashMap();
retVal.put(namespace, serviceToRefs);
}
-// String localName = qname.getLocalName();
+ String localName = qname.getLocalName();
Map<String, String> refsToSis = serviceToRefs.get(localName);
if(refsToSis==null) {
refsToSis = Maps.newHashMap();
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.fromxml.ObjectXmlReader;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.resolving.AttributeResolvingStrategy;
import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.resolving.ObjectResolver;
+import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import javax.management.openmbean.OpenType;
+import java.util.Collections;
+import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public Map<String, AttributeConfigElement> fromXml(XmlElement configRootNode) {
Map<String, AttributeConfigElement> retVal = Maps.newHashMap();
- Map<String, AttributeReadingStrategy> strats = new ObjectXmlReader().prepareReading(yangToAttrConfig);
+ // FIXME add identity map to runtime data
+ Map<String, AttributeReadingStrategy> strats = new ObjectXmlReader().prepareReading(yangToAttrConfig,
+ Collections.<String, Map<Date, EditConfig.IdentityMapping>> emptyMap());
for (Entry<String, AttributeReadingStrategy> readStratEntry : strats.entrySet()) {
List<XmlElement> configNodes = configRootNode.getChildElements(readStratEntry.getKey());
package org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig;
import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import org.opendaylight.controller.config.api.JmxAttributeValidationException;
import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
+import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import javax.management.InstanceNotFoundException;
import javax.management.ObjectName;
+import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Set;
public class EditConfig extends AbstractConfigNetconfOperation {
}
}
- public static Config getConfigMapping(ConfigRegistryClient configRegistryClient,
- Map<String/* Namespace from yang file */,
- Map<String /* Name of module entry from yang file */, ModuleMXBeanEntry>> mBeanEntries) {
- Map<String, Map<String, ModuleConfig>> factories = transformMbeToModuleConfigs(configRegistryClient, mBeanEntries);
+ public static Config getConfigMapping(ConfigRegistryClient configRegistryClient, YangStoreSnapshot yangStoreSnapshot) {
+ Map<String, Map<String, ModuleConfig>> factories = transformMbeToModuleConfigs(configRegistryClient,
+ yangStoreSnapshot.getModuleMXBeanEntryMap());
+ Map<String, Map<Date, IdentityMapping>> identitiesMap = transformIdentities(yangStoreSnapshot.getModules());
+ return new Config(factories, identitiesMap);
+ }
+
+
+ public static class IdentityMapping {
+ private final Map<String, IdentitySchemaNode> identityNameToSchemaNode;
+
+ IdentityMapping() {
+ this.identityNameToSchemaNode = Maps.newHashMap();
+ }
- return new Config(factories);
+ void addIdSchemaNode(IdentitySchemaNode node) {
+ String name = node.getQName().getLocalName();
+ Preconditions.checkState(identityNameToSchemaNode.containsKey(name) == false);
+ identityNameToSchemaNode.put(name, node);
+ }
+
+ public boolean containsIdName(String idName) {
+ return identityNameToSchemaNode.containsKey(idName);
+ }
+
+ public IdentitySchemaNode getIdentitySchemaNode(String idName) {
+ Preconditions.checkState(identityNameToSchemaNode.containsKey(idName), "No identity under name %s", idName);
+ return identityNameToSchemaNode.get(idName);
+ }
+ }
+
+ private static Map<String, Map<Date, IdentityMapping>> transformIdentities(Set<Module> modules) {
+ Map<String, Map<Date, IdentityMapping>> mappedIds = Maps.newHashMap();
+ for (Module module : modules) {
+ String namespace = module.getNamespace().toString();
+ Map<Date, IdentityMapping> revisionsByNamespace= mappedIds.get(namespace);
+ if(revisionsByNamespace == null) {
+ revisionsByNamespace = Maps.newHashMap();
+ mappedIds.put(namespace, revisionsByNamespace);
+ }
+
+ Date revision = module.getRevision();
+ Preconditions.checkState(revisionsByNamespace.containsKey(revision) == false,
+ "Duplicate revision %s for namespace %s", revision, namespace);
+
+ IdentityMapping identityMapping = revisionsByNamespace.get(revision);
+ if(identityMapping == null) {
+ identityMapping = new IdentityMapping();
+ revisionsByNamespace.put(revision, identityMapping);
+ }
+
+ for (IdentitySchemaNode identitySchemaNode : module.getIdentities()) {
+ identityMapping.addIdSchemaNode(identitySchemaNode);
+ }
+
+ }
+
+ return mappedIds;
}
public static Map<String/* Namespace from yang file */,
protected Element handle(Document document, XmlElement xml) throws NetconfDocumentedException {
EditConfigXmlParser.EditConfigExecution editConfigExecution;
- Config cfg = getConfigMapping(configRegistryClient, yangStoreSnapshot.getModuleMXBeanEntryMap());
+ Config cfg = getConfigMapping(configRegistryClient, yangStoreSnapshot);
try {
editConfigExecution = editConfigXmlParser.fromXml(xml, cfg, transactionProvider, configRegistryClient);
} catch (IllegalStateException e) {
return getResponseInternal(document, editConfigExecution);
}
+
}
package org.opendaylight.controller.netconf.confignetconfconnector;
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Sets;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.math.BigInteger;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
+import javax.xml.parsers.ParserConfigurationException;
+
import org.apache.commons.lang3.StringUtils;
import org.junit.Before;
import org.junit.Ignore;
import org.opendaylight.controller.config.yang.test.impl.DtoAInnerInner;
import org.opendaylight.controller.config.yang.test.impl.DtoC;
import org.opendaylight.controller.config.yang.test.impl.DtoD;
+import org.opendaylight.controller.config.yang.test.impl.IdentityTestModuleFactory;
import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleFactory;
import org.opendaylight.controller.config.yang.test.impl.NetconfTestImplModuleMXBean;
import org.opendaylight.controller.config.yang.test.impl.Peers;
import org.opendaylight.controller.netconf.util.xml.XmlElement;
import org.opendaylight.controller.netconf.util.xml.XmlNetconfConstants;
import org.opendaylight.controller.netconf.util.xml.XmlUtil;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.test.impl.rev130403.TestIdentity1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.test.impl.rev130403.TestIdentity2;
+import org.opendaylight.yangtools.yang.data.impl.codec.CodecRegistry;
+import org.opendaylight.yangtools.yang.data.impl.codec.IdentityCodec;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
-import javax.management.InstanceAlreadyExistsException;
-import javax.management.InstanceNotFoundException;
-import javax.management.ObjectName;
-import javax.xml.parsers.ParserConfigurationException;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-import java.net.URISyntaxException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
public class NetconfMappingTest extends AbstractConfigTest {
private static final String NETCONF_SESSION_ID = "foo";
private NetconfTestImplModuleFactory factory;
private DepTestImplModuleFactory factory2;
+ private IdentityTestModuleFactory factory3;
@Mock
YangStoreSnapshot yangStoreSnapshot;
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
doReturn(getMbes()).when(this.yangStoreSnapshot).getModuleMXBeanEntryMap();
+ doReturn(getModules()).when(this.yangStoreSnapshot).getModules();
+
this.factory = new NetconfTestImplModuleFactory();
this.factory2 = new DepTestImplModuleFactory();
- super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(this.factory, this.factory2));
+ this.factory3 = new IdentityTestModuleFactory();
+ super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(this.factory, this.factory2,
+ this.factory3));
transactionProvider = new TransactionProvider(this.configRegistryClient, NETCONF_SESSION_ID);
}
return on;
}
+ @Test
+ public void testIdentityRefs() throws Exception {
+ edit("netconfMessages/editConfig_identities.xml");
+
+ commit();
+ getConfigRunning();
+ }
+
+ @Override
+ protected CodecRegistry getCodecRegistry() {
+ IdentityCodec<?> idCodec = mock(IdentityCodec.class);
+ doReturn(TestIdentity1.class).when(idCodec).deserialize(TestIdentity1.QNAME);
+ doReturn(TestIdentity2.class).when(idCodec).deserialize(TestIdentity2.QNAME);
+
+ CodecRegistry codecReg = super.getCodecRegistry();
+ doReturn(idCodec).when(codecReg).getIdentityCodec();
+ return codecReg;
+ }
+
@Test
public void testServicePersistance() throws Exception {
createModule(INSTANCE_NAME);
edit("netconfMessages/editConfig.xml");
Element configCandidate = getConfigCandidate();
- System.err.println(XmlUtil.toString(configCandidate));
checkBinaryLeafEdited(configCandidate);
return mBeanEntries;
}
+ private Set<org.opendaylight.yangtools.yang.model.api.Module> getModules() throws Exception {
+ SchemaContext resolveSchemaContext = getSchemaContext();
+ return resolveSchemaContext.getModules();
+ }
+
+ private SchemaContext getSchemaContext() throws Exception {
+ final List<InputStream> yangDependencies = getYangs();
+ YangParserImpl parser = new YangParserImpl();
+
+ Set<Module> allYangModules = parser.parseYangModelsFromStreams(yangDependencies);
+
+ return parser.resolveSchemaContext(Sets
+ .newHashSet(allYangModules));
+ }
+
@Test
public void testConfigNetconfRuntime() throws Exception {
root.setAttribute(concat(XMLNS_ATTRIBUTE_KEY, prefix), namespace);
}
- public static Element createPrefixedTextElement(Document document, String key, String prefix, String moduleName) {
- return createTextElement(document, key, concat(prefix, moduleName));
+ public static Element createPrefixedTextElement(Document document, String key, String prefix, String content) {
+ return createTextElement(document, key, concat(prefix, content));
}
private static String concat(String prefix, String value) {
--- /dev/null
+<rpc message-id="a" a="64" xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <edit-config>
+ <target>
+ <candidate/>
+ </target>
+ <test-option>
+ set
+ </test-option>
+ <default-operation>merge</default-operation>
+ <config>
+ <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+ <module>
+ <type xmlns:test-impl="urn:opendaylight:params:xml:ns:yang:controller:test:impl">
+ test-impl:impl-identity-test
+ </type>
+ <name>id-test</name>
+ <identities>
+ <afi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test:impl">prefix:test-identity1</afi>
+ <safi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test:impl">prefix:test-identity2</safi>
+ </identities>
+ <identities>
+ <afi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test:impl">prefix:test-identity2</afi>
+ <safi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test:impl">prefix:test-identity1</safi>
+ </identities>
+ <identities-container>
+ <afi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test:impl">prefix:test-identity2</afi>
+ </identities-container>
+ <afi xmlns:prefix="urn:opendaylight:params:xml:ns:yang:controller:test:impl">prefix:test-identity1</afi>
+ </module>
+ </modules>
+
+ <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+
+ </services>
+ </config>
+ </edit-config>
+</rpc>