Merge "Split out codecs from BindingCodecContext"
authorTony Tkacik <ttkacik@cisco.com>
Fri, 23 Jan 2015 11:07:25 +0000 (11:07 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Fri, 23 Jan 2015 11:07:25 +0000 (11:07 +0000)
16 files changed:
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/UnionTypeCodec.java
code-generator/binding-data-codec/src/main/java/org/opendaylight/yangtools/binding/data/codec/impl/ValueTypeCodec.java
code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/UnionTypeTest.java [new file with mode: 0644]
code-generator/binding-generator-util/src/main/java/org/opendaylight/yangtools/binding/generator/util/generated/type/builder/GeneratedTOBuilderImpl.java
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/ClassTemplate.xtend
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/GeneratedTransferObject.java
code-generator/binding-model-api/src/main/java/org/opendaylight/yangtools/sal/binding/model/api/type/builder/GeneratedTOBuilder.java
code-generator/binding-test-model/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/yangtools/test/union/rev150121/TopLevelBuilder.java [new file with mode: 0644]
code-generator/binding-test-model/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/yangtools/test/union/rev150121/UnionTestTypeBuilder.java [new file with mode: 0644]
code-generator/binding-test-model/src/main/yang/opendaylight-yangtools-union-test.yang [new file with mode: 0644]
code-generator/binding-type-provider/src/main/java/org/opendaylight/yangtools/sal/binding/yang/types/TypeProviderImpl.java
common/artifacts/pom.xml
common/mockito-configuration/pom.xml
common/parent/pom.xml
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/impl/TypesResolutionTest.java
yang/yang-parser-impl/src/test/resources/types/union-with-bits/union-bits-model.yang [new file with mode: 0644]

index f94673c28897baa1eb67d79b12ae18efdb14a017..ed8a2bc80ae37a632f03bb3024d5d129ed202c98 100644 (file)
@@ -16,9 +16,11 @@ import java.util.HashSet;
 import java.util.Set;
 import java.util.concurrent.Callable;
 
+import org.opendaylight.yangtools.concepts.Codec;
 import org.opendaylight.yangtools.yang.binding.BindingMapping;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
+import org.opendaylight.yangtools.yang.model.util.UnionType;
 
 final class UnionTypeCodec extends ReflectionBasedCodec {
 
@@ -44,7 +46,7 @@ final class UnionTypeCodec extends ReflectionBasedCodec {
                     String methodName = "get" + BindingMapping.getClassName(subtype.getQName());
                     Method valueGetter = unionCls.getMethod(methodName);
                     Class<?> valueType = valueGetter.getReturnType();
-                    SchemaUnawareCodec valueCodec = ValueTypeCodec.getCodecFor(valueType, subtype);
+                    Codec<Object, Object> valueCodec = UnionTypeCodec.getCodecForType(valueType, subtype);
                     values.add(new UnionValueOptionContext(valueType,valueGetter, valueCodec));
                 }
                 return new UnionTypeCodec(unionCls, values);
@@ -52,6 +54,18 @@ final class UnionTypeCodec extends ReflectionBasedCodec {
         };
     }
 
+    private static Codec<Object, Object> getCodecForType(Class valueType, TypeDefinition subtype) {
+        if (subtype.getBaseType() instanceof UnionType) {
+            try {
+                return UnionTypeCodec.loader(valueType, (UnionType) subtype.getBaseType()).call();
+            } catch (final Exception e) {
+                throw new IllegalStateException("Could not construct Union Type Codec");
+            }
+        } else {
+            return ValueTypeCodec.getCodecFor(valueType, subtype);
+        }
+    }
+
     @Override
     public Object deserialize(final Object input) {
         try {
index d8536ee667e9aae07184f25f0e74bf943e72dd31..d327a468d54a1e40c9e1216f8be175cd460a2264 100644 (file)
@@ -97,7 +97,7 @@ abstract class ValueTypeCodec implements Codec<Object, Object> {
         while (rootType.getBaseType() != null) {
             rootType = rootType.getBaseType();
         }
-        if(rootType instanceof EmptyTypeDefinition) {
+        if (rootType instanceof EmptyTypeDefinition) {
             return EMPTY_CODEC;
         }
         return NOOP_CODEC;
diff --git a/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/UnionTypeTest.java b/code-generator/binding-data-codec/src/test/java/org/opendaylight/yangtools/binding/data/codec/test/UnionTypeTest.java
new file mode 100644 (file)
index 0000000..e519892
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * 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.yangtools.binding.data.codec.test;
+
+import javassist.ClassPool;
+import org.junit.Assert;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.union.rev150121.TopLevel;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.union.rev150121.TopLevelBuilder;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.union.rev150121.Wrapper;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.union.rev150121.WrapperBuilder;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
+
+public class UnionTypeTest extends AbstractBindingRuntimeTest {
+
+    private static final String testString = "testtesttest";
+
+    public static final QName WRAPPER_QNAME = QName.create("urn:opendaylight:params:xml:ns:yang:yangtools:test:union", "2015-01-21", "wrapper");
+    public static final QName WRAP_LEAF_QNAME = QName.create(WRAPPER_QNAME, "wrap");
+
+    private BindingNormalizedNodeCodecRegistry registry;
+
+    @Override
+    public void setup() {
+        super.setup();
+        JavassistUtils utils = JavassistUtils.forClassPool(ClassPool.getDefault());
+        registry = new BindingNormalizedNodeCodecRegistry(StreamWriterGenerator.create(utils));
+        registry.onBindingRuntimeContextUpdated(getRuntimeContext());
+    }
+
+    @Test
+    public void unionTest() {
+        TopLevel topLevel = TopLevelBuilder.getDefaultInstance(testString);
+        Wrapper wrapper = new WrapperBuilder().setWrap(topLevel).build();
+        NormalizedNode<?, ?> topLevelEntry = registry.toNormalizedNode(InstanceIdentifier.builder(Wrapper.class).build(), wrapper).getValue();
+
+        ContainerNode containerNode = ImmutableContainerNodeBuilder.create()
+                .withNodeIdentifier(new YangInstanceIdentifier.NodeIdentifier(WRAPPER_QNAME))
+                .withChild(ImmutableNodes.leafNode(WRAP_LEAF_QNAME, testString))
+                .build();
+        Assert.assertEquals(topLevelEntry, containerNode);
+    }
+}
index 270b04ac81161374d337fe03f012d96691939920..86d3bf5e3e3bdd5e3e35ad77d83730e6e27c2b99 100644 (file)
@@ -20,6 +20,7 @@ import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTO
 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.MethodSignatureBuilder;
 import org.opendaylight.yangtools.util.LazyCollections;
 import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 
 public final class GeneratedTOBuilderImpl extends AbstractGeneratedTypeBuilder<GeneratedTOBuilder> implements GeneratedTOBuilder {
 
@@ -30,6 +31,7 @@ public final class GeneratedTOBuilderImpl extends AbstractGeneratedTypeBuilder<G
     private boolean isTypedef = false;
     private boolean isUnionType = false;
     private boolean isUnionTypeBuilder = false;
+    private TypeDefinition baseType = null;
     private Restrictions restrictions;
     private GeneratedPropertyBuilder SUID;
     private String reference;
@@ -140,6 +142,11 @@ public final class GeneratedTOBuilderImpl extends AbstractGeneratedTypeBuilder<G
         this.isTypedef = isTypedef;
     }
 
+    @Override
+    public void setBaseType(final TypeDefinition typeDef) {
+        this.baseType = typeDef;
+    }
+
     @Override
     public void setIsUnion(final boolean isUnion) {
         this.isUnionType = isUnion;
@@ -178,6 +185,7 @@ public final class GeneratedTOBuilderImpl extends AbstractGeneratedTypeBuilder<G
         private final List<GeneratedProperty> stringProperties;
         private final GeneratedTransferObject extendsType;
         private final boolean isTypedef;
+        private final TypeDefinition baseType;
         private final boolean isUnionType;
         private final boolean isUnionTypeBuilder;
         private final Restrictions restrictions;
@@ -198,6 +206,7 @@ public final class GeneratedTOBuilderImpl extends AbstractGeneratedTypeBuilder<G
             this.stringProperties = toUnmodifiableProperties(builder.toStringProperties);
 
             this.isTypedef = builder.isTypedef;
+            this.baseType = builder.baseType;
             this.isUnionType = builder.isUnionType;
             this.isUnionTypeBuilder = builder.isUnionTypeBuilder;
             this.restrictions = builder.restrictions;
@@ -218,6 +227,11 @@ public final class GeneratedTOBuilderImpl extends AbstractGeneratedTypeBuilder<G
             return isTypedef;
         }
 
+        @Override
+        public TypeDefinition getBaseType() {
+            return baseType;
+        }
+
         @Override
         public boolean isUnionType() {
             return isUnionType;
index 8d20831242fc1be9149a80811227def001523ecc..dba7356f9bd68cd61ce72d99407a8bcebc26c28b 100644 (file)
@@ -26,6 +26,7 @@ import org.opendaylight.yangtools.sal.binding.model.api.GeneratedProperty
 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject
 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedType
 import org.opendaylight.yangtools.sal.binding.model.api.Restrictions
+import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition
 import com.google.common.base.Preconditions
 
 /**
@@ -126,6 +127,10 @@ class ClassTemplate extends BaseTemplate {
                 «ENDIF»
             «ENDFOR»
 
+            «IF (genTO.isTypedef() && genTO.getBaseType instanceof BitsTypeDefinition)»
+                «generateGetValueForBitsTypeDef»
+            «ENDIF»
+
             «generateHashCode»
 
             «generateEquals»
@@ -137,6 +142,24 @@ class ClassTemplate extends BaseTemplate {
             «generateRangeMethod("range", "_range")»
 
         }
+
+    '''
+
+    /**
+     * Template method which generates the method <code>getValue()</code> for typedef,
+     * which base type is BitsDefinition.
+     *
+     * @return string with the <code>getValue()</code> method definition in JAVA format
+     */
+    def protected generateGetValueForBitsTypeDef() '''
+
+        public boolean[] getValue() {
+            return new boolean[]{
+            «FOR property: genTO.properties SEPARATOR ','»
+                 «property.fieldName»
+            «ENDFOR»
+            };
+        }
     '''
 
     def private generateLengthMethod(String methodName, String varName) '''
index e6775e9e101b142e85aca1b4eecd6b47438034c5..32130d1cb77ebe06f0abdfee4d2db6cf91459794 100644 (file)
@@ -8,6 +8,7 @@
 package org.opendaylight.yangtools.sal.binding.model.api;
 
 import java.util.List;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 
 /**
  * Generated Transfer Object extends {@link GeneratedType} and is designed to
@@ -64,6 +65,13 @@ public interface GeneratedTransferObject extends GeneratedType {
 
     boolean isTypedef();
 
+    /**
+     * Returns Base type of Java representation of YANG typedef if set, otherwise it returns null
+     *
+     * @return Base type of Java representation of YANG typedef if set, otherwise it returns null
+     */
+    TypeDefinition getBaseType();
+
     /**
      * Return boolean value which describe whether Generated Transfer Object
      * was/wasn't created from union YANG type.
index b80d8eb94eadcb915625ea6cc83957cf6a66f9bd..fb680415a38d107dd9b7a22fe8ece39236419613 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.yangtools.sal.binding.model.api.type.builder;
 
 import org.opendaylight.yangtools.sal.binding.model.api.GeneratedTransferObject;
 import org.opendaylight.yangtools.sal.binding.model.api.Restrictions;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 
 /**
  * Generated Transfer Object Builder is interface that contains methods to build
@@ -78,6 +79,14 @@ public interface GeneratedTOBuilder extends GeneratedTypeBuilderBase<GeneratedTO
 
     void setTypedef(boolean isTypedef);
 
+    /**
+     * Sets the base type for Java representation of YANG typedef
+     *
+     * @param typeDef
+     *           Type Definition
+     */
+    void setBaseType(TypeDefinition typeDef);
+
     /**
      *
      * @param isUnion
diff --git a/code-generator/binding-test-model/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/yangtools/test/union/rev150121/TopLevelBuilder.java b/code-generator/binding-test-model/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/yangtools/test/union/rev150121/TopLevelBuilder.java
new file mode 100644 (file)
index 0000000..09d8e0d
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.union.rev150121;
+
+/**
+ * The purpose of generated class in src/main/java for Union types is to create new instances of unions from a string representation.
+ * In some cases it is very difficult to automate it since there can be unions such as (uint32 - uint16), or (string - uint32).
+ * The reason behind putting it under src/main/java is:
+ * This class is generated in form of a stub and needs to be finished by the user. This class is generated only once to prevent
+ * loss of user code.
+ */
+public class TopLevelBuilder {
+
+    public static TopLevel getDefaultInstance(java.lang.String defaultValue) {
+        if (defaultValue.length() <= 4) {
+            return new TopLevel(new NonUnionTestType(defaultValue));
+        }
+        else {
+            return new TopLevel(UnionTestTypeBuilder.getDefaultInstance(defaultValue));
+        }
+    }
+
+}
diff --git a/code-generator/binding-test-model/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/yangtools/test/union/rev150121/UnionTestTypeBuilder.java b/code-generator/binding-test-model/src/main/java/org/opendaylight/yang/gen/v1/urn/opendaylight/params/xml/ns/yang/yangtools/test/union/rev150121/UnionTestTypeBuilder.java
new file mode 100644 (file)
index 0000000..613f2dc
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * 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.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.yangtools.test.union.rev150121;
+
+/**
+ * The purpose of generated class in src/main/java for Union types is to create new instances of unions from a string representation.
+ * In some cases it is very difficult to automate it since there can be unions such as (uint32 - uint16), or (string - uint32).
+ * 
+ * The reason behind putting it under src/main/java is:
+ * This class is generated in form of a stub and needs to be finished by the user. This class is generated only once to prevent
+ * loss of user code.
+ * 
+ */
+public class UnionTestTypeBuilder {
+
+    public static UnionTestType getDefaultInstance(java.lang.String defaultValue) {
+        if (defaultValue.length() > 8) {
+            return new UnionTestType(new LowestLevel1(defaultValue));
+        } else {
+            return new UnionTestType(new LowestLevel2(defaultValue));
+        }
+    }
+
+}
diff --git a/code-generator/binding-test-model/src/main/yang/opendaylight-yangtools-union-test.yang b/code-generator/binding-test-model/src/main/yang/opendaylight-yangtools-union-test.yang
new file mode 100644 (file)
index 0000000..eea063b
--- /dev/null
@@ -0,0 +1,47 @@
+module opendaylight-yangtools-union-test {
+
+    namespace "urn:opendaylight:params:xml:ns:yang:yangtools:test:union";
+    prefix union-test;
+
+
+    description
+        "This module contains a collection of YANG definitions used for
+        some test cases.";
+
+    revision "2015-01-21" {
+        description
+        "Test model for testing union data types.";
+    }
+
+    typedef lowest-level1 {
+        type string;
+    }
+
+    typedef lowest-level2 {
+        type string;
+    }
+
+    typedef non-union-test-type {
+        type string;
+    }
+
+    typedef union-test-type {
+        type union {
+            type lowest-level1;
+            type lowest-level2;
+        }
+    }
+
+    typedef top-level {
+        type union {
+            type non-union-test-type;
+            type union-test-type;
+        }
+    }
+
+    container wrapper {
+        leaf wrap {
+            type top-level;
+        }
+    }
+}
\ No newline at end of file
index 57038761ee822f92e2b9fe2e689ee817d605c614..b393c13367806ea9fb7211e698906e569ebe421f 100644 (file)
@@ -1099,6 +1099,7 @@ public final class TypeProviderImpl implements TypeProvider {
             genTOBuilder.setReference(typeDef.getReference());
             genTOBuilder.setSchemaPath(typeDef.getPath().getPathFromRoot());
             genTOBuilder.setModuleName(moduleName);
+            genTOBuilder.setBaseType(typeDef);
 
             final List<Bit> bitList = bitsTypeDefinition.getBits();
             GeneratedPropertyBuilder genPropertyBuilder;
index ef3f8c7a26ee9241e939c58e7bcdc8fbab2deb06..3d2643e75b906788376f91728dfec2b0071a6d90 100644 (file)
     <version>0.7.0-SNAPSHOT</version>
     <packaging>pom</packaging>
 
-    <prerequisites>
-        <maven>3.0.4</maven>
-    </prerequisites>
-
     <properties>
         <!-- Model versions -->
         <ietf.topology.version>2013.10.21.7-SNAPSHOT</ietf.topology.version>
index aa81fdde17cdc70434b2e1bfca1b24f604d4e7bb..1637e1f9cbc3ccdde018767b948a28fc700a1094 100644 (file)
         <relativePath>/../../common/parent/pom.xml</relativePath>
     </parent>
 
-
     <modelVersion>4.0.0</modelVersion>
     <artifactId>mockito-configuration</artifactId>
     <description>Default mockito configuration</description>
     <packaging>jar</packaging><!-- not needed in OSGi -->
     <name>${project.artifactId}</name>
-    <prerequisites>
-        <maven>3.0.4</maven>
-    </prerequisites>
 
     <dependencies>
         <!-- all those dependencies will be in test scope as mockito-configuration should be referenced as test scope dependency -->
index a2fa60ee4393d3a59cefdb7d630857e892abe857..da6d96751f002668ae728b04a172538eef061a14 100644 (file)
@@ -22,9 +22,6 @@
     <groupId>org.opendaylight.yangtools</groupId>
     <version>0.7.0-SNAPSHOT</version>
     <packaging>pom</packaging>
-    <prerequisites>
-        <maven>3.0.4</maven>
-    </prerequisites>
 
     <properties>
         <yangtools.version>0.7.0-SNAPSHOT</yangtools.version>
index a2fa589a564e9a130135edf0c6e9d1e2caf2abfb..6156093cf89684131339d108868a6c08c924dd7d 100644 (file)
@@ -339,4 +339,11 @@ public class TypesResolutionTest {
         parser.parseFiles(Arrays.asList(extdef, unionbug, inet));
     }
 
+    @Test
+    public void testUnionWithBits() throws Exception {
+        File unionbits = new File(getClass().getResource("/types/union-with-bits/union-bits-model.yang").toURI());
+        YangContextParser parser = new YangParserImpl();
+        parser.parseFiles(Arrays.asList(unionbits));
+    }
+
 }
diff --git a/yang/yang-parser-impl/src/test/resources/types/union-with-bits/union-bits-model.yang b/yang/yang-parser-impl/src/test/resources/types/union-with-bits/union-bits-model.yang
new file mode 100644 (file)
index 0000000..2c99807
--- /dev/null
@@ -0,0 +1,59 @@
+module unionbitsmodel {
+    namespace "urn:ubt";
+    prefix "ubt";
+
+    revision 2014-12-10 {
+    }
+
+    typedef port-state-v13 {
+        description
+            "Current state of the physical port. These are not configurable from the controller.";
+
+        type bits {
+            bit link_down {
+                //description "No physical link present.";
+                position 0;
+            }
+
+            bit blocked {
+                //description "Port is blocked";
+                position 1;
+            }
+
+            bit live {
+                //description "Live for Fast Failover Group.";
+                position 2;
+            }
+        }
+    }
+
+    typedef port-state-v10 {
+        description "Current state of the physical port. These are not configurable from the controller.";
+
+        type bits {
+            bit link_down {
+                description "No physical link present.";
+                position 0;
+            }
+
+            bit blocked {
+                    description "Port is blocked";
+                    position 1;
+                }
+                bit live {
+                    description "Live for Fast Failover Group.";
+                    position 2;
+                }
+                bit stp_listen {
+                    description "Not learning or relaying frames.";
+                }
+            }
+        }
+
+    typedef my-union-type {
+        type union {
+            type port-state-v13;
+            type port-state-v10;
+        }
+    }
+}
\ No newline at end of file