Merge "Add Anyxml normalized node to yang-data-api."
authorTony Tkacik <ttkacik@cisco.com>
Wed, 18 Jun 2014 10:15:09 +0000 (10:15 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Wed, 18 Jun 2014 10:15:09 +0000 (10:15 +0000)
22 files changed:
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingGeneratorImpl.xtend
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingSchemaContextUtils.java
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/CodecMapping.java
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/LazyGeneratedCodecRegistry.java
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/ModuleContext.java
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/TransformerGenerator.xtend
common/feature/pom.xml [deleted file]
common/features/pom.xml [new file with mode: 0644]
common/features/src/main/resources/features.xml [moved from common/feature/src/main/resources/features.xml with 73% similarity]
common/parent/pom.xml
common/pom.xml
integration-test/bug1196-test-model/pom.xml [new file with mode: 0644]
integration-test/bug1196-test-model/src/main/yang/network-topology-pcep.yang [new file with mode: 0644]
integration-test/bug1196-test-model/src/main/yang/network-topology-unix.yang [new file with mode: 0644]
integration-test/bug1196-test-model/src/main/yang/network-topology@2013-10-21.yang [new file with mode: 0644]
integration-test/bug1196-test-model/src/main/yang/odl-pcep-ietf-stateful07.yang [new file with mode: 0644]
integration-test/bug1196-test-model/src/main/yang/pcep-types.yang [new file with mode: 0644]
integration-test/pom.xml
restconf/restconf-util/pom.xml
restconf/restconf-util/src/test/java/org/opendaylight/yangtools/restconf/utils/Bug1196Test.java [new file with mode: 0644]
restconf/restconf-util/src/test/resources/topology-bug1196-linux.xml [new file with mode: 0644]
restconf/restconf-util/src/test/resources/topology-bug1196-unix.xml [new file with mode: 0644]

index 8a41bef08f88a24889e712412508735e47227f87..ba8259e9b30627c064d1e041312963e4acafb427 100644 (file)
@@ -1148,6 +1148,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
                 val caseTypeBuilder = addDefaultInterfaceDefinition(packageName, caseNode)
                 caseTypeBuilder.addImplementsType(refChoiceType)
                 genCtx.get(module).addCaseType(caseNode.path, caseTypeBuilder)
+                genCtx.get(module).addChoiceToCaseMapping(refChoiceType, caseTypeBuilder,caseNode)
                 val Set<DataSchemaNode> caseChildNodes = caseNode.childNodes
                 if (caseChildNodes !== null) {
                     var Object parentNode = null
@@ -1250,21 +1251,18 @@ public class BindingGeneratorImpl implements BindingGenerator {
                     throw new IllegalArgumentException("Failed to find parent type of choice " + targetNode);
                 }
 
-                if (caseNode instanceof DataNodeContainer) {
-                    val DataNodeContainer dataNodeCase = caseNode as DataNodeContainer;
-                    val Set<DataSchemaNode> childNodes = dataNodeCase.childNodes;
-                    if (childNodes !== null) {
-                        resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, childNodes);
-                    }
-                } else {
-                    val ChoiceCaseNode node = targetNode.getCaseNodeByName(caseNode.getQName().getLocalName());
-                    val Set<DataSchemaNode> childNodes = node.childNodes;
-                    if (childNodes !== null) {
-                        resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, childNodes);
-                    }
+                var ChoiceCaseNode node = null;
+                if (caseNode instanceof ChoiceCaseNode) {
+                    node = caseNode as ChoiceCaseNode;
+                }  else {
+                    node = targetNode.getCaseNodeByName(caseNode.getQName().getLocalName());
+                }
+                val Set<DataSchemaNode> childNodes = node.childNodes;
+                if (childNodes !== null) {
+                    resolveDataSchemaNodes(module, basePackageName, caseTypeBuilder, childOfType, childNodes);
                 }
-
                 genCtx.get(module).addCaseType(caseNode.path, caseTypeBuilder)
+                genCtx.get(module).addChoiceToCaseMapping(targetType, caseTypeBuilder,node);
             }
         }
 
