Added support for union yang types to netconf. 78/3678/2
authorMaros Marsalek <mmarsale@cisco.com>
Thu, 5 Dec 2013 12:39:22 +0000 (13:39 +0100)
committerMaros Marsalek <mmarsale@cisco.com>
Fri, 13 Dec 2013 10:44:57 +0000 (11:44 +0100)
Change-Id: I3f936850fdf9a2c96e0ccda50a5178da6d90a92d
Signed-off-by: Maros Marsalek <mmarsale@cisco.com>
23 files changed:
opendaylight/config/yang-jmx-generator/pom.xml
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/TypeProviderWrapper.java
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/JavaAttribute.java
opendaylight/config/yang-jmx-generator/src/main/java/org/opendaylight/controller/config/yangjmxgenerator/attribute/SimpleTypeResolver.java
opendaylight/config/yang-test/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/controller/config/test/types/rev131127/UnionTestBuilder.java [new file with mode: 0644]
opendaylight/config/yang-test/src/main/yang/config-test-impl.yang
opendaylight/config/yang-test/src/main/yang/types/test-types.yang
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/AttributeIfcSwitchStatement.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/ObjectXmlReader.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleUnionAttributeReadingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/CompositeAttributeMappingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/ObjectMapper.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/UnionCompositeAttributeMappingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/CompositeAttributeResolvingStrategy.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/ObjectResolver.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/UnionCompositeAttributeResolvingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/ObjectXmlWriter.java
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/SimpleUnionAttributeWritingStrategy.java [new file with mode: 0644]
opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/util/Util.java
opendaylight/netconf/config-netconf-connector/src/test/java/org/opendaylight/controller/netconf/confignetconfconnector/NetconfMappingTest.java
opendaylight/netconf/config-persister-impl/src/main/java/org/opendaylight/controller/netconf/persist/impl/PropertiesProviderAdapterImpl.java
opendaylight/netconf/ietf-netconf-monitoring/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/netconf/monitoring/rev101004/netconf/state/schemas/LocationBuilder.java [new file with mode: 0644]
opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_setUnions.xml [new file with mode: 0644]

index c312cc849351587096c871c5edefe9bd25954efd..c66b11256601125e4ef84980756780fc9bc20376 100644 (file)
             <artifactId>commons-lang3</artifactId>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>binding-type-provider</artifactId>
+        </dependency>
     </dependencies>
 
     <build>
index 764ecd38868c7b224c1c8e0065d7989f8126fa37..c43fead0fcd0f5aa7e281768e2da0020bf149918 100644 (file)
@@ -64,4 +64,8 @@ public class TypeProviderWrapper {
     public String getJMXParamForBaseType(TypeDefinition<?> baseType) {
         return typeProvider.getConstructorPropertyName(baseType);
     }
+
+    public String getJMXParamForUnionInnerType(TypeDefinition<?> unionInnerType) {
+        return typeProvider.getParamNameFromType(unionInnerType);
+    }
 }
index 3e20e4a55ad47f58e538a33594d1f5d4f0e70d32..e01063ef92e86b217bc4c737eb89b0f7c17cf283 100644 (file)
@@ -7,20 +7,26 @@
  */
 package org.opendaylight.controller.config.yangjmxgenerator.attribute;
 
+import com.google.common.base.Preconditions;
 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.UnionTypeDefinition;
 
 import javax.management.openmbean.ArrayType;
 import javax.management.openmbean.CompositeType;
 import javax.management.openmbean.OpenDataException;
 import javax.management.openmbean.OpenType;
 import javax.management.openmbean.SimpleType;
