From cd50f92c60580b546a696aab7c3ff4fbf3f9a5f0 Mon Sep 17 00:00:00 2001 From: Maros Marsalek Date: Mon, 11 May 2015 16:53:19 +0200 Subject: [PATCH] BUG-2453 (De)Serialize enum values as defined in yang Netconf endpoint for config subsystem did not (de)serialize enum values properly It assumed the enum constants are identical in yang and in generated binding Change-Id: If46c770a49653348201cd5d5c9303b5207048252 Signed-off-by: Maros Marsalek --- .../RefreshingSCPModuleInfoRegistry.java | 6 +- .../RefreshingSCPModuleInfoRegistryTest.java | 13 +++-- .../attribute/JavaAttribute.java | 26 +++++++-- .../attribute/SimpleTypeResolver.java | 2 - .../src/main/yang/config-test-impl.yang | 2 +- .../src/main/yang/types/test-types.yang | 4 +- .../netconf/config-netconf-connector/pom.xml | 4 ++ .../AttributeIfcSwitchStatement.java | 6 ++ .../mapping/EnumAttributeMappingStrategy.java | 34 ++++++++++++ .../attributes/mapping/ObjectMapper.java | 10 +++- .../EnumAttributeResolvingStrategy.java | 55 +++++++++++++++++++ .../attributes/resolving/ObjectResolver.java | 13 ++++- .../attributes/toxml/ObjectXmlWriter.java | 5 ++ .../mapping/config/Config.java | 14 +++-- .../mapping/config/InstanceConfig.java | 17 +++--- .../mapping/config/ModuleConfig.java | 9 +-- .../mapping/rpc/InstanceRuntimeRpc.java | 7 ++- .../mapping/rpc/ModuleRpcs.java | 8 ++- .../mapping/runtime/InstanceRuntime.java | 11 ++-- .../mapping/runtime/ModuleRuntime.java | 7 ++- .../mapping/runtime/Runtime.java | 7 ++- .../operations/editconfig/EditConfig.java | 2 +- .../operations/get/Get.java | 2 +- .../operations/getconfig/GetConfig.java | 2 +- .../operations/runtimerpc/RuntimeRpc.java | 9 +-- .../osgi/Activator.java | 5 +- .../osgi/EnumResolver.java | 16 ++++++ .../osgi/YangStoreContext.java | 2 + .../osgi/YangStoreService.java | 16 +++++- .../osgi/YangStoreSnapshot.java | 31 ++++++++++- .../NetconfMappingTest.java | 33 ++++++++++- .../netconf/it/AbstractNetconfConfigTest.java | 17 ++++++ .../resources/netconfMessages/editConfig.xml | 2 +- 33 files changed, 330 insertions(+), 67 deletions(-) create mode 100644 opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/EnumAttributeMappingStrategy.java create mode 100644 opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/EnumAttributeResolvingStrategy.java create mode 100644 opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/EnumResolver.java diff --git a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/mapping/RefreshingSCPModuleInfoRegistry.java b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/mapping/RefreshingSCPModuleInfoRegistry.java index d4add50503..90b3357658 100644 --- a/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/mapping/RefreshingSCPModuleInfoRegistry.java +++ b/opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/mapping/RefreshingSCPModuleInfoRegistry.java @@ -12,6 +12,7 @@ import java.util.Hashtable; import org.opendaylight.yangtools.concepts.ObjectRegistration; import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy; import org.opendaylight.yangtools.sal.binding.generator.api.ModuleInfoRegistry; +import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext; import org.opendaylight.yangtools.yang.binding.YangModuleInfo; import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider; import org.osgi.framework.BundleContext; @@ -40,7 +41,10 @@ public class RefreshingSCPModuleInfoRegistry implements ModuleInfoRegistry, Auto private void updateService() { bindingContextProvider.update(classLoadingStrat, schemaContextProvider); - osgiReg.setProperties(null); // send modifiedService event + osgiReg.setProperties(new Hashtable() {{ + put(BindingRuntimeContext.class.getName(), bindingContextProvider.getBindingContext()); + } + }); // send modifiedService event } @Override diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/RefreshingSCPModuleInfoRegistryTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/RefreshingSCPModuleInfoRegistryTest.java index bb2d9c7927..850b45c505 100644 --- a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/RefreshingSCPModuleInfoRegistryTest.java +++ b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/RefreshingSCPModuleInfoRegistryTest.java @@ -1,5 +1,6 @@ package org.opendaylight.controller.config.manager.impl.osgi; +import static org.mockito.Matchers.any; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; @@ -13,6 +14,7 @@ import org.opendaylight.controller.config.manager.impl.osgi.mapping.RefreshingSC import org.opendaylight.yangtools.concepts.ObjectRegistration; import org.opendaylight.yangtools.sal.binding.generator.api.ClassLoadingStrategy; import org.opendaylight.yangtools.sal.binding.generator.api.ModuleInfoRegistry; +import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext; import org.opendaylight.yangtools.yang.binding.YangModuleInfo; import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider; import org.osgi.framework.BundleContext; @@ -26,16 +28,19 @@ public class RefreshingSCPModuleInfoRegistryTest { doReturn("string").when(prov).toString(); BundleContext ctxt = mock(BundleContext.class); ServiceRegistration servReg = mock(ServiceRegistration.class); - doReturn(servReg).when(ctxt).registerService(Mockito.any(Class.class), Mockito.any(SchemaContextProvider.class), Mockito.any(Dictionary.class)); - doReturn(servReg).when(ctxt).registerService(Mockito.anyString(), Mockito.any(Object.class), Mockito.any(Dictionary.class)); + doReturn(servReg).when(ctxt).registerService(any(Class.class), any(SchemaContextProvider.class), any(Dictionary.class)); + doReturn(servReg).when(ctxt).registerService(Mockito.anyString(), any(Object.class), any(Dictionary.class)); + doNothing().when(servReg).setProperties(any(Dictionary.class)); final ClassLoadingStrategy classLoadingStrat = mock(ClassLoadingStrategy.class); final BindingContextProvider codecRegistryProvider = mock(BindingContextProvider.class); doNothing().when(codecRegistryProvider).update(classLoadingStrat, prov); + final BindingRuntimeContext bindingRuntimeContext = mock(BindingRuntimeContext.class); + doReturn("B-runtime-context").when(bindingRuntimeContext).toString(); + doReturn(bindingRuntimeContext).when(codecRegistryProvider).getBindingContext(); RefreshingSCPModuleInfoRegistry scpreg = new RefreshingSCPModuleInfoRegistry(reg, prov, classLoadingStrat, codecRegistryProvider, ctxt); - doNothing().when(servReg).setProperties(null); doNothing().when(servReg).unregister(); YangModuleInfo modInfo = mock(YangModuleInfo.class); @@ -49,7 +54,7 @@ public class RefreshingSCPModuleInfoRegistryTest { scpreg.close(); - Mockito.verify(servReg, Mockito.times(1)).setProperties(null); + Mockito.verify(servReg, Mockito.times(1)).setProperties(any(Dictionary.class)); Mockito.verify(servReg, Mockito.times(1)).unregister(); } } diff --git a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/JavaAttribute.java b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/JavaAttribute.java index 6a90439bb2..d830e97678 100644 --- a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/JavaAttribute.java +++ b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/JavaAttribute.java @@ -21,6 +21,7 @@ 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.EnumTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition; import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition; @@ -60,6 +61,11 @@ public class JavaAttribute extends AbstractAttribute implements TypedAttribute { return base instanceof UnionTypeDefinition; } + public boolean isEnum() { + TypeDefinition base = getBaseType(typeProviderWrapper, typeDefinition); + return base instanceof EnumTypeDefinition; + } + public TypeDefinition getTypeDefinition() { return typeDefinition; } @@ -149,8 +155,8 @@ public class JavaAttribute extends AbstractAttribute implements TypedAttribute { if (isArray()) { return getArrayType(); - } else if (isEnum(baseType)) { - return getSimpleType(baseType); + } else if (isEnum()) { + return getEnumType(baseTypeDefinition); } else if (isUnion()) { return getCompositeTypeForUnion(baseTypeDefinition); } else if (isDerivedType(baseType, getType())) { @@ -162,6 +168,18 @@ public class JavaAttribute extends AbstractAttribute implements TypedAttribute { return getSimpleType(getType()); } + private OpenType getEnumType(final TypeDefinition baseType) { + final String fullyQualifiedName = typeProviderWrapper.getType(node, getTypeDefinition()).getFullyQualifiedName(); + final String[] items = {"instance"}; + String description = getNullableDescription() == null ? getAttributeYangName() : getNullableDescription(); + + try { + return new CompositeType(fullyQualifiedName, description, items, items, new OpenType[]{SimpleType.STRING}); + } catch (OpenDataException e) { + throw new RuntimeException("Unable to create enum type" + fullyQualifiedName + " as open type", e); + } + } + public boolean isIdentityRef() { return typeDefinition instanceof IdentityrefTypeDefinition; } @@ -223,10 +241,6 @@ public class JavaAttribute extends AbstractAttribute implements TypedAttribute { itemTypes[0] = artificialPropertyType; } - private boolean isEnum(Type baseType) { - return baseType.getFullyQualifiedName().equals(Enum.class.getName()); - } - private OpenType getSimpleType(Type type) { SimpleType simpleType = SimpleTypeResolver.getSimpleType(type); return simpleType; diff --git a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/SimpleTypeResolver.java b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/SimpleTypeResolver.java index 8454a6bb35..08aff12287 100644 --- a/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/SimpleTypeResolver.java +++ b/opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/SimpleTypeResolver.java @@ -51,7 +51,6 @@ public class SimpleTypeResolver { JAVA_TYPE_TO_SIMPLE_TYPE.put(Long.class.getName(), SimpleType.LONG); JAVA_TYPE_TO_SIMPLE_TYPE.put(long.class.getName(), SimpleType.LONG); JAVA_TYPE_TO_SIMPLE_TYPE.put(String.class.getName(), SimpleType.STRING); - JAVA_TYPE_TO_SIMPLE_TYPE.put(Enum.class.getName(), SimpleType.STRING); JAVA_TYPE_TO_SIMPLE_TYPE.put(Boolean.class.getName(), SimpleType.BOOLEAN); JAVA_TYPE_TO_SIMPLE_TYPE.put(boolean.class.getName(), SimpleType.BOOLEAN); JAVA_TYPE_TO_SIMPLE_TYPE.put(BigInteger.class.getName(), SimpleType.BIGINTEGER); @@ -61,7 +60,6 @@ public class SimpleTypeResolver { JAVA_TYPE_TO_SIMPLE_TYPE.put(Date.class.getName(), SimpleType.DATE); JAVA_TYPE_TO_SIMPLE_TYPE.put(Double.class.getName(), SimpleType.DOUBLE); JAVA_TYPE_TO_SIMPLE_TYPE.put(double.class.getName(), SimpleType.DOUBLE); - JAVA_TYPE_TO_SIMPLE_TYPE.put(char.class.getName(), SimpleType.CHARACTER); } diff --git a/opendaylight/config/yang-test/src/main/yang/config-test-impl.yang b/opendaylight/config/yang-test/src/main/yang/config-test-impl.yang index f772a26898..aff7c86fe4 100644 --- a/opendaylight/config/yang-test/src/main/yang/config-test-impl.yang +++ b/opendaylight/config/yang-test/src/main/yang/config-test-impl.yang @@ -192,7 +192,7 @@ module config-test-impl { leaf extended-enum { type tt:extend-enum; - default ONE; + default one; } leaf ip { diff --git a/opendaylight/config/yang-test/src/main/yang/types/test-types.yang b/opendaylight/config/yang-test/src/main/yang/types/test-types.yang index ee466b4034..df8cf9403c 100644 --- a/opendaylight/config/yang-test/src/main/yang/types/test-types.yang +++ b/opendaylight/config/yang-test/src/main/yang/types/test-types.yang @@ -20,8 +20,8 @@ module test-types { typedef extend-enum { type enumeration { - enum "ONE"; - enum "TWO"; + enum "one"; + enum "two"; } } diff --git a/opendaylight/netconf/config-netconf-connector/pom.xml b/opendaylight/netconf/config-netconf-connector/pom.xml index 2093ace97a..d8b2ea1c1d 100644 --- a/opendaylight/netconf/config-netconf-connector/pom.xml +++ b/opendaylight/netconf/config-netconf-connector/pom.xml @@ -53,6 +53,10 @@ org.opendaylight.yangtools mockito-configuration + + org.opendaylight.yangtools + binding-generator-impl + org.osgi org.osgi.core diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/AttributeIfcSwitchStatement.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/AttributeIfcSwitchStatement.java index 4d55119576..38c0b06de4 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/AttributeIfcSwitchStatement.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/AttributeIfcSwitchStatement.java @@ -38,6 +38,8 @@ public abstract class AttributeIfcSwitchStatement { return caseJavaUnionAttribute(openType); } else if(((JavaAttribute)attributeIfc).isIdentityRef()) { return caseJavaIdentityRefAttribute(openType); + } else if(((JavaAttribute)attributeIfc).isEnum()) { + return caseJavaEnumAttribute(openType); } else { return caseJavaAttribute(openType); } @@ -70,6 +72,10 @@ public abstract class AttributeIfcSwitchStatement { return caseJavaAttribute(openType); } + protected T caseJavaEnumAttribute(OpenType openType) { + return caseJavaAttribute(openType); + } + protected T caseJavaBinaryAttribute(OpenType openType) { return caseJavaAttribute(openType); } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/EnumAttributeMappingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/EnumAttributeMappingStrategy.java new file mode 100644 index 0000000000..052438beb5 --- /dev/null +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/EnumAttributeMappingStrategy.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015 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.mapping; + +import com.google.common.base.Optional; +import javax.management.openmbean.CompositeType; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.EnumResolver; + +public class EnumAttributeMappingStrategy extends AbstractAttributeMappingStrategy { + + private final EnumResolver enumResolver; + + public EnumAttributeMappingStrategy(CompositeType openType, final EnumResolver enumResolver) { + super(openType); + this.enumResolver = enumResolver; + } + + @Override + public Optional mapAttribute(Object value) { + if (value == null){ + return Optional.absent(); + } + + String expectedClass = getOpenType().getTypeName(); + return Optional.of(enumResolver.toYang(expectedClass, value.toString())); + } + +} diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/ObjectMapper.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/ObjectMapper.java index b50a035be2..463e98100c 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/ObjectMapper.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/ObjectMapper.java @@ -22,12 +22,15 @@ import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribu 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.osgi.EnumResolver; public class ObjectMapper extends AttributeIfcSwitchStatement>> { + private EnumResolver enumResolver; public Map>> prepareMapping( - Map configDefinition) { + Map configDefinition, EnumResolver enumResolver) { + this.enumResolver = Preconditions.checkNotNull(enumResolver); Map>> strategies = Maps.newHashMap(); for (Entry attrEntry : configDefinition.entrySet()) { @@ -63,6 +66,11 @@ public class ObjectMapper extends AttributeIfcSwitchStatement> caseJavaEnumAttribute(final OpenType openType) { + return new EnumAttributeMappingStrategy(((CompositeType) openType), enumResolver); + } + @Override protected AttributeMappingStrategy> caseJavaArrayAttribute(ArrayType openType) { diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/EnumAttributeResolvingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/EnumAttributeResolvingStrategy.java new file mode 100644 index 0000000000..25c4da1a66 --- /dev/null +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/EnumAttributeResolvingStrategy.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015 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.resolving; + +import com.google.common.base.Optional; +import com.google.common.base.Preconditions; +import java.util.Map; +import javax.management.openmbean.CompositeType; +import org.opendaylight.controller.netconf.api.NetconfDocumentedException; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.EnumResolver; +import org.opendaylight.controller.netconf.confignetconfconnector.util.Util; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +final class EnumAttributeResolvingStrategy extends AbstractAttributeResolvingStrategy { + + private static final Logger LOG = LoggerFactory.getLogger(EnumAttributeResolvingStrategy.class); + private final EnumResolver enumResolver; + + EnumAttributeResolvingStrategy(CompositeType simpleType, final EnumResolver enumResolver) { + super(simpleType); + this.enumResolver = enumResolver; + } + + @Override + public String toString() { + return "ResolvedEnumAttribute [" + getOpenType().getClassName() + "]"; + } + + @Override + public Optional parseAttribute(String attrName, Object value) throws NetconfDocumentedException { + if (value == null) { + return Optional.absent(); + } + + Util.checkType(value, Map.class); + Map valueMap = (Map) value; + Preconditions.checkArgument(valueMap.size() == 1, "Unexpected value size " + value + " should be just 1 foe enum"); + final Object innerValue = valueMap.values().iterator().next(); + Util.checkType(innerValue, String.class); + + final String className = getOpenType().getTypeName(); + final Object parsedValue = enumResolver.fromYang(className, ((String) innerValue)); + + LOG.debug("Attribute {} : {} parsed to enum type {} with value {}", attrName, innerValue, getOpenType(), parsedValue); + return Optional.of(parsedValue); + } + +} diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/ObjectResolver.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/ObjectResolver.java index b231cf8e78..93c83eb93c 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/ObjectResolver.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/ObjectResolver.java @@ -22,17 +22,21 @@ import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListDepende import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attributes.AttributeIfcSwitchStatement; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ServiceRegistryWrapper; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.EnumResolver; public class ObjectResolver extends AttributeIfcSwitchStatement>> { private final ServiceRegistryWrapper serviceTracker; + private EnumResolver enumResolver; public ObjectResolver(ServiceRegistryWrapper serviceTracker) { this.serviceTracker = serviceTracker; } public Map>> prepareResolving( - Map configDefinition) { + Map configDefinition, final EnumResolver enumResolver) { + this.enumResolver = enumResolver; + Map>> strategies = Maps.newHashMap(); for (Entry attrEntry : configDefinition.entrySet()) { @@ -44,7 +48,6 @@ public class ObjectResolver extends AttributeIfcSwitchStatement> prepareStrategy(AttributeIfc attributeIfc) { - return switchAttribute(attributeIfc); } @@ -56,6 +59,11 @@ public class ObjectResolver extends AttributeIfcSwitchStatement> caseJavaEnumAttribute(final OpenType openType) { + return new EnumAttributeResolvingStrategy((CompositeType) openType, enumResolver); + } + @Override protected AttributeResolvingStrategy> caseJavaSimpleAttribute(SimpleType openType) { return new SimpleAttributeResolvingStrategy(openType); @@ -63,6 +71,7 @@ public class ObjectResolver extends AttributeIfcSwitchStatement> caseJavaArrayAttribute(ArrayType openType) { + SimpleType innerType = (SimpleType) openType.getElementOpenType(); AttributeResolvingStrategy> strat = new SimpleAttributeResolvingStrategy(innerType); return new ArrayAttributeResolvingStrategy(strat, openType); diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ObjectXmlWriter.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ObjectXmlWriter.java index fcbb3a5eed..022e370c30 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ObjectXmlWriter.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ObjectXmlWriter.java @@ -56,6 +56,11 @@ public class ObjectXmlWriter extends AttributeIfcSwitchStatement openType) { + return new SimpleAttributeWritingStrategy(document, key); + } + @Override protected AttributeWritingStrategy caseJavaSimpleAttribute(SimpleType openType) { return new SimpleAttributeWritingStrategy(document, key); diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Config.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Config.java index 69318935e2..c26b4cf5bf 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Config.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/Config.java @@ -29,6 +29,7 @@ import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants; import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig; import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.EnumResolver; import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.w3c.dom.Document; @@ -42,13 +43,16 @@ public class Config { private final Map> identityMap; - public Config(Map> moduleConfigs) { - this(moduleConfigs, Collections.>emptyMap()); + private final EnumResolver enumResolver; + + public Config(Map> moduleConfigs, final EnumResolver enumResolver) { + this(moduleConfigs, Collections.>emptyMap(), enumResolver); } - public Config(Map> moduleConfigs, Map> identityMap) { + public Config(Map> moduleConfigs, Map> identityMap, final EnumResolver enumResolver) { this.moduleConfigs = moduleConfigs; this.identityMap = identityMap; + this.enumResolver = enumResolver; } public static Map>> getMappedInstances(Set instancesToMap, @@ -115,7 +119,7 @@ public class Config { } for (ObjectName objectName : moduleMappingEntry.getValue()) { - modulesElement.appendChild(mapping.toXml(objectName, document, moduleToInstanceEntry.getKey())); + modulesElement.appendChild(mapping.toXml(objectName, document, moduleToInstanceEntry.getKey(), enumResolver)); } } @@ -141,7 +145,7 @@ public class Config { @Override public ModuleElementResolved resolveElement(ModuleConfig moduleMapping, XmlElement moduleElement, ServiceRegistryWrapper serviceTracker, String instanceName, String moduleNamespace, EditStrategyType defaultStrategy) throws NetconfDocumentedException { return moduleMapping.fromXml(moduleElement, serviceTracker, - instanceName, moduleNamespace, defaultStrategy, identityMap); + instanceName, moduleNamespace, defaultStrategy, identityMap, enumResolver); } }; diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfig.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfig.java index ba7b2f20e4..7cfeb453bb 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfig.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/InstanceConfig.java @@ -33,6 +33,7 @@ import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attrib 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.confignetconfconnector.osgi.EnumResolver; import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.slf4j.Logger; @@ -57,11 +58,11 @@ public final class InstanceConfig { this.configRegistryClient = configRegistryClient; } - private Map getMappedConfiguration(ObjectName on) { + private Map getMappedConfiguration(ObjectName on, final EnumResolver enumResolver) { // TODO make field, mappingStrategies can be instantiated only once Map>> mappingStrategies = new ObjectMapper() - .prepareMapping(jmxToAttrConfig); + .prepareMapping(jmxToAttrConfig, enumResolver); Map toXml = Maps.newHashMap(); @@ -87,9 +88,9 @@ public final class InstanceConfig { return toXml; } - public Element toXml(ObjectName on, String namespace, Document document, Element rootElement) { + public Element toXml(ObjectName on, String namespace, Document document, Element rootElement, final EnumResolver enumResolver) { Map strats = new ObjectXmlWriter().prepareWriting(yangToAttrConfig, document); - Map mappedConfig = getMappedConfiguration(on); + Map mappedConfig = getMappedConfiguration(on, enumResolver); Element parentElement; if (nullableDummyContainerName != null) { Element dummyElement = XmlUtil.createElement(document, nullableDummyContainerName, Optional.of(namespace)); @@ -109,11 +110,11 @@ public final class InstanceConfig { return rootElement; } - private void resolveConfiguration(InstanceConfigElementResolved mappedConfig, ServiceRegistryWrapper depTracker) { + private void resolveConfiguration(InstanceConfigElementResolved mappedConfig, ServiceRegistryWrapper depTracker, final EnumResolver enumResolver) { // TODO make field, resolvingStrategies can be instantiated only once Map>> resolvingStrategies = new ObjectResolver( - depTracker).prepareResolving(yangToAttrConfig); + depTracker).prepareResolving(yangToAttrConfig, enumResolver); for (Entry configDefEntry : mappedConfig.getConfiguration().entrySet()) { AttributeConfigElement value = configDefEntry.getValue(); @@ -135,7 +136,7 @@ public final class InstanceConfig { public InstanceConfigElementResolved fromXml(XmlElement moduleElement, ServiceRegistryWrapper services, String moduleNamespace, EditStrategyType defaultStrategy, - Map> identityMap) throws NetconfDocumentedException { + Map> identityMap, final EnumResolver enumResolver) throws NetconfDocumentedException { Map retVal = Maps.newHashMap(); Map strats = new ObjectXmlReader().prepareReading(yangToAttrConfig, identityMap); @@ -188,7 +189,7 @@ public final class InstanceConfig { InstanceConfigElementResolved instanceConfigElementResolved = perInstanceEditStrategy.equals("") ? new InstanceConfigElementResolved( retVal, defaultStrategy) : new InstanceConfigElementResolved(perInstanceEditStrategy, retVal, defaultStrategy); - resolveConfiguration(instanceConfigElementResolved, services); + resolveConfiguration(instanceConfigElementResolved, services, enumResolver); return instanceConfigElementResolved; } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleConfig.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleConfig.java index 7dfe0cd6ea..5cadc08047 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleConfig.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/config/ModuleConfig.java @@ -17,6 +17,7 @@ import org.opendaylight.controller.netconf.api.NetconfDocumentedException; import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants; import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditConfig; import org.opendaylight.controller.netconf.confignetconfconnector.operations.editconfig.EditStrategyType; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.EnumResolver; import org.opendaylight.controller.netconf.util.xml.XmlElement; import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.w3c.dom.Document; @@ -32,7 +33,7 @@ public class ModuleConfig { this.instanceConfig = mbeanMapping; } - public Element toXml(ObjectName instanceON, Document document, String namespace) { + public Element toXml(ObjectName instanceON, Document document, String namespace, final EnumResolver enumResolver) { Element root = XmlUtil.createElement(document, XmlNetconfConstants.MODULE_KEY, Optional.absent()); // type belongs to config.yang namespace, but needs to be prefix:moduleName @@ -47,15 +48,15 @@ public class ModuleConfig { root.appendChild(nameElement); - root = instanceConfig.toXml(instanceON, namespace, document, root); + root = instanceConfig.toXml(instanceON, namespace, document, root, enumResolver); return root; } public ModuleElementResolved fromXml(XmlElement moduleElement, ServiceRegistryWrapper depTracker, String instanceName, - String moduleNamespace, EditStrategyType defaultStrategy, Map> identityMap) throws NetconfDocumentedException { + String moduleNamespace, EditStrategyType defaultStrategy, Map> identityMap, final EnumResolver enumResolver) throws NetconfDocumentedException { - InstanceConfigElementResolved ice = instanceConfig.fromXml(moduleElement, depTracker, moduleNamespace, defaultStrategy, identityMap); + InstanceConfigElementResolved ice = instanceConfig.fromXml(moduleElement, depTracker, moduleNamespace, defaultStrategy, identityMap, enumResolver); return new ModuleElementResolved(instanceName, ice); } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/rpc/InstanceRuntimeRpc.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/rpc/InstanceRuntimeRpc.java index e870731f69..f7108f44c7 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/rpc/InstanceRuntimeRpc.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/rpc/InstanceRuntimeRpc.java @@ -25,14 +25,17 @@ import org.opendaylight.controller.netconf.confignetconfconnector.mapping.attrib 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.confignetconfconnector.osgi.EnumResolver; import org.opendaylight.controller.netconf.util.xml.XmlElement; public final class InstanceRuntimeRpc { private final Map yangToAttrConfig; private final Rpc rpc; + private final EnumResolver enumResolver; - public InstanceRuntimeRpc(Rpc rpc) { + public InstanceRuntimeRpc(Rpc rpc, final EnumResolver enumResolver) { + this.enumResolver = enumResolver; this.yangToAttrConfig = map(rpc.getParameters()); this.rpc = rpc; } @@ -49,7 +52,7 @@ public final class InstanceRuntimeRpc { // TODO make field, resolvingStrategies can be instantiated only once Map>> resolvingStrategies = new ObjectResolver(null) - .prepareResolving(yangToAttrConfig); + .prepareResolving(yangToAttrConfig, enumResolver); // TODO make constructor for object resolver without service tracker for (Entry configDefEntry : mappedConfig.entrySet()) { try { diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/rpc/ModuleRpcs.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/rpc/ModuleRpcs.java index 0722555c55..7316dbcb06 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/rpc/ModuleRpcs.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/rpc/ModuleRpcs.java @@ -13,11 +13,17 @@ import com.google.common.collect.Maps; import java.util.Map; import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry; import org.opendaylight.controller.config.yangjmxgenerator.RuntimeBeanEntry.Rpc; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.EnumResolver; public final class ModuleRpcs { private final Map yangToJavaNames = Maps.newHashMap(); private final Map> rpcMapping = Maps.newHashMap(); + private final EnumResolver enumResolver; + + public ModuleRpcs(final EnumResolver enumResolver) { + this.enumResolver = enumResolver; + } public void addNameMapping(RuntimeBeanEntry runtimeEntry) { String yangName = runtimeEntry.getYangName(); @@ -36,7 +42,7 @@ public final class ModuleRpcs { Preconditions.checkState(!map.containsKey(rpc.getYangName()), "Rpc %s for runtime bean %s added twice", rpc.getYangName(), yangName); - map.put(rpc.getYangName(), new InstanceRuntimeRpc(rpc)); + map.put(rpc.getYangName(), new InstanceRuntimeRpc(rpc, enumResolver)); } public String getRbeJavaName(String yangName) { diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/InstanceRuntime.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/InstanceRuntime.java index e6102cf526..ce30dc4391 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/InstanceRuntime.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/InstanceRuntime.java @@ -17,6 +17,7 @@ import java.util.Map.Entry; import java.util.Set; import javax.management.ObjectName; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.InstanceConfig; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.EnumResolver; import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -84,13 +85,13 @@ public class InstanceRuntime { })); } - public Element toXml(ObjectName rootOn, Set childRbeOns, Document document, Element parentElement, String namespace) { - return toXml(rootOn, childRbeOns, document, null, parentElement, namespace); + public Element toXml(ObjectName rootOn, Set childRbeOns, Document document, Element parentElement, String namespace, final EnumResolver enumResolver) { + return toXml(rootOn, childRbeOns, document, null, parentElement, namespace, enumResolver); } public Element toXml(ObjectName rootOn, Set childRbeOns, Document document, String instanceIndex, - Element parentElement, String namespace) { - Element xml = instanceMapping.toXml(rootOn, namespace, document, parentElement); + Element parentElement, String namespace, final EnumResolver enumResolver) { + Element xml = instanceMapping.toXml(rootOn, namespace, document, parentElement, enumResolver); if (instanceIndex != null) { xml.setAttribute(KEY_ATTRIBUTE_KEY, instanceIndex); @@ -108,7 +109,7 @@ public class InstanceRuntime { Element innerXml = XmlUtil.createElement(document, elementName, Optional.of(namespace)); childMappingEntry.getValue().toXml(objectName, innerChildRbeOns, document, - runtimeInstanceIndex, innerXml, namespace); + runtimeInstanceIndex, innerXml, namespace, enumResolver); xml.appendChild(innerXml); } } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/ModuleRuntime.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/ModuleRuntime.java index 4d67c75893..ca2c019342 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/ModuleRuntime.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/ModuleRuntime.java @@ -13,6 +13,7 @@ import java.util.Collection; import java.util.Set; import javax.management.ObjectName; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleConfig; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.EnumResolver; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -34,9 +35,9 @@ public class ModuleRuntime { } public Element toXml(String namespace, Collection runtimeBeanOns, - Document document, ModuleConfig moduleConfig, ObjectName configBeanON) { + Document document, ModuleConfig moduleConfig, ObjectName configBeanON, final EnumResolver enumResolver) { - Element moduleElement = moduleConfig.toXml(configBeanON, document, namespace); + Element moduleElement = moduleConfig.toXml(configBeanON, document, namespace, enumResolver); ObjectName rootName = findRoot(runtimeBeanOns); @@ -44,7 +45,7 @@ public class ModuleRuntime { childrenRuntimeBeans.remove(rootName); // FIXME: why is this called and not used? - instanceRuntime.toXml(rootName, childrenRuntimeBeans, document, moduleElement, namespace); + instanceRuntime.toXml(rootName, childrenRuntimeBeans, document, moduleElement, namespace, enumResolver); return moduleElement; } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/Runtime.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/Runtime.java index 4a6c0eb365..ddbc99d0e5 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/Runtime.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/runtime/Runtime.java @@ -20,6 +20,7 @@ import org.opendaylight.controller.config.api.jmx.ObjectNameUtil; import org.opendaylight.controller.netconf.api.xml.XmlNetconfConstants; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.Config; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.config.ModuleConfig; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.EnumResolver; import org.opendaylight.controller.netconf.util.xml.XmlUtil; import org.w3c.dom.Document; import org.w3c.dom.Element; @@ -59,7 +60,7 @@ public class Runtime { return retVal; } - public Element toXml(Set instancesToMap, Set configBeans, Document document) { + public Element toXml(Set instancesToMap, Set configBeans, Document document, final EnumResolver enumResolver) { Element root = XmlUtil.createElement(document, XmlNetconfConstants.DATA_KEY, Optional.absent()); Element modulesElement = XmlUtil.createElement(document, XmlNetconfConstants.MODULES_KEY, Optional.of(XmlNetconfConstants.URN_OPENDAYLIGHT_PARAMS_XML_NS_YANG_CONTROLLER_CONFIG)); @@ -82,11 +83,11 @@ public class Runtime { Element runtimeXml; ModuleConfig moduleConfig = moduleConfigs.get(localNamespace).get(moduleName); if(instanceToRbe==null || !instanceToRbe.containsKey(instanceName)) { - runtimeXml = moduleConfig.toXml(instanceON, document, localNamespace); + runtimeXml = moduleConfig.toXml(instanceON, document, localNamespace, enumResolver); } else { ModuleRuntime moduleRuntime = moduleRuntimes.get(localNamespace).get(moduleName); runtimeXml = moduleRuntime.toXml(localNamespace, instanceToRbe.get(instanceName), document, - moduleConfig, instanceON); + moduleConfig, instanceON, enumResolver); } modulesElement.appendChild(runtimeXml); } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfig.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfig.java index 8b31a59768..7948bb6f42 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfig.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/editconfig/EditConfig.java @@ -209,7 +209,7 @@ public class EditConfig extends AbstractConfigNetconfOperation { Map> factories = transformMbeToModuleConfigs(configRegistryClient, yangStoreSnapshot.getModuleMXBeanEntryMap()); Map> identitiesMap = transformIdentities(yangStoreSnapshot.getModules()); - return new Config(factories, identitiesMap); + return new Config(factories, identitiesMap, yangStoreSnapshot.getEnumResolver()); } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/get/Get.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/get/Get.java index fe7f2773cd..40592ea64b 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/get/Get.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/get/Get.java @@ -136,7 +136,7 @@ public class Get extends AbstractConfigNetconfOperation { final Runtime runtime = new Runtime(moduleRuntimes, moduleConfigs); - final Element element = runtime.toXml(runtimeBeans, configBeans, document); + final Element element = runtime.toXml(runtimeBeans, configBeans, document, yangStoreSnapshot.getEnumResolver()); LOG.trace("{} operation successful", XmlNetconfConstants.GET); diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/getconfig/GetConfig.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/getconfig/GetConfig.java index 2c4bde0ee8..401124e7d9 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/getconfig/GetConfig.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/getconfig/GetConfig.java @@ -89,7 +89,7 @@ public class GetConfig extends AbstractConfigNetconfOperation { .queryInstances(configRegistryClient); final Config configMapping = new Config(EditConfig.transformMbeToModuleConfigs(registryClient, - yangStoreSnapshot.getModuleMXBeanEntryMap())); + yangStoreSnapshot.getModuleMXBeanEntryMap()), yangStoreSnapshot.getEnumResolver()); ServiceRegistryWrapper serviceTracker = new ServiceRegistryWrapper(registryClient); dataElement = configMapping.toXml(instances, this.maybeNamespace, document, dataElement, serviceTracker); diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpc.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpc.java index ebbc0e5695..f7d28b789e 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpc.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/operations/runtimerpc/RuntimeRpc.java @@ -30,6 +30,7 @@ import org.opendaylight.controller.netconf.confignetconfconnector.mapping.rpc.In import org.opendaylight.controller.netconf.confignetconfconnector.mapping.rpc.ModuleRpcs; import org.opendaylight.controller.netconf.confignetconfconnector.mapping.rpc.Rpcs; import org.opendaylight.controller.netconf.confignetconfconnector.operations.AbstractConfigNetconfOperation; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.EnumResolver; import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreContext; import org.opendaylight.controller.netconf.mapping.api.HandlingPriority; import org.opendaylight.controller.netconf.util.exception.MissingNameSpaceException; @@ -103,7 +104,7 @@ public class RuntimeRpc extends AbstractConfigNetconfOperation { final RuntimeRpcElementResolved id = RuntimeRpcElementResolved.fromXpath( contextInstanceElement.getTextContent(), operationName, namespace); - final Rpcs rpcs = mapRpcs(yangStoreSnapshot.getModuleMXBeanEntryMap()); + final Rpcs rpcs = mapRpcs(yangStoreSnapshot.getModuleMXBeanEntryMap(), yangStoreSnapshot.getEnumResolver()); final ModuleRpcs rpcMapping = rpcs.getRpcMapping(id); final InstanceRuntimeRpc instanceRuntimeRpc = rpcMapping.getRpc(id.getRuntimeBeanName(), operationName); @@ -144,7 +145,7 @@ public class RuntimeRpc extends AbstractConfigNetconfOperation { .getTextContent(), netconfOperationName, netconfOperationNamespace); // TODO reuse rpcs instance in fromXml method - final Rpcs rpcs = mapRpcs(yangStoreSnapshot.getModuleMXBeanEntryMap()); + final Rpcs rpcs = mapRpcs(yangStoreSnapshot.getModuleMXBeanEntryMap(), yangStoreSnapshot.getEnumResolver()); try { @@ -239,7 +240,7 @@ public class RuntimeRpc extends AbstractConfigNetconfOperation { return sorted; } - private static Rpcs mapRpcs(final Map> mBeanEntries) { + private static Rpcs mapRpcs(final Map> mBeanEntries, final EnumResolver enumResolver) { final Map> map = Maps.newHashMap(); @@ -255,7 +256,7 @@ public class RuntimeRpc extends AbstractConfigNetconfOperation { ModuleRpcs rpcMapping = namespaceToModules.get(moduleEntry.getKey()); if (rpcMapping == null) { - rpcMapping = new ModuleRpcs(); + rpcMapping = new ModuleRpcs(enumResolver); namespaceToModules.put(moduleEntry.getKey(), rpcMapping); } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/Activator.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/Activator.java index f39a21d16b..6f082b7ab1 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/Activator.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/Activator.java @@ -14,6 +14,7 @@ import java.util.Dictionary; import java.util.Hashtable; import org.opendaylight.controller.netconf.api.util.NetconfConstants; import org.opendaylight.controller.netconf.mapping.api.NetconfOperationServiceFactory; +import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext; import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; @@ -53,7 +54,9 @@ public class Activator implements BundleActivator { @Override public void modifiedService(ServiceReference reference, ConfigRegistryLookupThread configRegistryLookup) { LOG.debug("Got modifiedService(SchemaContextProvider) event"); - configRegistryLookup.yangStoreService.refresh(); + final BindingRuntimeContext runtimeContext = (BindingRuntimeContext) reference.getProperty(BindingRuntimeContext.class.getName()); + LOG.debug("BindingRuntimeContext retrieved as {}", runtimeContext); + configRegistryLookup.yangStoreService.refresh(runtimeContext); } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/EnumResolver.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/EnumResolver.java new file mode 100644 index 0000000000..7efdf5f415 --- /dev/null +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/EnumResolver.java @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2015 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.osgi; + +public interface EnumResolver { + + String fromYang(String enumType, String enumYangValue); + + String toYang(String enumType, String enumJavaValue); +} diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreContext.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreContext.java index 6a38a9ad3d..290912afbb 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreContext.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreContext.java @@ -35,4 +35,6 @@ public interface YangStoreContext { String getModuleSource(ModuleIdentifier moduleIdentifier); + EnumResolver getEnumResolver(); + } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreService.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreService.java index ac3873e6b8..ad771f99d8 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreService.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreService.java @@ -33,6 +33,7 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.not import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.notifications.rev120206.NetconfCapabilityChangeBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.notifications.rev120206.changed.by.parms.ChangedByBuilder; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.notifications.rev120206.changed.by.parms.changed.by.server.or.user.ServerBuilder; +import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier; @@ -58,7 +59,7 @@ public class YangStoreService implements YangStoreContext { * * We synchronize with GC as usual, using a SoftReference. * - * The atomic reference is used to synchronize with {@link #refresh()}, e.g. when + * The atomic reference is used to synchronize with {@link #refresh(org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext)}, e.g. when * refresh happens, it will push a SoftReference(null), e.g. simulate the GC. Now * that may happen while the getter is already busy acting on the old schema context, * so it needs to understand that a refresh has happened and retry. To do that, it @@ -71,6 +72,9 @@ public class YangStoreService implements YangStoreContext { private final AtomicReference> ref = new AtomicReference<>(new SoftReference(null)); + private final AtomicReference> refBindingContext = + new AtomicReference<>(new SoftReference(null)); + private final SchemaContextProvider schemaContextProvider; private final BaseNetconfNotificationListener notificationPublisher; @@ -98,7 +102,7 @@ public class YangStoreService implements YangStoreContext { while (ret == null) { // We need to be compute a new value - ret = new YangStoreSnapshot(schemaContextProvider.getSchemaContext()); + ret = new YangStoreSnapshot(schemaContextProvider.getSchemaContext(), refBindingContext.get().get()); if (!ref.compareAndSet(r, new SoftReference<>(ret))) { LOG.debug("Concurrent refresh detected, recomputing snapshot"); @@ -130,9 +134,15 @@ public class YangStoreService implements YangStoreContext { return getYangStoreSnapshot().getModuleSource(moduleIdentifier); } - public void refresh() { + @Override + public EnumResolver getEnumResolver() { + return getYangStoreSnapshot().getEnumResolver(); + } + + public void refresh(final BindingRuntimeContext runtimeContext) { final YangStoreSnapshot previous = ref.get().get(); ref.set(new SoftReference(null)); + refBindingContext.set(new SoftReference<>(runtimeContext)); notificationExecutor.submit(new CapabilityChangeNotifier(previous)); } diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreSnapshot.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreSnapshot.java index 5da5322e0d..c798da7f76 100644 --- a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreSnapshot.java +++ b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/osgi/YangStoreSnapshot.java @@ -9,7 +9,9 @@ package org.opendaylight.controller.netconf.confignetconfconnector.osgi; import com.google.common.base.Optional; +import com.google.common.base.Preconditions; import com.google.common.base.Predicate; +import com.google.common.collect.BiMap; import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import com.google.common.collect.Sets; @@ -23,6 +25,7 @@ import org.opendaylight.controller.config.yangjmxgenerator.ModuleMXBeanEntry; import org.opendaylight.controller.config.yangjmxgenerator.PackageTranslator; import org.opendaylight.controller.config.yangjmxgenerator.ServiceInterfaceEntry; import org.opendaylight.controller.config.yangjmxgenerator.TypeProviderWrapper; +import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext; import org.opendaylight.yangtools.sal.binding.yang.types.TypeProviderImpl; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode; @@ -32,7 +35,7 @@ import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleIdentifierImpl; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -final class YangStoreSnapshot implements YangStoreContext { +final class YangStoreSnapshot implements YangStoreContext, EnumResolver { private static final Logger LOG = LoggerFactory.getLogger(YangStoreSnapshot.class); @@ -43,8 +46,10 @@ final class YangStoreSnapshot implements YangStoreContext { private final Map> qNamesToIdentitiesToModuleMXBeanEntries; private final SchemaContext schemaContext; + private final BindingRuntimeContext bindingContextProvider; - public YangStoreSnapshot(final SchemaContext resolveSchemaContext) { + public YangStoreSnapshot(final SchemaContext resolveSchemaContext, final BindingRuntimeContext bindingContextProvider) { + this.bindingContextProvider = bindingContextProvider; LOG.trace("Resolved modules:{}", resolveSchemaContext.getModules()); this.schemaContext = resolveSchemaContext; // JMX generator @@ -132,6 +137,11 @@ final class YangStoreSnapshot implements YangStoreContext { } } + @Override + public EnumResolver getEnumResolver() { + return this; + } + @Override public boolean equals(final Object o) { if (this == o) return true; @@ -149,4 +159,21 @@ final class YangStoreSnapshot implements YangStoreContext { public int hashCode() { return schemaContext != null ? schemaContext.hashCode() : 0; } + + @Override + public String fromYang(final String enumClass, final String enumYangValue) { + Preconditions.checkState(bindingContextProvider != null, "Binding context provider was not set yet"); + final BiMap enumMapping = bindingContextProvider.getEnumMapping(enumClass); + final String javaName = enumMapping.get(enumYangValue); + return Preconditions.checkNotNull(javaName, "Unable to resolve enum value %s for enum class %s with assumed enum mapping: %s", enumYangValue, enumClass, enumMapping); + } + + @Override + public String toYang(final String enumClass, final String enumJavaValue) { + Preconditions.checkState(bindingContextProvider != null, "Binding context provider was not set yet"); + final BiMap enumMapping = bindingContextProvider.getEnumMapping(enumClass); + final String javaName = enumMapping.inverse().get(enumJavaValue); + return Preconditions.checkNotNull(javaName, "Unable to map enumcd .." + + "cd value %s for enum class %s with assumed enum mapping: %s", enumJavaValue, enumClass, enumMapping.inverse()); + } } diff --git a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java index 47bdcd8cc8..ec09cfa7a9 100644 --- a/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java +++ b/opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java @@ -26,6 +26,8 @@ import static org.opendaylight.controller.netconf.util.xml.XmlUtil.readXmlToElem import com.google.common.base.Optional; import com.google.common.base.Preconditions; +import com.google.common.collect.BiMap; +import com.google.common.collect.HashBiMap; import com.google.common.collect.ImmutableMap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; @@ -92,6 +94,7 @@ import org.opendaylight.controller.netconf.confignetconfconnector.operations.edi import org.opendaylight.controller.netconf.confignetconfconnector.operations.get.Get; import org.opendaylight.controller.netconf.confignetconfconnector.operations.getconfig.GetConfig; import org.opendaylight.controller.netconf.confignetconfconnector.operations.runtimerpc.RuntimeRpc; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.EnumResolver; import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreContext; import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreService; import org.opendaylight.controller.netconf.confignetconfconnector.transactions.TransactionProvider; @@ -162,6 +165,19 @@ public class NetconfMappingTest extends AbstractConfigTest { doReturn(getMbes()).when(this.yangStoreSnapshot).getModuleMXBeanEntryMap(); doReturn(getModules()).when(this.yangStoreSnapshot).getModules(); + doReturn(new EnumResolver() { + @Override + public String fromYang(final String enumType, final String enumYangValue) { + return Preconditions.checkNotNull(getEnumMapping().get(enumYangValue), + "Unable to resolve enum value %s, for enum %s with mappings %s", enumYangValue, enumType, getEnumMapping()); + } + + @Override + public String toYang(final String enumType, final String enumYangValue) { + return Preconditions.checkNotNull(getEnumMapping().inverse().get(enumYangValue), + "Unable to resolve enum value %s, for enum %s with mappings %s", enumYangValue, enumType, getEnumMapping().inverse()); + } + }).when(this.yangStoreSnapshot).getEnumResolver(); this.factory = new NetconfTestImplModuleFactory(); this.factory2 = new DepTestImplModuleFactory(); @@ -601,9 +617,9 @@ public class NetconfMappingTest extends AbstractConfigTest { // Default assertContainsElement(response, readXmlToElement("2")); - assertContainsElement(response, readXmlToElement("TWO")); + assertContainsElement(response, readXmlToElement("two")); // Default - assertContainsElement(response, readXmlToElement("ONE")); + assertContainsElement(response, readXmlToElement("one")); } private void assertContainsString(String string, String substring) { @@ -612,7 +628,7 @@ public class NetconfMappingTest extends AbstractConfigTest { private void checkEnum(final Document response) throws Exception { - String expectedEnumContent = "TWO"; + String expectedEnumContent = "two"; XMLAssert.assertXpathEvaluatesTo(expectedEnumContent, getXpathForNetconfImplSubnode(INSTANCE_NAME,"extended-enum"), @@ -657,11 +673,22 @@ public class NetconfMappingTest extends AbstractConfigTest { return schemaContext ; } }, mockedContext); + final BindingRuntimeContext bindingRuntimeContext = mock(BindingRuntimeContext.class); + doReturn(getEnumMapping()).when(bindingRuntimeContext).getEnumMapping(any(Class.class)); + yangStoreService.refresh(bindingRuntimeContext); mBeanEntries.putAll(yangStoreService.getModuleMXBeanEntryMap()); return mBeanEntries; } + private BiMap getEnumMapping() { + final HashBiMap enumBiMap = HashBiMap.create(); + // Enum constants mapping from yang -> Java and back + enumBiMap.put("one", "One"); + enumBiMap.put("two", "Two"); + return enumBiMap; + } + private Set getModules() throws Exception { SchemaContext resolveSchemaContext = getSchemaContext(); return resolveSchemaContext.getModules(); diff --git a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/AbstractNetconfConfigTest.java b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/AbstractNetconfConfigTest.java index 7cdcb1bd28..1e31782bb2 100644 --- a/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/AbstractNetconfConfigTest.java +++ b/opendaylight/netconf/netconf-it/src/test/java/org/opendaylight/controller/netconf/it/AbstractNetconfConfigTest.java @@ -50,6 +50,7 @@ import org.opendaylight.controller.netconf.client.NetconfClientDispatcherImpl; import org.opendaylight.controller.netconf.client.SimpleNetconfClientSessionListener; import org.opendaylight.controller.netconf.client.conf.NetconfClientConfiguration; import org.opendaylight.controller.netconf.client.conf.NetconfClientConfigurationBuilder; +import org.opendaylight.controller.netconf.confignetconfconnector.osgi.EnumResolver; import org.opendaylight.controller.netconf.confignetconfconnector.osgi.NetconfOperationServiceFactoryImpl; import org.opendaylight.controller.netconf.confignetconfconnector.osgi.YangStoreService; import org.opendaylight.controller.netconf.impl.DefaultCommitNotificationProducer; @@ -65,6 +66,7 @@ import org.opendaylight.controller.netconf.notifications.BaseNetconfNotification import org.opendaylight.controller.netconf.util.test.XmlFileLoader; import org.opendaylight.protocol.framework.NeverReconnectStrategy; import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.notifications.rev120206.NetconfCapabilityChange; +import org.opendaylight.yangtools.yang.binding.BindingMapping; import org.opendaylight.yangtools.yang.model.api.SchemaContext; import org.opendaylight.yangtools.yang.model.api.SchemaContextProvider; import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl; @@ -280,5 +282,20 @@ public abstract class AbstractNetconfConfigTest extends AbstractConfigTest { final YangParserImpl yangParser = new YangParserImpl(); return yangParser.resolveSchemaContext(new HashSet<>(yangParser.parseYangModelsFromStreamsMapped(byteArrayInputStreams).values())); } + + @Override + public EnumResolver getEnumResolver() { + return new EnumResolver() { + @Override + public String fromYang(final String enumType, final String enumYangValue) { + return BindingMapping.getClassName(enumYangValue); + } + + @Override + public String toYang(final String enumType, final String enumJavaValue) { + return enumJavaValue.toLowerCase(); + } + }; + } } } diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig.xml index a0458c45e3..761225015e 100644 --- a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig.xml +++ b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig.xml @@ -44,7 +44,7 @@ - TWO + two 44 -- 2.36.6