index 6645aba5741a64d4deb339ad2f1cd92dcffb15c2..f0e05f166551189175e454663c14ed605dbb11f4 100644 (file)
@@ -55,7 +55,7 @@ public class BindingSchemaContextUtils {
                 if(pathArguments.hasNext()) {
                     currentArg = pathArguments.next();
                 } else {
-                    return Optional.absent();
+                    return currentContainer;
                 }
             }
             if(ChildOf.class.isAssignableFrom(currentArg.getType()) && BindingReflections.isAugmentationChild(currentArg.getType())) {
index 9a4ce78541f13ed7461bf66153a99a51b2fad3a2..2ef288f79703c09936b77fb486535995db5580b9 100644 (file)
@@ -9,11 +9,10 @@ package org.opendaylight.yangtools.sal.binding.generator.impl;
 
 import java.lang.reflect.Field;
 import java.util.Map;
-
-import org.opendaylight.yangtools.yang.data.impl.codec.IdentityCodec;
-import org.opendaylight.yangtools.yang.data.impl.codec.InstanceIdentifierCodec;
 import org.opendaylight.yangtools.yang.binding.BindingCodec;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.data.impl.codec.IdentityCodec;
+import org.opendaylight.yangtools.yang.data.impl.codec.InstanceIdentifierCodec;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -27,6 +26,7 @@ public class CodecMapping {
     public static final String CLASS_TO_CASE_MAP = "CLASS_TO_CASE";
     public static final String COMPOSITE_TO_CASE = "COMPOSITE_TO_CASE";
     public static final String AUGMENTATION_CODEC = "AUGMENTATION_CODEC";
+    public static final String DISPATCH_CODEC = "DISPATCH_CODEC";
 
     public static void setIdentifierCodec(Class<?> obj,InstanceIdentifierCodec codec) {
         Field instanceIdField;
@@ -82,6 +82,19 @@ public class CodecMapping {
         }
     }
 
+    public static void setDispatchCodec(Class<? extends BindingCodec<?,?>> codec,
+            BindingCodec<?, ?> dispatchCodec) {
+        Field instanceIdField;
+        try {
+            instanceIdField = codec.getField(DISPATCH_CODEC);
+            instanceIdField.set(null, dispatchCodec);
+        } catch (NoSuchFieldException e) {
+            LOG.debug("BUG: dispatch codec is not needed for {}",codec.getName(),e);
+        } catch (SecurityException | IllegalAccessException e) {
+            LOG.error("Dispatch codec could not be set for {}",codec.getName(),e);
+        }
+    }
+
     public static void setAugmentationCodec(Class<? extends BindingCodec<?,?>> dataCodec,
             BindingCodec<?,?> augmentableCodec) {
             Field instanceIdField;
index e62f28e6469f2ad1f9a2af9e319b7ca92650ec4a..f857c0d7315adaf4d9e9704cb601513bc8d2887a 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.yangtools.sal.binding.generator.impl;
 
 import java.lang.ref.WeakReference;
 import java.lang.reflect.Field;
+import java.util.AbstractMap.SimpleEntry;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -18,7 +19,6 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
-import java.util.Objects;
 import java.util.Set;
 import java.util.WeakHashMap;
 import java.util.concurrent.ConcurrentHashMap;
@@ -33,7 +33,6 @@ import org.opendaylight.yangtools.sal.binding.generator.util.CodeGenerationExcep
 import org.opendaylight.yangtools.sal.binding.model.api.ConcreteType;
 import org.opendaylight.yangtools.sal.binding.model.api.Type;
 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTOBuilder;
-import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder;
 import org.opendaylight.yangtools.yang.binding.Augmentable;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
 import org.opendaylight.yangtools.yang.binding.BaseIdentity;
@@ -69,7 +68,6 @@ import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaContextListener;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
-import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -78,6 +76,7 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.BiMap;
 import com.google.common.collect.HashBiMap;
 import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Iterables;
 import com.google.common.collect.Multimap;
 import com.google.common.collect.Multimaps;
 
@@ -87,7 +86,6 @@ class LazyGeneratedCodecRegistry implements //
         GeneratorListener {
 
     private static final Logger LOG = LoggerFactory.getLogger(LazyGeneratedCodecRegistry.class);
-    private static final LateMixinCodec NOT_READY_CODEC = new LateMixinCodec();
 
     // Concrete class to codecs
     private static final Map<Class<?>, DataContainerCodec<?>> containerCodecs = Collections
@@ -109,8 +107,7 @@ class LazyGeneratedCodecRegistry implements //
     @SuppressWarnings("rawtypes")
     private static final Map<Type, WeakReference<Class>> typeToClass = new ConcurrentHashMap<>();
 
-    @SuppressWarnings("rawtypes")
-    private static final ConcurrentMap<Type, ChoiceCaseCodecImpl> typeToCaseCodecs = new ConcurrentHashMap<>();
+    private static final ConcurrentMap<Type, ChoiceCaseNode> caseTypeToCaseSchema = new ConcurrentHashMap<>();
 
     private static final Map<SchemaPath, Type> pathToType = new ConcurrentHashMap<>();
     private static final Map<List<QName>, Type> pathToInstantiatedType = new ConcurrentHashMap<>();
@@ -124,7 +121,6 @@ class LazyGeneratedCodecRegistry implements //
             .<Type, Type> create());
 
     private final InstanceIdentifierCodec instanceIdentifierCodec = new InstanceIdentifierCodecImpl(this);
-    private final CaseClassMapFacade classToCaseRawCodec = new CaseClassMapFacade();
     private final IdentityCompositeCodec identityRefCodec = new IdentityCompositeCodec();
     private final ClassLoadingStrategy classLoadingStrategy;
     private final AbstractTransformerGenerator generator;
@@ -392,22 +388,14 @@ class LazyGeneratedCodecRegistry implements //
             return potential;
         }
         ConcreteType typeref = Types.typeForClass(caseClass);
-        ChoiceCaseCodecImpl caseCodec = typeToCaseCodecs.get(typeref);
+        ChoiceCaseNode caseSchema = caseTypeToCaseSchema.get(typeref);
 
-        Preconditions.checkState(caseCodec != null, "Case Codec was not created proactivelly for %s",
-                caseClass.getName());
-        Preconditions.checkState(caseCodec.getSchema() != null, "Case schema is not available for %s",
-                caseClass.getName());
-        Class<? extends BindingCodec> newCodec = generator.caseCodecFor(caseClass, caseCodec.getSchema());
+        Preconditions.checkState(caseSchema != null, "Case schema is not available for %s", caseClass.getName());
+        Class<? extends BindingCodec> newCodec = generator.caseCodecFor(caseClass, caseSchema);
         BindingCodec newInstance = newInstanceOf(newCodec);
-        caseCodec.setDelegate(newInstance);
+        @SuppressWarnings("unchecked")
+        ChoiceCaseCodecImpl caseCodec = new ChoiceCaseCodecImpl(caseClass, caseSchema, newInstance);
         caseCodecs.put(caseClass, caseCodec);
-
-        for (Entry<Class<?>, PublicChoiceCodecImpl<?>> choice : choiceCodecs.entrySet()) {
-            if (choice.getKey().isAssignableFrom(caseClass)) {
-                choice.getValue().cases.put(caseClass, caseCodec);
-            }
-        }
         return caseCodec;
     }
 
@@ -437,29 +425,8 @@ class LazyGeneratedCodecRegistry implements //
         synchronized (choiceToCases) {
             choiceToCases.putAll(context.getChoiceToCases());
         }
-        captureCases(context.getCases(), schemaContext);
-    }
-
-    private void captureCases(final Map<SchemaPath, GeneratedTypeBuilder> cases, final SchemaContext module) {
-        for (Entry<SchemaPath, GeneratedTypeBuilder> caseNode : cases.entrySet()) {
-            ReferencedTypeImpl typeref = new ReferencedTypeImpl(caseNode.getValue().getPackageName(), caseNode
-                    .getValue().getName());
-
-            pathToType.put(caseNode.getKey(), caseNode.getValue());
-
-            ChoiceCaseNode node = (ChoiceCaseNode) SchemaContextUtil.findDataSchemaNode(module, caseNode.getKey());
-
-            if (node == null) {
-                LOG.warn("Failed to find YANG SchemaNode for {}, with path {} was not found in context.",
-                        typeref.getFullyQualifiedName(), caseNode.getKey());
-                @SuppressWarnings("rawtypes")
-                ChoiceCaseCodecImpl value = new ChoiceCaseCodecImpl();
-                typeToCaseCodecs.putIfAbsent(typeref, value);
-                continue;
-            }
-            @SuppressWarnings("rawtypes")
-            ChoiceCaseCodecImpl value = new ChoiceCaseCodecImpl(node);
-            typeToCaseCodecs.putIfAbsent(typeref, value);
+        synchronized (caseTypeToCaseSchema) {
+            caseTypeToCaseSchema.putAll(context.getCaseTypeToSchemas());
         }
     }
 
@@ -476,43 +443,9 @@ class LazyGeneratedCodecRegistry implements //
         Preconditions.checkState(oldCodec == null);
         BindingCodec<Map<QName, Object>, Object> delegate = newInstanceOf(choiceCodec);
         PublicChoiceCodecImpl<?> newCodec = new PublicChoiceCodecImpl(delegate);
+        DispatchChoiceCodecImpl dispatchCodec = new DispatchChoiceCodecImpl(choiceClass);
         choiceCodecs.put(choiceClass, newCodec);
-        CodecMapping.setClassToCaseMap(choiceCodec, classToCaseRawCodec);
-        CodecMapping.setCompositeNodeToCaseMap(choiceCodec, newCodec.getCompositeToCase());
-
-        tryToCreateCasesCodecs(schema);
-
-    }
-
-    @Deprecated
-    private void tryToCreateCasesCodecs(final ChoiceNode schema) {
-        for (ChoiceCaseNode choiceCase : schema.getCases()) {
-            ChoiceCaseNode caseNode = choiceCase;
-            if (caseNode.isAddedByUses()) {
-                DataSchemaNode origCaseNode = SchemaContextUtil.findOriginal(caseNode, currentSchema);
-                if (origCaseNode instanceof ChoiceCaseNode) {
-                    caseNode = (ChoiceCaseNode) origCaseNode;
-                }
-            }
-            SchemaPath path = caseNode.getPath();
-
-            Type type;
-            if (path != null && (type = pathToType.get(path)) != null) {
-                ReferencedTypeImpl typeref = new ReferencedTypeImpl(type.getPackageName(), type.getName());
-                @SuppressWarnings("rawtypes")
-                ChoiceCaseCodecImpl partialCodec = typeToCaseCodecs.get(typeref);
-                if (partialCodec.getSchema() == null) {
-                    partialCodec.setSchema(caseNode);
-                }
-                try {
-                    Class<?> caseClass = classLoadingStrategy.loadClass(type.getFullyQualifiedName());
-                    getCaseCodecFor(caseClass);
-                } catch (ClassNotFoundException e) {
-                    LOG.trace("Could not proactivelly create case codec for {}", type, e);
-                }
-            }
-        }
-
+        CodecMapping.setDispatchCodec(choiceCodec, dispatchCodec);
     }
 
     @Override