+import java.util.Arrays;
+import java.util.List;
 
 public class JavaAttribute extends AbstractAttribute implements TypedAttribute {
 
+    public static final String DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION = "valueOfArtificialUnionProperty";
+
     private final Type type;
     private final String nullableDescription, nullableDefault, nullableDefaultWrappedForCode;
     private final TypeProviderWrapper typeProviderWrapper;
@@ -47,6 +53,11 @@ public class JavaAttribute extends AbstractAttribute implements TypedAttribute {
         this.nullableDescription = leaf.getDescription();
     }
 
+    public boolean isUnion() {
+        TypeDefinition<?> base = getBaseType(typeProviderWrapper, typeDefinition);
+        return base instanceof UnionTypeDefinition;
+    }
+
     public TypeDefinition<?> getTypeDefinition() {
         return typeDefinition;
     }
@@ -132,13 +143,70 @@ public class JavaAttribute extends AbstractAttribute implements TypedAttribute {
             return getArrayType();
         } else if (isEnum(baseType)) {
             return getSimpleType(baseType);
-        } else if (isDerivedType(baseType)) {
+        } else if (isUnion()) {
+            return getCompositeTypeForUnion(baseTypeDefinition);
+        } else if (isDerivedType(baseType, getType())) {
             return getCompositeType(baseType, baseTypeDefinition);
         }
 
         return getSimpleType(getType());
     }
 
+    private OpenType<?> getCompositeTypeForUnion(TypeDefinition<?> baseTypeDefinition) {
+        Preconditions.checkArgument(baseTypeDefinition instanceof UnionTypeDefinition,
+                "Expected %s instance but was %s", UnionTypeDefinition.class, baseTypeDefinition);
+
+        List<TypeDefinition<?>> types = ((UnionTypeDefinition) baseTypeDefinition).getTypes();
+
+        String[] itemNames = new String[types.size()+1];
+        OpenType<?>[] itemTypes = new OpenType[itemNames.length];
+
+        addArtificialPropertyToUnionCompositeType(baseTypeDefinition, itemNames, itemTypes);
+
+        String description = getNullableDescription() == null ? getAttributeYangName() : getNullableDescription();
+
+        int i = 1;
+        for (TypeDefinition<?> innerTypeDefinition : types) {
+
+            Type innerType = typeProviderWrapper.getType(innerTypeDefinition, innerTypeDefinition);
+
+            TypeDefinition<?> baseInnerTypeDefinition = getBaseType(typeProviderWrapper, innerTypeDefinition);
+            Type innerTypeBaseType = typeProviderWrapper.getType(baseInnerTypeDefinition, baseInnerTypeDefinition);
+
+            OpenType<?> innerCompositeType;
+
+            if(isDerivedType(innerTypeBaseType, innerType)) {
+                innerCompositeType = getCompositeType(innerTypeBaseType, baseInnerTypeDefinition);
+            } else {
+                innerCompositeType = SimpleTypeResolver.getSimpleType(innerType);
+            }
+
+            itemNames[i] = typeProviderWrapper.getJMXParamForUnionInnerType(innerTypeDefinition);
+            itemTypes[i++] = innerCompositeType;
+        }
+
+        String[] descriptions = Arrays.copyOf(itemNames, itemNames.length);
+        descriptions[0] = DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION;
+
+        try {
+            return new CompositeType(getUpperCaseCammelCase(), description, itemNames, descriptions, itemTypes);
+        } catch (OpenDataException e) {
+            throw new RuntimeException("Unable to create " + CompositeType.class + " with inner elements "
+                    + Arrays.toString(itemTypes), e);
+        }
+    }
+
+    public static final Class<Character> TYPE_OF_ARTIFICIAL_UNION_PROPERTY = char.class;
+
+    private void addArtificialPropertyToUnionCompositeType(TypeDefinition<?> baseTypeDefinition, String[] itemNames, OpenType<?>[] itemTypes) {
+        String artificialPropertyName = typeProviderWrapper.getJMXParamForBaseType(baseTypeDefinition);
+        itemNames[0] = artificialPropertyName;
+
+        OpenType<?> artificialPropertyType = getArrayOpenTypeForSimpleType(TYPE_OF_ARTIFICIAL_UNION_PROPERTY.getName(),
+                SimpleTypeResolver.getSimpleType(TYPE_OF_ARTIFICIAL_UNION_PROPERTY.getName()));
+        itemTypes[0] = artificialPropertyType;
+    }
+
     private boolean isEnum(Type baseType) {
         return baseType.getFullyQualifiedName().equals(Enum.class.getName());
     }