@@ -734,41 +667,22 @@ class LazyGeneratedCodecRegistry implements //
     @SuppressWarnings("rawtypes")
     private static class ChoiceCaseCodecImpl<T extends DataContainer> implements ChoiceCaseCodec<T>, //
             Delegator<BindingCodec>, LocationAwareBindingCodec<Node<?>, ValueWithQName<T>> {
-        private boolean augmenting;
-        private boolean uses;
-        private BindingCodec delegate;
-
-        private Set<String> validNames;
-        private Set<QName> validQNames;
-        private ChoiceCaseNode schema;
-        private Set<InstanceIdentifier<?>> applicableLocations;
+        private final BindingCodec delegate;
+        private final ChoiceCaseNode schema;
+        private final Map<InstanceIdentifier<?>, ChoiceCaseNode> instantiatedLocations;
+        private final Class<?> dataType;
 
         @Override
         public boolean isApplicable(final InstanceIdentifier location) {
-            return applicableLocations.contains(location);
+            return instantiatedLocations.containsKey(location);
         }
 
-        public void setSchema(final ChoiceCaseNode caseNode) {
+        public ChoiceCaseCodecImpl(final Class<?> caseClass, final ChoiceCaseNode caseNode,
+                final BindingCodec newInstance) {
+            this.delegate = newInstance;
+            this.dataType = caseClass;
             this.schema = caseNode;
-            validNames = new HashSet<>();
-            validQNames = new HashSet<>();
-            for (DataSchemaNode node : caseNode.getChildNodes()) {
-                QName qname = node.getQName();
-                validQNames.add(qname);
-                validNames.add(qname.getLocalName());
-            }
-            augmenting = caseNode.isAugmenting();
-            uses = caseNode.isAddedByUses();
-            applicableLocations = new HashSet<>();
-        }
-
-        public ChoiceCaseCodecImpl() {
-            this.delegate = NOT_READY_CODEC;
-        }
-
-        public ChoiceCaseCodecImpl(final ChoiceCaseNode caseNode) {
-            this.delegate = NOT_READY_CODEC;
-            setSchema(caseNode);
+            instantiatedLocations = new HashMap<>();
         }
 
         @Override
@@ -778,7 +692,19 @@ class LazyGeneratedCodecRegistry implements //
 
         @Override
         public ValueWithQName<T> deserialize(final Node<?> input, final InstanceIdentifier<?> bindingIdentifier) {
-            throw new UnsupportedOperationException("Direct invocation of this codec is not allowed.");
+            if (input == null) {
+                return null;
+            }
+            QName qname = input.getNodeType();
+            synchronized (instantiatedLocations) {
+                ChoiceCaseNode instantiation = instantiatedLocations.get(bindingIdentifier);
+                if (instantiation != null) {
+                    qname = instantiatedLocations.get(bindingIdentifier).getQName();
+                }
+            }
+            @SuppressWarnings("unchecked")
+            T value = (T) getDelegate().deserialize(new SimpleEntry(qname, input), bindingIdentifier);
+            return new ValueWithQName<T>(qname, value);
         }
 
         @Override
@@ -791,56 +717,75 @@ class LazyGeneratedCodecRegistry implements //
             return delegate;
         }
 
-        public void setDelegate(final BindingCodec delegate) {
-            this.delegate = delegate;
-        }
-
         public ChoiceCaseNode getSchema() {
             return schema;
         }
 
         @Override
+        @Deprecated
         public boolean isAcceptable(final Node<?> input) {
-            if (input instanceof CompositeNode) {
-                if (augmenting && !uses) {
-                    return checkAugmenting((CompositeNode) input);
-                } else {
-                    return checkLocal((CompositeNode) input);
+            return checkAgainstSchema(schema, input);
+        }
+
+        private static boolean checkAgainstSchema(final ChoiceCaseNode schema, final Node<?> node) {
+            if (node instanceof CompositeNode) {
+                CompositeNode input = (CompositeNode) node;
+                for (Node<?> childNode : input.getValue()) {
+                    QName child = childNode.getNodeType();
+                    if (schema.getDataChildByName(child) != null) {
+                        return true;
+                    }
                 }
             }
             return false;
         }
 
-        @SuppressWarnings("deprecation")
-        private boolean checkLocal(final CompositeNode input) {
-            QName parent = input.getNodeType();
-            for (Node<?> childNode : input.getChildren()) {
-                QName child = childNode.getNodeType();
-                if (!Objects.equals(parent.getNamespace(), child.getNamespace())
-                        || !Objects.equals(parent.getRevision(), child.getRevision())) {
-                    continue;
-                }
-                if (validNames.contains(child.getLocalName())) {
-                    return true;
-                }
+        @Override
+        public Class<?> getDataType() {
+            return dataType;
+        }
+
+        public void adaptForPath(final InstanceIdentifier<?> augTarget, final ChoiceCaseNode choiceCaseNode) {
+            synchronized (instantiatedLocations) {
+                instantiatedLocations.put(augTarget, choiceCaseNode);
             }
-            return false;
         }
 
-        @SuppressWarnings("deprecation")
-        private boolean checkAugmenting(final CompositeNode input) {
-            for (Node<?> child : input.getChildren()) {
-                if (validQNames.contains(child.getNodeType())) {
-                    return true;
-                }
+        public boolean isAcceptable(final InstanceIdentifier path, final CompositeNode input) {
+            ChoiceCaseNode instantiatedSchema = null;
+            synchronized (instantiatedLocations) {
+                instantiatedSchema = instantiatedLocations.get(path);
             }
-            return false;
+            if (instantiatedSchema == null) {
+                return false;
+            }
+            return checkAgainstSchema(instantiatedSchema, input);
         }
 
-        @Override
-        public Class<?> getDataType() {
-            // TODO Auto-generated method stub
-            throw new UnsupportedOperationException("Not implemented Yet.");
+        protected boolean isAugmenting(final QName choiceName,final QName proposedQName) {
+            if (schema.isAugmenting()) {
+                return true;
+            }
+            // Choice QName
+            QName parentQName = Iterables.get(schema.getPath().getPathTowardsRoot(), 1);
+            if (!parentQName.getNamespace().equals(schema.getQName().getNamespace())) {
+                return true;
+            }
+            if (!parentQName.equals(choiceName)) {
+                // This item is instantiation of choice via uses in other YANG module
+                if(choiceName.getNamespace().equals(schema.getQName())) {
+                    // Original definition of grouping is in same namespace
+                    // as original definition of case
+                    // so for sure case is introduced via instantiation of grouping
+                    return false;
+                }
+                // Since we are still here, that means case has same namespace
+                // as its parent, which is instantiation of grouping
+                // but case namespace is different from parent node
+                // so it is augmentation.
+                return true;
+            }
+            return false;
         }
     }
 
@@ -849,15 +794,8 @@ class LazyGeneratedCodecRegistry implements //
 
         private final BindingCodec<Map<QName, Object>, Object> delegate;
 
-        @SuppressWarnings("rawtypes")
-        private final Map<Class, ChoiceCaseCodecImpl<?>> cases = Collections
-                .synchronizedMap(new WeakHashMap<Class, ChoiceCaseCodecImpl<?>>());
-
-        private final CaseCompositeNodeMapFacade CompositeToCase;
-
         public PublicChoiceCodecImpl(final BindingCodec<Map<QName, Object>, Object> delegate) {
             this.delegate = delegate;
-            this.CompositeToCase = new CaseCompositeNodeMapFacade(cases);
         }
 
         @Override
@@ -875,10 +813,6 @@ class LazyGeneratedCodecRegistry implements //
             throw new UnsupportedOperationException("Direct invocation of this codec is not allowed.");
         }
 
-        public CaseCompositeNodeMapFacade getCompositeToCase() {
-            return CompositeToCase;
-        }
-
         @Override
         public BindingCodec<Map<QName, Object>, Object> getDelegate() {
             return delegate;
@@ -886,163 +820,134 @@ class LazyGeneratedCodecRegistry implements //
 
     }
 
-    @SuppressWarnings("unused")
-    private class DispatchChoiceCodecImpl extends LocationAwareDispatchCodec<ChoiceCaseCodecImpl<?>> {
-
-        @Override
-        public Object deserialize(final Object input,
-                @SuppressWarnings("rawtypes") final InstanceIdentifier bindingIdentifier) {
-            // TODO Auto-generated method stub
-            return null;
-        }
-
-        @Override
-        public Object serialize(final Object input) {
-            // TODO Auto-generated method stub
-            return null;
-        }
-
-        @Override
-        protected ChoiceCaseCodecImpl<?> tryToLoadImplementation(final Class<? extends DataContainer> inputType) {
-            return getCaseCodecFor(inputType);
-        }
-
-        @Override
-        protected void tryToLoadImplementations() {
-            // TODO Auto-generated method stub
-
-        }
-
-        @Override
-        protected void adaptForPathImpl(final InstanceIdentifier<?> path, final DataNodeContainer ctx) {
-            // TODO Auto-generated method stub
+    class DispatchChoiceCodecImpl extends LocationAwareDispatchCodec<ChoiceCaseCodecImpl<?>> {
+        private final Class<?> choiceType;
+        private final QName choiceName;
 
+        private DispatchChoiceCodecImpl(final Class<?> type) {
+            choiceType = type;
+            choiceName = BindingReflections.findQName(type);
         }
-    }
-
-    @SuppressWarnings("rawtypes")
-    private class CaseClassMapFacade extends MapFacadeBase {
 
         @Override
-        public Set<Entry<Class, BindingCodec<Object, Object>>> entrySet() {
-            return Collections.emptySet();
-        }
-
-        @Override
-        public BindingCodec get(final Object key) {
-            if (key instanceof Class) {
-                Class cls = (Class) key;
-                // bindingClassEncountered(cls);
-                ChoiceCaseCodecImpl caseCodec = getCaseCodecFor(cls);
-                return caseCodec.getDelegate();
-            }
-            return null;
-        }
-    }
-
-    @SuppressWarnings("rawtypes")
-    private static class CaseCompositeNodeMapFacade extends MapFacadeBase<CompositeNode> {
-
-        final Map<Class, ChoiceCaseCodecImpl<?>> choiceCases;
-
-        public CaseCompositeNodeMapFacade(final Map<Class, ChoiceCaseCodecImpl<?>> choiceCases) {
-            this.choiceCases = choiceCases;
-        }
+        public Object deserialize(final Object input, @SuppressWarnings("rawtypes") final InstanceIdentifier path) {
+            adaptForPath(path);
 
-        @Override
-        public BindingCodec get(final Object key) {
-            if (!(key instanceof CompositeNode)) {
-                return null;
-            }
-            for (Entry<Class, ChoiceCaseCodecImpl<?>> entry : choiceCases.entrySet()) {
-                ChoiceCaseCodecImpl<?> codec = entry.getValue();
-                if (codec.isAcceptable((CompositeNode) key)) {
-                    return codec.getDelegate();
+            if (input instanceof CompositeNode) {
+                List<Entry<Class, ChoiceCaseCodecImpl<?>>> codecs = new ArrayList<>(getImplementations().entrySet());
+                for (Entry<Class, ChoiceCaseCodecImpl<?>> codec : codecs) {
+                    ChoiceCaseCodecImpl<?> caseCodec = codec.getValue();
+                    if (caseCodec.isAcceptable(path, (CompositeNode) input)) {
+                        ValueWithQName<?> value = caseCodec.deserialize((CompositeNode) input, path);
+                        if (value != null) {
+                            return value.getValue();
+                        }
+                        return null;
+                    }
                 }
             }
             return null;
         }
 
-    }
-
-    /**
-     * This map is used as only facade for
-     * {@link org.opendaylight.yangtools.yang.binding.BindingCodec} in different
-     * classloaders to retrieve codec dynamicly based on provided key.
-     *
-     * @param <T>
-     *            Key type
-     */
-    @SuppressWarnings("rawtypes")
-    private abstract static class MapFacadeBase<T> implements Map<T, BindingCodec<?, ?>> {
-
-        @Override
-        public boolean containsKey(final Object key) {
-            return get(key) != null;
-        }
-
-        @Override
-        public void clear() {
-            throw notModifiable();
-        }
-
-        @Override
-        public boolean equals(final Object obj) {
-            return super.equals(obj);
-        }
-
+        @SuppressWarnings("unchecked")
         @Override
-        public BindingCodec remove(final Object key) {
-            return null;
+        public Object serialize(final Object input) {
+            Preconditions.checkArgument(input instanceof Map.Entry<?, ?>, "Input must be QName, Value");
+            @SuppressWarnings("rawtypes")
+            QName derivedQName =  (QName) ((Map.Entry) input).getKey();
+                    @SuppressWarnings("rawtypes")
+            Object inputValue = ((Map.Entry) input).getValue();
+            Preconditions.checkArgument(inputValue instanceof DataObject);
+            Class<? extends DataContainer> inputType = ((DataObject) inputValue).getImplementedInterface();
+            ChoiceCaseCodecImpl<?> codec = tryToLoadImplementation(inputType);
+            Preconditions.checkState(codec != null, "Unable to get codec for %s", inputType);
+            if (codec.isAugmenting(choiceName,derivedQName)) {
+                // If choice is augmenting we use QName which defined this
+                // augmentation
+                return codec.getDelegate().serialize(new ValueWithQName<>(codec.getSchema().getQName(), inputValue));
+            }
+            return codec.getDelegate().serialize(input);
         }
 
-        @Override
-        public int size() {
-            return 0;
-        }
 
-        @Override
-        public Collection<BindingCodec<?, ?>> values() {
-            return Collections.emptySet();
-        }
 
-        private UnsupportedOperationException notModifiable() {
-            return new UnsupportedOperationException("Not externally modifiable.");
+        @SuppressWarnings("rawtypes")
+        protected Optional<ChoiceCaseCodecImpl> tryToLoadImplementation(final Type potential) {
+            try {
+                @SuppressWarnings("unchecked")
+                Class<? extends DataContainer> clazz = (Class<? extends DataContainer>) classLoadingStrategy
+                        .loadClass(potential);
+                ChoiceCaseCodecImpl codec = tryToLoadImplementation(clazz);
+                addImplementation(codec);
+                return Optional.of(codec);
+            } catch (ClassNotFoundException e) {
+                LOG.warn("Failed to find class for choice {}", potential, e);
+            }
+            return Optional.absent();
         }
 
         @Override
-        public BindingCodec<Map<QName, Object>, Object> put(final T key, final BindingCodec<?, ?> value) {
-            throw notModifiable();
+        protected ChoiceCaseCodecImpl<?> tryToLoadImplementation(final Class<? extends DataContainer> inputType) {
+            ChoiceCaseCodecImpl<?> codec = getCaseCodecFor(inputType);
+            addImplementation(codec);
+            return codec;
         }
 
         @Override
-        public void putAll(final Map<? extends T, ? extends BindingCodec<?, ?>> m) {
-            throw notModifiable();
+        protected void tryToLoadImplementations() {
+            Type type = referencedType(choiceType);
+            Collection<Type> potentialCases;
+            synchronized (choiceToCases) {
+                potentialCases = choiceToCases.get(type);
+            }
+            for (Type potential : potentialCases) {
+                try {
+                    tryToLoadImplementation(potential);
+                } catch (CodeGenerationException e) {
+                    LOG.warn("Failed to proactively generate choice code for {}", type, e);
+                }
+            }
         }
 
         @Override
-        public int hashCode() {
-            return super.hashCode();
+        protected void adaptForPathImpl(final InstanceIdentifier<?> augTarget, final DataNodeContainer ctxNode) {
+            Optional<ChoiceNode> newChoice = findInstantiatedChoice(ctxNode, choiceName);
+            tryToLoadImplementations();
+            Preconditions.checkState(newChoice.isPresent(), "BUG: Unable to find instantiated choice node in schema.");
+            for (@SuppressWarnings("rawtypes")
+            Entry<Class, ChoiceCaseCodecImpl<?>> codec : getImplementations().entrySet()) {
+                ChoiceCaseCodecImpl<?> caseCodec = codec.getValue();
+                Optional<ChoiceCaseNode> instantiatedSchema = findInstantiatedCase(newChoice.get(),
+                        caseCodec.getSchema());
+                if (instantiatedSchema.isPresent()) {
+                    caseCodec.adaptForPath(augTarget, instantiatedSchema.get());
+                }
+            }
         }
 
-        @Override
-        public boolean isEmpty() {
-            return true;
-        }
+        private Optional<ChoiceNode> findInstantiatedChoice(final DataNodeContainer ctxNode, final QName choiceName) {
+            DataSchemaNode potential = ctxNode.getDataChildByName(choiceName);
+            if (potential == null) {
+                potential = ctxNode.getDataChildByName(choiceName.getLocalName());
+            }
 
-        @Override
-        public Set<T> keySet() {
-            return Collections.emptySet();
-        }
+            if (potential instanceof ChoiceNode) {
+                return Optional.of((ChoiceNode) potential);
+            }
 
-        @Override
-        public Set<Entry<T, BindingCodec<?, ?>>> entrySet() {
-            return Collections.emptySet();
+            return Optional.absent();
         }
 
-        @Override
-        public boolean containsValue(final Object value) {
-            return false;
+        private Optional<ChoiceCaseNode> findInstantiatedCase(final ChoiceNode newChoice, final ChoiceCaseNode schema) {
+            ChoiceCaseNode potential = newChoice.getCaseNodeByName(schema.getQName());
+            if (potential != null) {
+                return Optional.of(potential);
+            }
+            // FIXME: Probably requires more extensive check
+            // e.g. we have one choice and two augmentations from different
+            // modules using same local name
+            // but different namespace / contents
+            return Optional.fromNullable(newChoice.getCaseNodeByName(schema.getQName().getLocalName()));
         }
     }
 
@@ -1169,8 +1074,7 @@ class LazyGeneratedCodecRegistry implements //
          *
          * Adaptation consists of:
          * <ol>
-         * <li> scan of available (valid) augmentations for
-         * current location
+         * <li>scan of available (valid) augmentations for current location
          * <li>lookup for Java classes derived from this augmentations
          * <li>generation of missing codecs
          * <li>updating Augmentation codecs to work with new location
@@ -1190,27 +1094,27 @@ class LazyGeneratedCodecRegistry implements //
                         InstanceIdentifier augPath = augTarget.augmentation(augType);
                         try {
 
-                            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath = getInstanceIdentifierCodec().serialize(augPath);
-                            if(domPath == null) {
-                                LOG.error("Unable to serialize instance identifier for {}",augPath);
+                            org.opendaylight.yangtools.yang.data.api.InstanceIdentifier domPath = getInstanceIdentifierCodec()
+                                    .serialize(augPath);
+                            if (domPath == null) {
+                                LOG.error("Unable to serialize instance identifier for {}", augPath);
                             }
                         } catch (Exception e) {
-                            LOG.error("Unable to serialize instance identifiers for {}",augPath,e);
+                            LOG.error("Unable to serialize instance identifiers for {}", augPath, e);
                         }
 
                     }
                 } else {
-                    // Omits warning for empty augmentations since they are not represented in data
-                    if(!aug.getChildNodes().isEmpty()) {
+                    // Omits warning for empty augmentations since they are not
+                    // represented in data
+                    if (!aug.getChildNodes().isEmpty()) {
                         LOG.warn("Could not find generated type for augmentation {} with children {}", aug,
-                            aug.getChildNodes());
+                                aug.getChildNodes());
                     }
                 }
             }
         }
 
-
-
         private Type getTypeForAugmentation(final AugmentationSchema aug) {
             Optional<AugmentationSchema> currentAug = Optional.of(aug);
             while (currentAug.isPresent()) {
@@ -1224,36 +1128,6 @@ class LazyGeneratedCodecRegistry implements //
         }
     }
 
-    @SuppressWarnings({ "rawtypes", "unchecked" })
-    private static class LateMixinCodec implements BindingCodec, Delegator<BindingCodec> {
-
-        private BindingCodec delegate;
-
-        @Override
-        public BindingCodec getDelegate() {
-            if (delegate == null) {
-                throw new IllegalStateException("Codec not initialized yet.");
-            }
-            return delegate;
-        }
-
-        @Override
-        public Object deserialize(final Object input) {
-            return getDelegate().deserialize(input);
-        }
-
-        @Override
-        public Object deserialize(final Object input, final InstanceIdentifier bindingIdentifier) {
-            return getDelegate().deserialize(input, bindingIdentifier);
-        }
-
-        @Override
-        public Object serialize(final Object input) {
-            return getDelegate().serialize(input);
-        }
-
-    }
-
     @SuppressWarnings("rawtypes")
     private static class AugmentationCodecWrapper<T extends Augmentation<?>> implements AugmentationCodec<T>,
             Delegator<BindingCodec>, LocationAwareBindingCodec<Node<?>, ValueWithQName<T>> {
index 48b6947f9a0627b7cab2862561c2115788bf1d05..acb939d14962f0df818af2950bb1e8b5a1c35ede 100644 (file)
@@ -7,25 +7,24 @@
  */
 package org.opendaylight.yangtools.sal.binding.generator.impl;
 
+import com.google.common.collect.BiMap;
+import com.google.common.collect.HashBiMap;
+import com.google.common.collect.HashMultimap;
+import com.google.common.collect.Multimap;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-
 import org.opendaylight.yangtools.sal.binding.model.api.Type;
 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTOBuilder;
 import org.opendaylight.yangtools.sal.binding.model.api.type.builder.GeneratedTypeBuilder;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
+import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 
-import com.google.common.collect.BiMap;
-import com.google.common.collect.HashBiMap;
-import com.google.common.collect.HashMultimap;
-import com.google.common.collect.Multimap;
-
 public final class ModuleContext {
     private GeneratedTypeBuilder moduleNode;
     private final List<GeneratedTOBuilder> genTOs = new ArrayList<GeneratedTOBuilder>();
@@ -39,6 +38,7 @@ public final class ModuleContext {
     private final BiMap<Type,AugmentationSchema> typeToAugmentation = HashBiMap.create();
 
     private final Multimap<Type, Type> choiceToCases = HashMultimap.create();
+    private final BiMap<Type,ChoiceCaseNode> caseTypeToSchema = HashBiMap.create();
 
     private final Multimap<Type, Type> augmentableToAugmentations = HashMultimap.create();
 
@@ -178,4 +178,13 @@ public final class ModuleContext {
         augmentableToAugmentations.put(target,augmentation);
     }
 
+    public void addChoiceToCaseMapping(Type choiceType, Type caseType, ChoiceCaseNode schema) {
+        choiceToCases.put(choiceType, caseType);
+        caseTypeToSchema.put(caseType, schema);
+    }
+
+    public BiMap<Type, ChoiceCaseNode> getCaseTypeToSchemas() {
+        return caseTypeToSchema;
+    }
+
 }
index 8821411022763d504a06e3fd9f1078005b898ee0..792b0b9cc3d1cc470d4d463d7dfb7a79e2b30102 100644 (file)
@@ -625,8 +625,7 @@ class TransformerGenerator extends AbstractTransformerGenerator {
                 //staticQNameField(inputType);
                 staticField(it, INSTANCE_IDENTIFIER_CODEC, BindingCodec)
                 staticField(it, IDENTITYREF_CODEC, BindingCodec)
-                staticField(it, CLASS_TO_CASE_MAP, Map)
-                staticField(it, COMPOSITE_TO_CASE, Map)
+                staticField(it, DISPATCH_CODEC, BindingCodec)
                 //staticField(it,QNAME_TO_CASE_MAP,BindingCodec)
                 implementsType(BINDING_CODEC)
                 method(List, "toDomStatic", #[QName, Object]) [
@@ -636,14 +635,11 @@ class TransformerGenerator extends AbstractTransformerGenerator {
                             if($2 == null) {
                                 return null;
                             }
-                            Â«DataObject.name» _baValue = («DataObject.name») $2;
-                            Class _baClass = _baValue.getImplementedInterface();
-                            Â«BINDING_CODEC.name» _codec =  Â«CLASS_TO_CASE_MAP».get(_baClass);
-                            if(_codec == null) {
-                                return null;
+                            if («DISPATCH_CODEC» == null) {
+                                throw new Â«IllegalStateException.name»("Implementation of codec was not initialized.");
                             }
-                            java.util.Map.Entry _input = new Â«SimpleEntry.name»($1,_baValue);
-                            Object _ret =  _codec.serialize(_input);
+                            java.util.Map.Entry _input = new Â«SimpleEntry.name»($1,$2);
+                            Object _ret =  Â«DISPATCH_CODEC».serialize(_input);
                             ////System.out.println("«typeSpec.name»#toDomStatic: " + _ret);
                             return («List.name») _ret;
                         }
@@ -658,11 +654,10 @@ class TransformerGenerator extends AbstractTransformerGenerator {
                     modifiers = PUBLIC + FINAL + STATIC
                     bodyChecked = '''
                         {
-                            Â«BINDING_CODEC.name» _codec = («BINDING_CODEC.name») Â«COMPOSITE_TO_CASE».get($2);
-                            if(_codec != null) {
-                                return _codec.deserialize(new Â«SimpleEntry.name»($1,$2),$3);
+                            if («DISPATCH_CODEC» == null) {
+                                throw new Â«IllegalStateException.name»("Implementation of codec was not initialized.");
                             }
-                            return null;
+                            return Â«DISPATCH_CODEC».deserialize($2,$3);
                         }
                     '''
                 ]
diff --git a/common/feature/pom.xml b/common/feature/pom.xml
deleted file mode 100644 (file)
index b07506b..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- vi: set et smarttab sw=4 tabstop=4: -->
-<!--
- Copyright (c) 2014 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
--->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
-    <modelVersion>4.0.0</modelVersion>
-
-    <parent>
-        <groupId>org.opendaylight.yangtools</groupId>
-        <artifactId>yangtools-parent</artifactId>
-        <version>0.6.2-SNAPSHOT</version>
-        <relativePath>/../../common/parent/pom.xml</relativePath>
-    </parent>
-
-    <artifactId>features-file</artifactId>
-    <packaging>pom</packaging>
-
-    <properties>
-        <features.file>features.xml</features.file>
-    </properties>
-
-    <build>
-        <resources>
-            <resource>
-                <directory>src/main/resources</directory>
-                <filtering>true</filtering>
-            </resource>
-        </resources>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-resources-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>filter</id>
-                        <phase>generate-resources</phase>
-                        <goals>
-                            <goal>resources</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.codehaus.mojo</groupId>
-                <artifactId>build-helper-maven-plugin</artifactId>
-                <executions>
-                    <execution>
-                        <id>attach-artifacts</id>
-                        <phase>package</phase>
-                        <goals>
-                            <goal>attach-artifact</goal>
-                        </goals>
-                        <configuration>
-                            <artifacts>
-                                <artifact>
-                                    <file>${project.build.directory}/classes/${features.file}</file>
-                                    <type>xml</type>
-                                    <classifier>features</classifier>
-                                </artifact>
-                            </artifacts>
-                        </configuration>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
-</project>
-
diff --git a/common/features/pom.xml b/common/features/pom.xml
new file mode 100644 (file)
index 0000000..e8ad432
--- /dev/null
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!--
+ Copyright (c) 2014 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
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+   <modelVersion>4.0.0</modelVersion>
+   <parent>
+      <groupId>org.opendaylight.yangtools</groupId>
+      <artifactId>yangtools-parent</artifactId>
+      <version>0.6.2-SNAPSHOT</version>
+      <relativePath>../parent/pom.xml</relativePath>
+   </parent>
+   <artifactId>features-yangtools</artifactId>
+   <packaging>pom</packaging>
+   <properties>
+      <features.file>features.xml</features.file>
+   </properties>
+   <build>
+      <resources>
+         <resource>
+            <directory>src/main/resources</directory>
+            <filtering>true</filtering>
+         </resource>
+      </resources>
+      <plugins>
+         <plugin>
+            <groupId>org.apache.karaf.tooling</groupId>
+            <artifactId>karaf-maven-plugin</artifactId>
+            <version>${karaf.version}</version>
+            <extensions>true</extensions>
+            <executions>
+               <execution>
+                  <id>features-create-kar</id>
+                  <goals>
+                     <goal>features-create-kar</goal>
+                  </goals>
+                  <configuration>
+                     <featuresFile>${project.build.directory}/classes/${features.file}</featuresFile>
+                  </configuration>
+               </execution>
+            </executions>
+        <!-- There is no useful configuration for the kar mojo. The features-generate-descriptor mojo configuration may be useful -->
+         </plugin>
+         <plugin>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-resources-plugin</artifactId>
+            <executions>
+               <execution>
+                  <id>filter</id>
+                  <phase>generate-resources</phase>
+                  <goals>
+                     <goal>resources</goal>
+                  </goals>
+               </execution>
+            </executions>
+         </plugin>
+         <plugin>
+            <groupId>org.codehaus.mojo</groupId>
+            <artifactId>build-helper-maven-plugin</artifactId>
+            <executions>
+               <execution>
+                  <id>attach-artifacts</id>
+                  <phase>package</phase>
+                  <goals>
+                     <goal>attach-artifact</goal>
+                  </goals>
+                  <configuration>
+                     <artifacts>
+                        <artifact>
+                           <file>${project.build.directory}/classes/${features.file}</file>
+                           <type>xml</type>
+                           <classifier>features</classifier>
+                        </artifact>
+                     </artifacts>
+                  </configuration>
+               </execution>
+            </executions>
+         </plugin>
+      </plugins>
+   </build>
+</project>
similarity index 73%
rename from common/feature/src/main/resources/features.xml
rename to common/features/src/main/resources/features.xml
index 82725c63e74ecadd995ce3c2ee850899a16d823d..968990aaa916dfb49232d522e8fbb80fce5e8e09 100644 (file)
     <feature name='yangtools-all' version='${project.version}'>
         <feature version='${project.version}'>yangtools-models</feature>
         <feature version='${project.version}'>yangtools-binding</feature>
+        <feature version='${project.version}'>yangtools-common</feature>
         <feature version='${project.version}'>yangtools-concepts</feature>
         <feature version='${project.version}'>yangtools-binding-generator</feature>
     </feature>
 
     <feature name='yangtools-models' version='${project.version}'>
-        <bundle>mvn:org.opendaylight.yangtools.model/ietf-inet-types/2010.09.24.4-SNAPSHOT</bundle>
-        <bundle>mvn:org.opendaylight.yangtools.model/ietf-yang-types/2010.09.24.4-SNAPSHOT</bundle>
-        <bundle>mvn:org.opendaylight.yangtools.model/yang-ext/2013.09.07.4-SNAPSHOT</bundle>
-        <bundle>mvn:org.opendaylight.yangtools.model/opendaylight-l2-types/2013.08.27.4-SNAPSHOT</bundle>
-        <bundle>mvn:org.opendaylight.yangtools.model/ietf-topology/2013.10.21.2-SNAPSHOT</bundle>
-        <bundle>mvn:org.opendaylight.yangtools.model/opendaylight-l2-types/2013.08.27.4-SNAPSHOT</bundle>
-    </feature>
+        <bundle>mvn:org.opendaylight.yangtools.model/ietf-inet-types/${ietf.inet.types.version}</bundle>
+        <bundle>mvn:org.opendaylight.yangtools.model/ietf-yang-types/${ietf.yang.types.version}</bundle>
+        <bundle>mvn:org.opendaylight.yangtools.model/yang-ext/${yang.ext.version}</bundle>
+        <bundle>mvn:org.opendaylight.yangtools.model/opendaylight-l2-types/${opendaylight.l2.types.version}</bundle>
+        <bundle>mvn:org.opendaylight.yangtools.model/ietf-topology/${ietf.topology.version}</bundle>
+       </feature>
 
     <feature name='yangtools-binding' version='${project.version}'>
         <feature version='${project.version}'>yangtools-concepts</feature>
-        <bundle>mvn:org.opendaylight.yangtools.thirdparty/antlr4-runtime-osgi-nohead/4.0</bundle>
-        <bundle>mvn:commons-io/commons-io/2.4</bundle>
+        <bundle>mvn:org.opendaylight.yangtools.thirdparty/antlr4-runtime-osgi-nohead/${antlr4.version}</bundle>
+        <bundle>mvn:commons-io/commons-io/${commons.io.version}</bundle>
         <bundle>mvn:org.opendaylight.yangtools/yang-binding/${project.version}</bundle>
         <bundle>mvn:org.opendaylight.yangtools/yang-data-api/${project.version}</bundle>
         <bundle>mvn:org.opendaylight.yangtools/yang-data-impl/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.yangtools/yang-data-json/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.yangtools/yang-data-operations/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.yangtools/yang-data-util/${project.version}</bundle>
         <bundle>mvn:org.opendaylight.yangtools/yang-model-api/${project.version}</bundle>
         <bundle>mvn:org.opendaylight.yangtools/yang-model-util/${project.version}</bundle>
         <bundle>mvn:org.opendaylight.yangtools/yang-parser-impl/${project.version}</bundle>
         <bundle>wrap:mvn:org.eclipse.xtend/org.eclipse.xtend.lib/${xtend.version}</bundle>
         <bundle>wrap:mvn:org.eclipse.xtext/org.eclipse.xtext.xbase.lib/${xtend.version}</bundle>
     </feature>
-
+    <feature name="yangtools-common" version='${project.version}'>
+        <bundle>mvn:org.opendaylight.yangtools/util/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.yangtools/object-cache-api/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.yangtools/object-cache-guava/${project.version}</bundle>
+        <bundle>mvn:org.opendaylight.yangtools/object-cache-noop/${project.version}</bundle>
+    </feature>
     <feature name='yangtools-binding-generator' version='${project.version}'>
         <feature version='${project.version}'>yangtools-binding</feature>
         <bundle>mvn:org.javassist/javassist/${javassist.version}</bundle>
-        <bundle>mvn:org.apache.commons/commons-lang3/${commons.lang.version}</bundle>
+        <bundle>mvn:org.apache.commons/commons-lang3/${commons.lang3.version}</bundle>
         <bundle>mvn:org.opendaylight.yangtools/binding-generator-api/${project.version}</bundle>
         <bundle>mvn:org.opendaylight.yangtools/binding-generator-impl/${project.version}</bundle>
         <bundle>mvn:org.opendaylight.yangtools/binding-generator-spi/${project.version}</bundle>
index 6b528d983361d7180b7c2a7c7aa725609e33d486..5d0c9fdad96e3de7967b8f7c9759e96aef680988 100644 (file)
     </prerequisites>
 
     <properties>
-        <junit.version>4.10</junit.version>
+        <antlr4.version>4.0</antlr4.version>
+        <commons.io.version>2.4</commons.io.version>
+        <ctrie.version>0.2.0</ctrie.version>
         <exam.version>3.0.0</exam.version>
         <groovy.version>2.1.6</groovy.version>
-        <nexusproxy>http://nexus.opendaylight.org/content</nexusproxy>
-        <ctrie.version>0.2.0</ctrie.version>
         <ietf.topology.version>2013.10.21.2-SNAPSHOT</ietf.topology.version>
         <ietf.inet.types.version>2010.09.24.4-SNAPSHOT</ietf.inet.types.version>
         <ietf.yang.types.version>2010.09.24.4-SNAPSHOT</ietf.yang.types.version>
         <ietf.restconf.version>2013.10.19.1-SNAPSHOT</ietf.restconf.version>
+        <junit.version>4.10</junit.version>
+        <karaf.version>3.0.1</karaf.version>
+        <nexusproxy>http://nexus.opendaylight.org/content</nexusproxy>
+        <opendaylight.l2.types.version>2013.08.27.4-SNAPSHOT</opendaylight.l2.types.version>
+        <yang.ext.version>2013.09.07.4-SNAPSHOT</yang.ext.version>
         <maven.javadoc.version>2.9.1</maven.javadoc.version>
     </properties>
 
                 <version>0.6.2-SNAPSHOT</version>
                 <scope>test</scope>
             </dependency>
+            <dependency>
+                <groupId>org.opendaylight.yangtools</groupId>
+                <artifactId>bug1196-test-model</artifactId>
+                <version>0.6.2-SNAPSHOT</version>
+                <scope>test</scope>
+            </dependency>
 
             <dependency>
                 <groupId>org.opendaylight.yangtools</groupId>
index 32c77ea97648bcb176c151bf29c715e950651979..540e43a0578f141229974d73bc1014661fe200bf 100644 (file)
@@ -19,7 +19,7 @@
     <modules>
         <module>checkstyle-logging</module>
         <module>concepts</module>
-        <module>feature</module>
+        <module>features</module>
         <module>mockito-configuration</module>
         <module>object-cache-api</module>
         <module>object-cache-guava</module>
diff --git a/integration-test/bug1196-test-model/pom.xml b/integration-test/bug1196-test-model/pom.xml
new file mode 100644 (file)
index 0000000..8059b5c
--- /dev/null
@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!-- 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 -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <parent>
+        <groupId>org.opendaylight.yangtools</groupId>
+        <artifactId>yangtools-parent</artifactId>
+        <version>0.6.2-SNAPSHOT</version>
+        <relativePath>/../../common/parent/pom.xml</relativePath>
+    </parent>
+
+    <modelVersion>4.0.0</modelVersion>
+    <artifactId>bug1196-test-model</artifactId>
+    <name>${project.artifactId}</name>
+    <description>${project.artifactId}</description>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-jar-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.opendaylight.yangtools</groupId>
+                <artifactId>yang-maven-plugin</artifactId>
+                <dependencies>
+                    <dependency>
+                        <groupId>org.opendaylight.yangtools</groupId>
+                        <artifactId>yang-binding</artifactId>
+                        <version>0.6.2-SNAPSHOT</version>
+                    </dependency>
+                    <dependency>
+                        <groupId>org.opendaylight.yangtools</groupId>
+                        <artifactId>yang-common</artifactId>
+                        <version>0.6.2-SNAPSHOT</version>
+                    </dependency>
+                    <dependency>
+                        <groupId>org.opendaylight.yangtools.model</groupId>
+                        <artifactId>yang-ext</artifactId>
+                        <version>2013.09.07.4-SNAPSHOT</version>
+                    </dependency>
+                    <dependency>
+                        <groupId>org.opendaylight.yangtools.model</groupId>
+                        <artifactId>ietf-inet-types</artifactId>
+                        <version>2010.09.24.4-SNAPSHOT</version>
+                    </dependency>
+                </dependencies>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-Name>org.opendaylight.yangtools.model.${project.artifactId}</Bundle-Name>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-binding</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-common</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>yang-ext</artifactId>
+            <version>2013.09.07.4-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools.model</groupId>
+            <artifactId>ietf-inet-types</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/integration-test/bug1196-test-model/src/main/yang/network-topology-pcep.yang b/integration-test/bug1196-test-model/src/main/yang/network-topology-pcep.yang
new file mode 100644 (file)
index 0000000..29d202d
--- /dev/null
@@ -0,0 +1,32 @@
+module network-topology-pcep {
+    // vi: set et smarttab sw=4 tabstop=4:
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:topology:pcep";
+    prefix "pn";
+
+    import network-topology { prefix nt; revision-date 2013-10-21; }
+
+    revision "2013-10-24" {
+    }
+
+
+    grouping pcep-client-attributes {
+        container path-computation-client {
+            config false;
+            list reported-lsp {
+                leaf name {
+                    type string;
+                }
+                key name;
+            }
+        }
+    }
+
+    augment "/nt:network-topology/nt:topology/nt:node" {
+        when "../../nt:topology-types/topology-pcep";
+
+        uses pcep-client-attributes;
+    }
+
+}
+
diff --git a/integration-test/bug1196-test-model/src/main/yang/network-topology-unix.yang b/integration-test/bug1196-test-model/src/main/yang/network-topology-unix.yang
new file mode 100644 (file)
index 0000000..d061f47
--- /dev/null
@@ -0,0 +1,25 @@
+module network-topology-unix {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:network:topology-unix";
+    prefix "unix";
+
+    import network-topology { prefix nt; revision-date 2013-10-21; }
+    import network-topology-pcep { prefix topo; revision-date 2013-10-24; }
+    import odl-pcep-ietf-stateful07 { prefix stateful; revision-date 2013-12-22; }
+
+    revision "2013-12-22" {
+    }
+
+
+    augment "/nt:network-topology/nt:topology/nt:node/topo:path-computation-client/topo:reported-lsp/stateful:lsp/stateful:tlvs/stateful:vs-tlv/stateful:vendor-payload" {
+        case unix {
+            container unix-sub-tlvs {
+                leaf unix-value {
+                    type uint8;
+                }
+            }
+        }
+    }
+
+}
+
diff --git a/integration-test/bug1196-test-model/src/main/yang/network-topology@2013-10-21.yang b/integration-test/bug1196-test-model/src/main/yang/network-topology@2013-10-21.yang
new file mode 100644 (file)
index 0000000..630b780
--- /dev/null
@@ -0,0 +1,23 @@
+module network-topology  {
+    yang-version 1;
+    namespace "urn:TBD:params:xml:ns:yang:network-topology";
+    prefix "nt";
+
+
+    revision 2013-10-21 {
+    }
+
+
+
+    container network-topology {
+        list topology {
+            key "topology-id";
+            leaf topology-id {
+                type string;
+            }
+            list node {
+            }
+        }
+    }
+}
+
diff --git a/integration-test/bug1196-test-model/src/main/yang/odl-pcep-ietf-stateful07.yang b/integration-test/bug1196-test-model/src/main/yang/odl-pcep-ietf-stateful07.yang
new file mode 100644 (file)
index 0000000..525040c
--- /dev/null
@@ -0,0 +1,38 @@
+module odl-pcep-ietf-stateful07 {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:pcep:ietf:stateful";
+    prefix "stateful";
+
+    import network-topology { prefix nt; revision-date 2013-10-21; }
+    import network-topology-pcep { prefix topo; revision-date 2013-10-24; }
+    import pcep-types { prefix pcep; revision-date 2013-10-05; }
+    import yang-ext { prefix ext; revision-date 2013-07-09; }
+
+    revision "2013-12-22" {
+    }
+
+
+    grouping lsp-object {
+        container lsp {
+            container "tlvs" {
+                uses pcep:vs-tlv;
+            }
+        }
+    }
+
+    augment "/nt:network-topology/nt:topology/nt:node/topo:path-computation-client/topo:reported-lsp" {
+        uses lsp-object;
+    }
+
+    augment "/nt:network-topology/nt:topology/nt:node/topo:path-computation-client/topo:reported-lsp/stateful:lsp/stateful:tlvs/stateful:vs-tlv/stateful:vendor-payload" {
+        case linux {
+            container linux-sub-tlvs {
+                leaf linux-value {
+                    type uint8;
+                }
+            }
+        }
+    }
+
+}
+
diff --git a/integration-test/bug1196-test-model/src/main/yang/pcep-types.yang b/integration-test/bug1196-test-model/src/main/yang/pcep-types.yang
new file mode 100644 (file)
index 0000000..a05c2ea
--- /dev/null
@@ -0,0 +1,19 @@
+module pcep-types {
+    yang-version 1;
+    namespace "urn:opendaylight:params:xml:ns:yang:pcep:types";
+    prefix "pcep-t";
+
+    revision "2013-10-05" {
+    }
+
+
+    grouping vs-tlv {
+        description "Vendor-specific TLV.";
+        container vs-tlv {
+                choice vendor-payload {
+                }
+        }
+    }
+
+}
+
index 2b9a20c90874456f7ca3e49190bdf48111e8dde7..77dd63be37a71195f7b98db72df02558cb2b7187 100644 (file)
@@ -15,6 +15,7 @@
 
     <modules>
         <module>bug527-test-model</module>
+        <module>bug1196-test-model</module>
         <module>bundle-test</module>
         <module>test-models</module>
         <module>regression-test-model</module>
index 99c08eb51511cbf3c24d57d81a6a35a8fe84e499..b21db8414775da7966276cfcb9e568375fb75dc0 100644 (file)
             <version>0.6.2-SNAPSHOT</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>bug1196-test-model</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>
diff --git a/restconf/restconf-util/src/test/java/org/opendaylight/yangtools/restconf/utils/Bug1196Test.java b/restconf/restconf-util/src/test/java/org/opendaylight/yangtools/restconf/utils/Bug1196Test.java
new file mode 100644 (file)
index 0000000..ac5d868
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2014 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.restconf.utils;
+
+import static junit.framework.Assert.assertNotNull;
+import static org.junit.Assert.assertEquals;
+
+import java.io.InputStream;
+import java.util.AbstractMap.SimpleEntry;
+import java.util.Map.Entry;
+
+import javassist.ClassPool;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.network.topology.unix.rev131222.network.topology.topology.node.path.computation.client.reported.lsp.lsp.tlvs.vs.tlv.vendor.payload.unix.UnixSubTlvs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.ReportedLsp1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.Lsp;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.lsp.Tlvs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.network.topology.topology.node.path.computation.client.reported.lsp.lsp.tlvs.vs.tlv.vendor.payload.linux.LinuxSubTlvs;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.types.rev131005.vs.tlv.VsTlv;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.Node1;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.PathComputationClient;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.topology.pcep.rev131024.pcep.client.attributes.path.computation.client.ReportedLsp;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.NetworkTopology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.TopologyId;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.Topology;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.TopologyKey;
+import org.opendaylight.yang.gen.v1.urn.tbd.params.xml.ns.yang.network.topology.rev131021.network.topology.topology.Node;
+import org.opendaylight.yangtools.sal.binding.generator.impl.ModuleInfoBackedContext;
+import org.opendaylight.yangtools.sal.binding.generator.impl.RuntimeGeneratedMappingServiceImpl;
+import org.opendaylight.yangtools.yang.binding.DataObject;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.binding.util.BindingReflections;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.CompositeNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+public class Bug1196Test {
+
+    private static final InstanceIdentifier<PathComputationClient> PATH_TO_CLIENT = InstanceIdentifier.builder(NetworkTopology.class)
+            .child(Topology.class)
+            .child(Node.class)
+            .augmentation(Node1.class)
+            .child(PathComputationClient.class)
+            .build();
+    private RuntimeGeneratedMappingServiceImpl mappingService;
+
+    @Before
+    public void setup() {
+        this.mappingService = new RuntimeGeneratedMappingServiceImpl(new ClassPool());
+
+        final ModuleInfoBackedContext moduleInfo = ModuleInfoBackedContext.create();
+        moduleInfo.addModuleInfos(BindingReflections.loadModuleInfos());
+        this.mappingService.onGlobalContextUpdated(moduleInfo.tryToCreateSchemaContext().get());
+    }
+
+    @Test
+    public void testXmlDataToDataObjectLinuxCase() {
+        final InstanceIdentifier<Topology> instanceIdentifier = InstanceIdentifier.builder(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(new TopologyId("example-pcep-topology"))).toInstance();
+        final InputStream is = this.getClass().getClassLoader().getResourceAsStream("topology-bug1196-linux.xml");
+        final DataSchemaNode dataSchema = RestconfUtils.toRestconfIdentifier(instanceIdentifier, this.mappingService,
+                this.mappingService.getSchemaContext()).getValue();
+        Topology topology = (Topology) RestconfUtils.dataObjectFromInputStream(instanceIdentifier, is,
+                this.mappingService.getSchemaContext(), this.mappingService, dataSchema);
+        assertNotNull(topology);
+        assertNotNull(topology.getNode());
+        assertEquals(1, topology.getNode().size());
+        Node node = topology.getNode().get(0);
+        Node1 node1 = node.getAugmentation(Node1.class);
+        assertNotNull(node1);
+        final PathComputationClient pcc = node1.getPathComputationClient();
+        final Lsp lsp = pcc.getReportedLsp().get(0).getAugmentation(ReportedLsp1.class).getLsp();
+        org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.lsp.Tlvs tlvs = lsp.getTlvs();
+        assertNotNull(tlvs);
+        VsTlv vsTlv = tlvs.getVsTlv();
+        assertNotNull(vsTlv.getVendorPayload());
+
+        Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> domPcc = mappingService.toDataDom(new SimpleEntry<InstanceIdentifier<?>,DataObject>(PATH_TO_CLIENT,pcc));
+        CompositeNode domPccValue = domPcc.getValue();
+        assertNotNull(domPccValue);
+        CompositeNode domPccTlvs = getFirstReportedLspVsTlvs(domPccValue);
+        assertNotNull(domPccTlvs);
+        assertNotNull(domPccTlvs.getFirstCompositeByName(LinuxSubTlvs.QNAME));
+
+    }
+
+    private CompositeNode getFirstReportedLspVsTlvs(final CompositeNode domPccValue) {
+        return domPccValue.getFirstCompositeByName(ReportedLsp.QNAME).getFirstCompositeByName(Lsp.QNAME).getFirstCompositeByName(Tlvs.QNAME).getFirstCompositeByName(QName.create(Tlvs.QNAME,VsTlv.QNAME.getLocalName()));
+    }
+
+    @Test
+    public void testXmlDataToDataObjectUnixCase() {
+        final InstanceIdentifier<Topology> instanceIdentifier = InstanceIdentifier.builder(NetworkTopology.class)
+                .child(Topology.class, new TopologyKey(new TopologyId("example-pcep-topology"))).toInstance();
+        final InputStream is = this.getClass().getClassLoader().getResourceAsStream("topology-bug1196-unix.xml");
+        final DataSchemaNode dataSchema = RestconfUtils.toRestconfIdentifier(instanceIdentifier, this.mappingService,
+                this.mappingService.getSchemaContext()).getValue();
+        Topology topology = (Topology) RestconfUtils.dataObjectFromInputStream(instanceIdentifier, is,
+                this.mappingService.getSchemaContext(), this.mappingService, dataSchema);
+        assertNotNull(topology);
+        assertNotNull(topology.getNode());
+        assertEquals(1, topology.getNode().size());
+        Node node = topology.getNode().get(0);
+        Node1 node1 = node.getAugmentation(Node1.class);
+        assertNotNull(node1);
+        final PathComputationClient pcc = node1.getPathComputationClient();
+        final Lsp lsp = pcc.getReportedLsp().get(0).getAugmentation(ReportedLsp1.class).getLsp();
+        org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.pcep.ietf.stateful.rev131222.lsp.object.lsp.Tlvs tlvs = lsp.getTlvs();
+        assertNotNull(tlvs);
+        VsTlv vsTlv = tlvs.getVsTlv();
+        assertNotNull(vsTlv.getVendorPayload());
+
+        Entry<org.opendaylight.yangtools.yang.data.api.InstanceIdentifier, CompositeNode> domPcc = mappingService.toDataDom(new SimpleEntry<InstanceIdentifier<?>,DataObject>(PATH_TO_CLIENT,pcc));
+        CompositeNode domPccValue = domPcc.getValue();
+        assertNotNull(domPccValue);
+        CompositeNode domPccTlvs = getFirstReportedLspVsTlvs(domPccValue);
+        assertNotNull(domPccTlvs);
+        assertNotNull(domPccTlvs.getFirstCompositeByName(UnixSubTlvs.QNAME));
+    }
+
+}
diff --git a/restconf/restconf-util/src/test/resources/topology-bug1196-linux.xml b/restconf/restconf-util/src/test/resources/topology-bug1196-linux.xml
new file mode 100644 (file)
index 0000000..517e840
--- /dev/null
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- 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 -->
+<topology xmlns="urn:TBD:params:xml:ns:yang:network-topology">
+    <server-provided>true</server-provided>
+    <topology-id>example-pcep-topology</topology-id>
+    <topology-types/>
+    <node>
+     <path-computation-client xmlns="urn:opendaylight:params:xml:ns:yang:topology:pcep">
+      <state-sync>synchronized</state-sync>
+       <stateful-tlv>
+        <stateful>
+         <lsp-update-capability>true</lsp-update-capability>
+         <include-db-version>false</include-db-version>
+         <initiation>true</initiation>
+        </stateful>
+       </stateful-tlv>
+       <reported-lsp>
+        <name>update-tunel</name>
+        <path>
+          <bandwidth>
+           <bandwidth>AAAAAA==</bandwidth>
+           <ignore>false</ignore>
+           <processing-rule>false</processing-rule>
+          </bandwidth>
+          <ero>
+            <ignore>false</ignore>
+            <processing-rule>false</processing-rule>
+            <subobject>
+             <loose>false</loose>
+             <ip-prefix>
+              <ip-prefix>195.20.160.40/32</ip-prefix>
+             </ip-prefix>
+          </subobject>
+          <subobject>
+           <loose>false</loose>
+           <ip-prefix>
+            <ip-prefix>201.20.160.43/32</ip-prefix>
+           </ip-prefix>
+          </subobject>
+         </ero>
+         <lspa>
+          <exclude-any>0</exclude-any>
+          <hold-priority>7</hold-priority>
+          <ignore>false</ignore>
+          <include-all>0</include-all>
+          <include-any>0</include-any>
+          <local-protection-desired>false</local-protection-desired>
+          <processing-rule>false</processing-rule>
+          <setup-priority>7</setup-priority>
+         </lspa>
+        </path>
+        <lsp xmlns="urn:opendaylight:params:xml:ns:yang:pcep:ietf:stateful">
+         <tlvs>
+          <symbolic-path-name>
+           <path-name>dXBkYXRlLXR1bmVs</path-name>
+          </symbolic-path-name>
+            <vs-tlv>
+                 <enterprise-number>9</enterprise-number>
+                 <linux-sub-tlvs>
+                    <linux-value>5</linux-value>
+                 </linux-sub-tlvs>
+            </vs-tlv>
+         </tlvs>
+         <delegate>true</delegate>
+         <processing-rule>false</processing-rule>
+         <ignore>false</ignore>
+         <operational>true</operational>
+         <sync>false</sync>
+         <plsp-id>40</plsp-id>
+         <remove>false</remove>
+        </lsp>
+      </reported-lsp>
+      <ip-address>39.39.39.39</ip-address>
+     </path-computation-client>
+     <node-id>pcc://39.39.39.39</node-id>
+    </node>
+</topology>
diff --git a/restconf/restconf-util/src/test/resources/topology-bug1196-unix.xml b/restconf/restconf-util/src/test/resources/topology-bug1196-unix.xml
new file mode 100644 (file)
index 0000000..5213fda
--- /dev/null
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- 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 -->
+<topology xmlns="urn:TBD:params:xml:ns:yang:network-topology">
+    <server-provided>true</server-provided>
+    <topology-id>example-pcep-topology</topology-id>
+    <topology-types/>
+    <node>
+     <path-computation-client xmlns="urn:opendaylight:params:xml:ns:yang:topology:pcep">
+      <state-sync>synchronized</state-sync>
+       <stateful-tlv>
+        <stateful>
+         <lsp-update-capability>true</lsp-update-capability>
+         <include-db-version>false</include-db-version>
+         <initiation>true</initiation>
+        </stateful>
+       </stateful-tlv>
+       <reported-lsp>
+        <name>update-tunel</name>
+        <path>
+          <bandwidth>
+           <bandwidth>AAAAAA==</bandwidth>
+           <ignore>false</ignore>
+           <processing-rule>false</processing-rule>
+          </bandwidth>
+          <ero>
+            <ignore>false</ignore>
+            <processing-rule>false</processing-rule>
+            <subobject>
+             <loose>false</loose>
+             <ip-prefix>
+              <ip-prefix>195.20.160.40/32</ip-prefix>
+             </ip-prefix>
+          </subobject>
+          <subobject>
+           <loose>false</loose>
+           <ip-prefix>
+            <ip-prefix>201.20.160.43/32</ip-prefix>
+           </ip-prefix>
+          </subobject>
+         </ero>
+         <lspa>
+          <exclude-any>0</exclude-any>
+          <hold-priority>7</hold-priority>
+          <ignore>false</ignore>
+          <include-all>0</include-all>
+          <include-any>0</include-any>
+          <local-protection-desired>false</local-protection-desired>
+          <processing-rule>false</processing-rule>
+          <setup-priority>7</setup-priority>
+         </lspa>
+        </path>
+        <lsp xmlns="urn:opendaylight:params:xml:ns:yang:pcep:ietf:stateful">
+         <tlvs>
+          <symbolic-path-name>
+           <path-name>dXBkYXRlLXR1bmVs</path-name>
+          </symbolic-path-name>
+            <vs-tlv>
+                 <enterprise-number>9</enterprise-number>
+                 <unix-sub-tlvs xmlns="urn:opendaylight:params:xml:ns:yang:network:topology-unix">
+                    <unix-value>5</unix-value>
+                 </unix-sub-tlvs>
+            </vs-tlv>
+         </tlvs>
+         <delegate>true</delegate>
+         <processing-rule>false</processing-rule>
+         <ignore>false</ignore>
+         <operational>true</operational>
+         <sync>false</sync>
+         <plsp-id>40</plsp-id>
+         <remove>false</remove>
+        </lsp>
+      </reported-lsp>
+      <ip-address>39.39.39.39</ip-address>
+     </path-computation-client>
+     <node-id>pcc://39.39.39.39</node-id>
+    </node>
+</topology>