@@ -163,12 +231,15 @@ public class JavaAttribute extends AbstractAttribute implements TypedAttribute {
             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);
+        return getArrayOpenTypeForSimpleType(innerTypeFullyQName, innerSimpleType);
+    }
+
+    private OpenType<?> getArrayOpenTypeForSimpleType(String innerTypeFullyQName, SimpleType<?> innerSimpleType) {
         try {
             ArrayType<Object> arrayType = isPrimitive(innerTypeFullyQName) ? new ArrayType<>(innerSimpleType, true)
                     : new ArrayType<>(1, innerSimpleType);
@@ -191,8 +262,8 @@ public class JavaAttribute extends AbstractAttribute implements TypedAttribute {
         return type.getName().endsWith("[]");
     }
 
-    private boolean isDerivedType(Type baseType) {
-        return  baseType.equals(getType()) == false;
+    private boolean isDerivedType(Type baseType, Type currentType) {
+        return  baseType.equals(currentType) == false;
     }
 
     private static String getInnerType(Type type) {
index 87b55f3756a0e042c98c89739d91bf0f92ab5285..f4bd979faca43fa5f4bdce943ceeb389ca07b42b 100644 (file)
@@ -59,6 +59,8 @@ 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/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/controller/config/test/types/rev131127/UnionTestBuilder.java b/opendaylight/config/yang-test/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/controller/config/test/types/rev131127/UnionTestBuilder.java
new file mode 100644 (file)
index 0000000..c49319b
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.config.test.types.rev131127;
+
+
+/**
+**/
+public class UnionTestBuilder {
+
+    public static UnionTest getDefaultInstance(String defaultValue) {
+        try {
+            int i = Integer.valueOf(defaultValue);
+            return new UnionTest(new ExtendTwice(i));
+        } catch (NumberFormatException e) {
+            return new UnionTest(defaultValue);
+        }
+    }
+
+}
index 9ad7a44915b15bdfbce7a64cbdaf2eb02f8bba14..f7cea0a52abbb0b46edb5b431d140dc4482fe76d 100644 (file)
@@ -61,10 +61,6 @@ module config-test-impl {
                     default 127.0.0.1;
                 }
 
-                leaf ip {
-                    type inet:ip-address;
-                    // TODO defaults for union default 0:0:0:0:0:0:0:1;
-                }
             }
 
             leaf as-number {
@@ -136,6 +132,16 @@ module config-test-impl {
                 default ONE;
             }
 
+            leaf ip {
+                type inet:ip-address;
+                default 0:0:0:0:0:0:0:1;
+            }
+
+            leaf union-test-attr {
+                type tt:unionTest;
+                default 456;
+            }
+
             leaf sleep-factor {
                 type decimal64 {
                     fraction-digits 2;
index 84fbcb089d6390ba4478c24a0503442ad0bfd8d1..8c086d8aceb1d5ec21c06f398e57fcd46d8bda62 100644 (file)
@@ -23,4 +23,12 @@ module test-types {
         }
     }
 
+      typedef unionTest {
+        type union {
+          type string;
+          type uint32;
+          type extend-twice;
+        }
+      }
+
 }
index 697b811d51c90c9b7cab4f05f266292d25d2a260..cf0e71e67a52ab9983b5a2599519cf9f3014118c 100644 (file)
@@ -29,12 +29,16 @@ public abstract class AttributeIfcSwitchStatement<T> {
 
         this.lastAttribute = attributeIfc;
 
+        OpenType<?> openType = attributeIfc.getOpenType();
+
         if (attributeIfc instanceof JavaAttribute) {
             try {
                 if(((JavaAttribute)attributeIfc).getTypeDefinition() instanceof BinaryTypeDefinition) {
-                    return caseJavaBinaryAttribute(attributeIfc.getOpenType());
+                    return caseJavaBinaryAttribute(openType);
+                } else if(((JavaAttribute)attributeIfc).isUnion()) {
+                    return caseJavaUnionAttribute(openType);
                 } else
-                    return caseJavaAttribute(attributeIfc.getOpenType());
+                    return caseJavaAttribute(openType);
             } catch (UnknownOpenTypeException e) {
                 throw getIllegalArgumentException(attributeIfc);
             }
@@ -42,9 +46,9 @@ public abstract class AttributeIfcSwitchStatement<T> {
         } else if (attributeIfc instanceof DependencyAttribute) {
             return caseDependencyAttribute(((DependencyAttribute) attributeIfc).getOpenType());
         } else if (attributeIfc instanceof ListAttribute) {
-            return caseListAttribute((ArrayType<?>) attributeIfc.getOpenType());
+            return caseListAttribute((ArrayType<?>) openType);
         } else if (attributeIfc instanceof ListDependenciesAttribute) {
-            return caseListDependeciesAttribute((ArrayType<?>) attributeIfc.getOpenType());
+            return caseListDependeciesAttribute((ArrayType<?>) openType);
         } else if (attributeIfc instanceof TOAttribute) {
             return caseTOAttribute(((TOAttribute) attributeIfc).getOpenType());
         }
@@ -52,6 +56,10 @@ public abstract class AttributeIfcSwitchStatement<T> {
         throw getIllegalArgumentException(attributeIfc);
     }
 
+    protected T caseJavaUnionAttribute(OpenType<?> openType) {
+        return caseJavaAttribute(openType);
+    }
+
     protected T caseJavaBinaryAttribute(OpenType<?> openType) {
         return caseJavaAttribute(openType);
     }
index a2691f241cfa9a6c273c95c653c2fa9720d03cb9..97c0f4d834ba7d7a810d9d36a08a1a74deb748e7 100644 (file)
@@ -11,6 +11,7 @@ package org.opendaylight.controller.netconf.confignetconfconnector.mapping.attri
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Maps;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.AttributeIfc;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.ListDependenciesAttribute;
 import org.opendaylight.controller.config.yangjmxgenerator.attribute.TOAttribute;
@@ -47,6 +48,12 @@ public class ObjectXmlReader extends AttributeIfcSwitchStatement<AttributeReadin
         return new SimpleBinaryAttributeReadingStrategy(lastAttribute.getNullableDefault());
     }
 
+    @Override
+    protected AttributeReadingStrategy caseJavaUnionAttribute(OpenType<?> openType) {
+        String mappingKey = JavaAttribute.DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION;
+        return new SimpleUnionAttributeReadingStrategy(lastAttribute.getNullableDefault(), mappingKey);
+    }
+
     @Override
     public AttributeReadingStrategy caseJavaSimpleAttribute(SimpleType<?> openType) {
         return new SimpleAttributeReadingStrategy(lastAttribute.getNullableDefault());
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleUnionAttributeReadingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/fromxml/SimpleUnionAttributeReadingStrategy.java
new file mode 100644 (file)
index 0000000..2e8b459
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * 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 com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+
+import java.util.List;
+import java.util.Map;
+
+public class SimpleUnionAttributeReadingStrategy extends SimpleAttributeReadingStrategy {
+
+    private final String key;
+
+    public SimpleUnionAttributeReadingStrategy(String nullableDefault, String key) {
+        super(nullableDefault);
+        this.key = key;
+    }
+
+    protected Object postprocessParsedValue(String textContent) {
+        char[] charArray = textContent.toCharArray();
+        List<String> chars = Lists.newArrayListWithCapacity(charArray.length);
+
+        for (char c : charArray) {
+            chars.add(Character.toString(c));
+        }
+
+        Map<String, Object> map = Maps.newHashMap();
+        map.put(key, chars);
+        return map;
+    }
+
+    @Override
+    protected Object postprocessNullableDefault(String nullableDefault) {
+        return nullableDefault == null ? null : postprocessParsedValue(nullableDefault);
+    }
+}
index 252b13bf6850c498d6c122565044359647dd5520..368e1f12a642e54dc90ac8231818619a0de96815 100644 (file)
@@ -53,17 +53,21 @@ public class CompositeAttributeMappingStrategy extends
         Map<String, Object> retVal = Maps.newHashMap();
 
         for (String jmxName : jmxToJavaNameMapping.keySet()) {
-            String innerAttrJmxName = jmxName;
-            Object innerValue = compositeData.get(innerAttrJmxName);
-
-            AttributeMappingStrategy<?, ? extends OpenType<?>> attributeMappingStrategy = innerStrategies
-                    .get(innerAttrJmxName);
-            Optional<?> mapAttribute = attributeMappingStrategy.mapAttribute(innerValue);
-            if (mapAttribute.isPresent())
-                retVal.put(jmxToJavaNameMapping.get(innerAttrJmxName), mapAttribute.get());
+            Optional<?> mapped = mapInnerAttribute(compositeData, jmxName, expectedType.getDescription(jmxName));
+            if(mapped.isPresent())
+                retVal.put(jmxToJavaNameMapping.get(jmxName), mapped.get());
         }
 
         return Optional.of(retVal);
     }
 
+    protected Optional<?> mapInnerAttribute(CompositeDataSupport compositeData, String jmxName, String description) {
+        Object innerValue = compositeData.get(jmxName);
+
+        AttributeMappingStrategy<?, ? extends OpenType<?>> attributeMappingStrategy = innerStrategies
+                .get(jmxName);
+        Optional<?> mapAttribute = attributeMappingStrategy.mapAttribute(innerValue);
+        return mapAttribute;
+    }
+
 }
index 6e5bd0d3fe8229597ab6984f37150f1833cd3525..fb385221c8877b9ffceadf53cd355f8c78197811 100644 (file)
@@ -90,6 +90,22 @@ public class ObjectMapper extends AttributeIfcSwitchStatement<AttributeMappingSt
         return new CompositeAttributeMappingStrategy(openType, innerStrategies, attributeMapping);
     }
 
+    @Override
+    protected AttributeMappingStrategy<?, ? extends OpenType<?>> caseJavaUnionAttribute(OpenType<?> openType) {
+        Map<String, AttributeMappingStrategy<?, ? extends OpenType<?>>> innerStrategies = Maps.newHashMap();
+
+        Map<String, String> attributeMapping = Maps.newHashMap();
+
+        CompositeType compositeType = (CompositeType) openType;
+        for (String innerAttributeKey : compositeType.keySet()) {
+
+            innerStrategies.put(innerAttributeKey, caseJavaAttribute(compositeType.getType(innerAttributeKey)));
+            attributeMapping.put(innerAttributeKey, innerAttributeKey);
+        }
+
+        return new UnionCompositeAttributeMappingStrategy(compositeType, innerStrategies, attributeMapping);
+    }
+
     private String serviceNameOfDepAttr;
     private String namespaceOfDepAttr;
 
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/UnionCompositeAttributeMappingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/mapping/UnionCompositeAttributeMappingStrategy.java
new file mode 100644 (file)
index 0000000..81a1e53
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * 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.mapping;
+
+import com.google.common.base.Optional;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute;
+
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
+import java.util.Map;
+
+public class UnionCompositeAttributeMappingStrategy extends
+        CompositeAttributeMappingStrategy {
+
+
+    public UnionCompositeAttributeMappingStrategy(CompositeType compositeType, Map<String, AttributeMappingStrategy<?, ? extends OpenType<?>>> innerStrategies, Map<String, String> jmxToJavaNameMapping) {
+        super(compositeType, innerStrategies, jmxToJavaNameMapping);
+    }
+
+    @Override
+    protected Optional<?> mapInnerAttribute(CompositeDataSupport compositeData, String jmxName, String description) {
+        if(description.equals(JavaAttribute.DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION) == false)
+            return Optional.absent();
+
+        return super.mapInnerAttribute(compositeData, jmxName, description);
+    }
+}
index c477821051b08d03288d129fc29c1aaddd32eef6..e8e97f990f44cd45608fb8df92e042437351e319 100644 (file)
@@ -21,7 +21,7 @@ import javax.management.openmbean.OpenDataException;
 import javax.management.openmbean.OpenType;
 import java.util.Map;
 
-final class CompositeAttributeResolvingStrategy extends
+class CompositeAttributeResolvingStrategy extends
         AbstractAttributeResolvingStrategy<CompositeDataSupport, CompositeType> {
     private final Map<String, AttributeResolvingStrategy<?, ? extends OpenType<?>>> innerTypes;
     private final Map<String, String> yangToJavaAttrMapping;
@@ -49,6 +49,7 @@ final class CompositeAttributeResolvingStrategy extends
 
         Util.checkType(value, Map.class);
         Map<?, ?> valueMap = (Map<?, ?>) value;
+        valueMap = preprocessValueMap(valueMap);
 
         Map<String, Object> items = Maps.newHashMap();
         Map<String, OpenType<?>> openTypes = Maps.newHashMap();
@@ -82,4 +83,8 @@ final class CompositeAttributeResolvingStrategy extends
 
         return Optional.of(parsedValue);
     }
+
+    protected Map<?, ?> preprocessValueMap(Map<?, ?> valueMap) {
+        return valueMap;
+    }
 }
index f5a25112602ac6b92c6d08faa46b311dbd11533c..a3e2813fa0d383f6db78c6a2c2d52e32d03dc5e1 100644 (file)
@@ -72,13 +72,30 @@ public class ObjectResolver extends AttributeIfcSwitchStatement<AttributeResolvi
     @Override
     protected AttributeResolvingStrategy<?, ? extends OpenType<?>>  caseJavaCompositeAttribute(CompositeType openType) {
         Map<String, AttributeResolvingStrategy<?, ? extends OpenType<?>>> innerMap = Maps.newHashMap();
-
         Map<String, String> yangToJmxMapping = Maps.newHashMap();
+
+        fillMappingForComposite(openType, innerMap, yangToJmxMapping);
+        return new CompositeAttributeResolvingStrategy(innerMap, openType, yangToJmxMapping);
+    }
+
+    private void fillMappingForComposite(CompositeType openType, Map<String, AttributeResolvingStrategy<?, ? extends OpenType<?>>> innerMap, Map<String, String> yangToJmxMapping) {
         for (String innerAttributeKey : openType.keySet()) {
             innerMap.put(innerAttributeKey, caseJavaAttribute(openType.getType(innerAttributeKey)));
             yangToJmxMapping.put(innerAttributeKey, innerAttributeKey);
         }
-        return new CompositeAttributeResolvingStrategy(innerMap, openType, yangToJmxMapping);
+    }
+
+    @Override
+    protected AttributeResolvingStrategy<?, ? extends OpenType<?>> caseJavaUnionAttribute(OpenType<?> openType) {
+
+        Preconditions.checkState(openType instanceof CompositeType, "Unexpected open type, expected %s but was %s");
+        CompositeType compositeType = (CompositeType) openType;
+
+        Map<String, AttributeResolvingStrategy<?, ? extends OpenType<?>>> innerMap = Maps.newHashMap();
+        Map<String, String> yangToJmxMapping = Maps.newHashMap();
+        fillMappingForComposite(compositeType, innerMap, yangToJmxMapping);
+
+        return new UnionCompositeAttributeResolvingStrategy(innerMap, compositeType, yangToJmxMapping);
     }
 
     @Override
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/UnionCompositeAttributeResolvingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/resolving/UnionCompositeAttributeResolvingStrategy.java
new file mode 100644 (file)
index 0000000..bc99ecf
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * 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.resolving;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.Maps;
+import org.opendaylight.controller.config.yangjmxgenerator.attribute.JavaAttribute;
+
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
+import java.util.Map;
+
+final class UnionCompositeAttributeResolvingStrategy extends CompositeAttributeResolvingStrategy {
+
+    UnionCompositeAttributeResolvingStrategy(Map<String, AttributeResolvingStrategy<?, ? extends OpenType<?>>> innerTypes,
+                                        CompositeType openType, Map<String, String> yangToJavaAttrMapping) {
+        super(innerTypes, openType, yangToJavaAttrMapping);
+    }
+
+    protected Map<String, Object> preprocessValueMap(Map<?, ?> valueMap) {
+        CompositeType openType = getOpenType();
+
+        Preconditions.checkArgument(
+                valueMap.size() == 1 && valueMap.containsKey(JavaAttribute.DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION),
+                "Unexpected structure of incoming map, expecting one element under %s, but was %s",
+                JavaAttribute.DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION, valueMap);
+
+        Map<String, Object> newMap = Maps.newHashMap();
+
+        for (String key : openType.keySet()) {
+            if (openType.getDescription(key).equals(JavaAttribute.DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION))
+                newMap.put(key, valueMap.get(JavaAttribute.DESCRIPTION_OF_VALUE_ATTRIBUTE_FOR_UNION));
+            else
+                newMap.put(key, null);
+        }
+        return newMap;
+    }
+}
index a174e9a25160e8aa3d52ab66891c9d1314e58185..4e870f042d8cf45605546750d0f99868772fa897 100644 (file)
@@ -73,6 +73,11 @@ public class ObjectXmlWriter extends AttributeIfcSwitchStatement<AttributeWritin
         return new SimpleCompositeAttributeWritingStrategy(document, key);
     }
 
+    @Override
+    protected AttributeWritingStrategy caseJavaUnionAttribute(OpenType<?> openType) {
+        return new SimpleUnionAttributeWritingStrategy(document, key);
+    }
+
     @Override
     protected AttributeWritingStrategy caseDependencyAttribute(SimpleType<?> openType) {
         return new ObjectNameAttributeWritingStrategy(document, key);
diff --git a/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/SimpleUnionAttributeWritingStrategy.java b/opendaylight/netconf/config-netconf-connector/src/main/java/org/opendaylight/controller/netconf/confignetconfconnector/mapping/attributes/toxml/SimpleUnionAttributeWritingStrategy.java
new file mode 100644 (file)
index 0000000..d75feb2
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * 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 com.google.common.base.Preconditions;
+import org.opendaylight.controller.netconf.confignetconfconnector.util.Util;
+import org.w3c.dom.Document;
+
+import java.util.List;
+import java.util.Map;
+
+public class SimpleUnionAttributeWritingStrategy extends SimpleAttributeWritingStrategy {
+
+    /**
+     * @param document
+     * @param key
+     */
+    public SimpleUnionAttributeWritingStrategy(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 listOfStrings = ((Map) value).values().iterator().next();
+        Util.checkType(listOfStrings, List.class);
+
+        StringBuilder b = new StringBuilder();
+        for (Object character: (List)listOfStrings) {
+            Util.checkType(character, String.class);
+            b.append(character);
+        }
+
+        return b.toString();
+    }
+
+}
index 26719592bbbe4dd7e553534a1d9fbafe89fbc097..1c806742e9b141c7f836d9565a9f449255406b69 100644 (file)
@@ -38,7 +38,7 @@ public final class Util {
 
     public static void checkType(final Object value, final Class<?> clazz) {
         Preconditions.checkArgument(clazz.isAssignableFrom(value.getClass()), "Unexpected type " + value.getClass()
-                + " should be " + clazz);
+                + " should be " + clazz + " of " + value);
     }
 
     // TODO: add message and proper error types
index b248342a0a9c308a23714a3f82966f11456faa02..11cf1aae6a42bc184dda8288dddcafa9ba47f419 100644 (file)
@@ -144,7 +144,7 @@ public class NetconfMappingTest extends AbstractConfigTest {
                 "ref_from_code_to_instance-from-code_1");
 
         edit("netconfMessages/editConfig_addServiceName.xml");
-         config = getConfigCandidate();
+        config = getConfigCandidate();
         assertCorrectServiceNames(config, 7, "ref_test2", "user_to_instance_from_code", "ref_dep_user",
                 "ref_dep_user_two", "ref_from_code_to_instance-from-code_dep_1",
                 "ref_from_code_to_instance-from-code_1", "ref_dep_user_another");
@@ -199,6 +199,29 @@ public class NetconfMappingTest extends AbstractConfigTest {
         }
     }
 
+    @Test
+    public void testConfigNetconfUnionTypes() throws Exception {
+
+        createModule(INSTANCE_NAME);
+
+        edit("netconfMessages/editConfig.xml");
+        commit();
+        Element response = getConfigRunning();
+        String trimmedResponse = XmlUtil.toString(response).replaceAll("\\s", "");
+        assertContainsString(trimmedResponse, "<ipxmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">0:0:0:0:0:0:0:1</ip>");
+        assertContainsString(trimmedResponse, "<union-test-attrxmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">456</union-test-attr>");
+
+
+        edit("netconfMessages/editConfig_setUnions.xml");
+        commit();
+        response = getConfigRunning();
+
+        trimmedResponse = XmlUtil.toString(response).replaceAll("\\s", "");
+        assertContainsString(trimmedResponse, "<ipxmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">127.1.2.3</ip>");
+        assertContainsString(trimmedResponse, "<union-test-attrxmlns=\"urn:opendaylight:params:xml:ns:yang:controller:test:impl\">randomStringForUnion</union-test-attr>");
+
+    }
+
     @Test
     public void testConfigNetconf() throws Exception {
 
index 981be827b74a7714ae7316aedc7a0347d8263f4c..d9466ff00b6d6a0d1e9c034d43ad310600407dd3 100644 (file)
@@ -1,10 +1,9 @@
-/**
- * @author Tomas Olvecky
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
  *
- * 11 2013
- *
- * Copyright (c) 2013 by Cisco Systems, Inc.
- * 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.persist.impl;
 
diff --git a/opendaylight/netconf/ietf-netconf-monitoring/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/netconf/monitoring/rev101004/netconf/state/schemas/LocationBuilder.java b/opendaylight/netconf/ietf-netconf-monitoring/src/main/java/org/opendaylight/yang/gen/v1/urn/ietf/params/xml/ns/yang/ietf/netconf/monitoring/rev101004/netconf/state/schemas/LocationBuilder.java
new file mode 100644 (file)
index 0000000..0a084b0
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * 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.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev100924.Uri;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.netconf.monitoring.rev101004.netconf.state.schemas.Schema.Location;
+
+
+/**
+**/
+public class LocationBuilder {
+
+    public static Location getDefaultInstance(String defaultValue) {
+        return defaultValue.equals("NETCONF") ? new Location(Location.Enumeration.NETCONF) : new Location(new Uri(
+                defaultValue));
+    }
+
+}
diff --git a/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_setUnions.xml b/opendaylight/netconf/netconf-util/src/test/resources/netconfMessages/editConfig_setUnions.xml
new file mode 100644 (file)
index 0000000..21db4b8
--- /dev/null
@@ -0,0 +1,30 @@
+<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-netconf
+                    </type>
+
+                    <name>instance-from-code</name>
+
+                    <ip xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">127.1.2.3</ip>
+                    <union-test-attr xmlns="urn:opendaylight:params:xml:ns:yang:controller:test:impl">randomStringForUnion</union-test-attr>
+
+                </module>
+            </modules>
+
+            <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
+
+            </services>
+        </config>
+    </edit-config>
+</rpc>