Merge "Add model parent"
authorTony Tkacik <ttkacik@cisco.com>
Fri, 28 Nov 2014 10:12:36 +0000 (10:12 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Fri, 28 Nov 2014 10:12:36 +0000 (10:12 +0000)
49 files changed:
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/CodecTypeUtils.java
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/RuntimeGeneratedMappingServiceImpl.java
code-generator/binding-java-api-generator/src/main/java/org/opendaylight/yangtools/sal/java/api/generator/ClassTemplate.xtend
code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/CompilationTestUtils.java
code-generator/binding-java-api-generator/src/test/java/org/opendaylight/yangtools/sal/java/api/generator/test/TypedefCompilationTest.java
common/object-cache-api/src/main/java/org/opendaylight/yangtools/objcache/ObjectCacheFactory.java
common/util/src/main/java/org/opendaylight/yangtools/util/LazyCollections.java
model/ietf/ietf-topology-isis/src/main/yang/isis-topology@2013-07-12.yang
restconf/restconf-common/src/main/java/org/opendaylight/yangtools/restconf/common/MediaTypes.java
restconf/restconf-util/src/test/java/org/opendaylight/yangtools/restconf/utils/RestconfUtilsTest.java
restconf/restconf-util/src/test/resources/topology.xml
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/InstanceIdentifier.java
yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/QNameModule.java
yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/SimpleDateFormatUtil.java
yang/yang-data-composite-node/src/main/java/org/opendaylight/yangtools/yang/data/composite/node/schema/json/CnSnToNormalizedNodesUtils.java
yang/yang-data-impl/pom.xml
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/ValueWithQName.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/InstanceIdentifierForXmlCodec.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XMLStreamNormalizedNodeStreamWriter.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlDocumentUtils.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlStreamUtils.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/Builders.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/ImmutableNormalizedNodeStreamWriter.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/AbstractImmutableDataContainerNodeBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetEntryNodeBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableLeafSetNodeBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableMapNodeBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableOrderedMapNodeBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableOrderedMapNodeSchemaAwareBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/builder/impl/ImmutableUnkeyedListNodeBuilder.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableDataContainerNode.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableNormalizedValueAttrNode.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/UnmodifiableChildrenMap.java [new file with mode: 0644]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/NormalizedNodeContainerModificationStrategy.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/tree/TreeNodeUtils.java
yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/codec/xml/XmlStreamUtilsTest.java
yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableNormalizedValueAttrNodeTest.java [new file with mode: 0644]
yang/yang-data-impl/src/test/resources/leafref-test.yang [new file with mode: 0644]
yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/ChoiceNodeModification.java
yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/LeafSetNodeModification.java
yang/yang-data-operations/src/main/java/org/opendaylight/yangtools/yang/data/operations/MapNodeModification.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/SchemaContextUtil.java
yang/yang-parser-impl/src/main/antlr/YangLexer.g4
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/builder/impl/ListSchemaNodeBuilder.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/ParserListenerUtils.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YangParserListenerImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/repo/SharedSchemaContextFactory.java

index 5cb27aa0b6da4a12c516c4dc6d86aae5fbe96b4b..283a262e58817cd634e891b34677c1776008b708 100644 (file)
@@ -1,9 +1,10 @@
 package org.opendaylight.yangtools.sal.binding.generator.impl;
 
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Set;
-
 import org.opendaylight.yangtools.yang.binding.Augmentation;
 import org.opendaylight.yangtools.yang.binding.BindingMapping;
 import org.opendaylight.yangtools.yang.binding.ChildOf;
@@ -25,10 +26,11 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.util.SchemaNodeUtils;
 
-import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
+public final class BindingSchemaContextUtils {
 
-public class BindingSchemaContextUtils {
+    private BindingSchemaContextUtils() {
+        throw new UnsupportedOperationException("Utility class should not be instantiated");
+    }
 
     // FIXME: THis method does not search in case augmentations.
     public static Optional<DataNodeContainer> findDataNodeContainer(final SchemaContext ctx,
@@ -196,7 +198,7 @@ public class BindingSchemaContextUtils {
         // This solves case, if choice was inside grouping
         // which was used in different module and thus namespaces are
         // different, but local names are still same.
-        // 
+        //
         // Still we need to check equality of definition, because local name is not
         // sufficient to uniquelly determine equality of cases
         //
index 2ef288f79703c09936b77fb486535995db5580b9..4622ab737d6626d9dc9a6c0ba32779c7ef0f5d1d 100644 (file)
@@ -16,7 +16,7 @@ import org.opendaylight.yangtools.yang.data.impl.codec.InstanceIdentifierCodec;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class CodecMapping {
+public final class CodecMapping {
 
     private static final Logger LOG = LoggerFactory.getLogger(CodecMapping.class);
 
@@ -28,6 +28,10 @@ public class CodecMapping {
     public static final String AUGMENTATION_CODEC = "AUGMENTATION_CODEC";
     public static final String DISPATCH_CODEC = "DISPATCH_CODEC";
 
+    private CodecMapping() {
+        throw new UnsupportedOperationException("Utility class should not be instantiated");
+    }
+
     public static void setIdentifierCodec(Class<?> obj,InstanceIdentifierCodec codec) {
         Field instanceIdField;
         try {
index 60de0c69154e9a8c0a6128136c0fb25b78c655e9..447dbdc3eb328314953fed6e1b8840f3c29f3dcb 100644 (file)
@@ -11,7 +11,11 @@ import org.opendaylight.yangtools.yang.binding.Identifiable;
 import org.opendaylight.yangtools.yang.binding.Identifier;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier.IdentifiableItem;
 
-public class CodecTypeUtils {
+public final class CodecTypeUtils {
+
+    private CodecTypeUtils() {
+        throw new UnsupportedOperationException("Utility class should not be instantiated");
+    }
 
     @SuppressWarnings({"unchecked","rawtypes"})
     public static IdentifiableItem<?, ?> newIdentifiableItem(Class<?> type, Object key) {
index 29a532228dd54bfc6421c34035af5f91f923cafb..c0fef76f26c058ee8a26b9a08ce5c5b919a27d5c 100644 (file)
@@ -13,26 +13,7 @@ import com.google.common.collect.HashMultimap;
 import com.google.common.collect.Multimap;
 import com.google.common.util.concurrent.ListenableFuture;
 import com.google.common.util.concurrent.SettableFuture;
-
-import java.net.URI;
-import java.util.AbstractMap.SimpleEntry;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.ExecutionException;
-
 import javassist.ClassPool;
-
-import javax.annotation.concurrent.GuardedBy;
-
 import org.opendaylight.yangtools.binding.generator.util.BindingGeneratorUtil;
 import org.opendaylight.yangtools.binding.generator.util.ReferencedTypeImpl;
 import org.opendaylight.yangtools.binding.generator.util.Types;
@@ -75,6 +56,22 @@ import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.annotation.concurrent.GuardedBy;
+import java.net.URI;
+import java.util.AbstractMap.SimpleEntry;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutionException;
+
 public class RuntimeGeneratedMappingServiceImpl implements BindingIndependentMappingService, SchemaContextListener,
 SchemaLock, AutoCloseable, SchemaContextHolder, TypeResolver {
 
@@ -159,6 +156,7 @@ SchemaLock, AutoCloseable, SchemaContextHolder, TypeResolver {
                 Type serviceClass = new ReferencedTypeImpl(namespace, BindingMapping.getClassName(module.getName())
                         + "Service");
                 serviceTypeToRpc.put(serviceClass, rpcs);
+                updatePromisedSchemas(serviceClass);
             }
 
             Map<SchemaPath, Type> typedefs = context.getTypedefs();
@@ -337,8 +335,10 @@ SchemaLock, AutoCloseable, SchemaContextHolder, TypeResolver {
         Set<QName> serviceRef = serviceTypeToRpc.get(new ReferencedTypeImpl(service.getPackage().getName(), service
                 .getSimpleName()));
         if (serviceRef == null) {
-            serviceRef = Collections.emptySet();
-        }
+            waitForSchema(service);
+            serviceRef = serviceTypeToRpc.get(new ReferencedTypeImpl(service.getPackage().getName(), service
+                    .getSimpleName()));
+            }
         return serviceRef;
     }
 
index e7400f9ff6865d0f78bfdb83af20283b0ad40920..8d20831242fc1be9149a80811227def001523ecc 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 com.google.common.base.Preconditions
 
 /**
  * Template for generating JAVA class.
@@ -52,12 +53,12 @@ class ClassTemplate extends BaseTemplate {
      * List of generated types which are enclosed inside <code>genType</code>
      */
     protected val List<GeneratedType> enclosedGeneratedTypes;
-    
+
     protected val GeneratedTransferObject genTO;
 
     /**
      * Creates instance of this class with concrete <code>genType</code>.
-     * 
+     *
      * @param genType generated transfer object which will be transformed to JAVA class source code
      */
     new(GeneratedTransferObject genType) {
@@ -83,7 +84,7 @@ class ClassTemplate extends BaseTemplate {
 
     /**
      * Generates JAVA class source code (class body only).
-     * 
+     *
      * @return string with JAVA class body source code
      */
     def CharSequence generateAsInnerClass() {
@@ -96,7 +97,7 @@ class ClassTemplate extends BaseTemplate {
 
     /**
      * Template method which generates class body.
-     * 
+     *
      * @param isInnerClass boolean value which specify if generated class is|isn't inner
      * @return string with class source code in JAVA format
      */
@@ -108,11 +109,11 @@ class ClassTemplate extends BaseTemplate {
             Â«enumDeclarations»
             Â«constantsDeclarations»
             Â«generateFields»
-            
-            Â«IF restrictions != null && (!restrictions.rangeConstraints.nullOrEmpty || 
+
+            Â«IF restrictions != null && (!restrictions.rangeConstraints.nullOrEmpty ||
                 !restrictions.lengthConstraints.nullOrEmpty)»
             Â«generateConstraints»
-            
+
             Â«ENDIF»
             Â«constructors»
 
@@ -158,7 +159,7 @@ class ClassTemplate extends BaseTemplate {
 
     /**
      * Template method which generates inner classes inside this interface.
-     * 
+     *
      * @return string with the source code for inner classes in JAVA format
      */
     def protected innerClassesDeclarations() '''
@@ -244,14 +245,38 @@ class ClassTemplate extends BaseTemplate {
         Â«IF false == parentProperties.empty»
             super(«parentProperties.asArguments»);
         Â«ENDIF»
-        Â«FOR p : allProperties» 
+        Â«FOR p : allProperties»
             Â«generateRestrictions(type, p.fieldName.toString, p.returnType)»
         Â«ENDFOR»
-        Â«FOR p : properties» 
+
+        Â«/*
+         * If we have patterns, we need to apply them to the value field. This is a sad
+         * consequence of how this code is structured.
+         */
+        IF genTO.typedef && !allProperties.empty && allProperties.size == 1 && allProperties.get(0).name.equals("value")»
+
+        Â«Preconditions.importedName».checkNotNull(_value, "Supplied value may not be null");
+
+            Â«FOR c : consts»
+                Â«IF c.name == TypeConstants.PATTERN_CONSTANT_NAME && c.value instanceof List<?>»
+            boolean valid = false;
+            for (Pattern p : patterns) {
+                if (p.matcher(_value).matches()) {
+                    valid = true;
+                    break;
+                }
+            }
+
+            Â«Preconditions.importedName».checkArgument(valid, "Supplied value \"%s\" does not match any of the permitted patterns %s", _value, Â«TypeConstants.PATTERN_CONSTANT_NAME»);
+                Â«ENDIF»
+            Â«ENDFOR»
+        Â«ENDIF»
+
+        Â«FOR p : properties»
             this.«p.fieldName» = Â«p.fieldName»;
         Â«ENDFOR»
     }
-    
+
     '''
 
     def protected genUnionConstructor() '''
@@ -269,11 +294,13 @@ class ClassTemplate extends BaseTemplate {
         Â«IF false == parentProperties.empty»
             super(«parentProperties.asArguments»);
         Â«ENDIF»
-            Â«generateRestrictions(type, property.fieldName.toString, property.returnType)»
-            this.«property.fieldName» = Â«property.name»;
-            Â«FOR p : other»
+
+        Â«generateRestrictions(type, property.fieldName.toString, property.returnType)»
+
+        this.«property.fieldName» = Â«property.name»;
+        Â«FOR p : other»
             this.«p.fieldName» = null;
-            Â«ENDFOR»
+        Â«ENDFOR»
     }
     '''
 
@@ -287,7 +314,7 @@ class ClassTemplate extends BaseTemplate {
         Â«IF false == parentProperties.empty»
             super(source);
         Â«ENDIF»
-        Â«FOR p : properties» 
+        Â«FOR p : properties»
             this.«p.fieldName» = source.«p.fieldName»;
         Â«ENDFOR»
     }
@@ -310,7 +337,7 @@ class ClassTemplate extends BaseTemplate {
             Â«IF !("org.opendaylight.yangtools.yang.binding.InstanceIdentifier".equals(prop.returnType.fullyQualifiedName))»
             public static Â«genTO.name» getDefaultInstance(String defaultValue) {
                 Â«IF "byte[]".equals(prop.returnType.name)»
-                    Â«BaseEncoding.importedName» baseEncoding = Â«BaseEncoding.importedName».base64(); 
+                    Â«BaseEncoding.importedName» baseEncoding = Â«BaseEncoding.importedName».base64();
                     return new Â«genTO.name»(baseEncoding.decode(defaultValue));
                 Â«ELSEIF "java.lang.String".equals(prop.returnType.fullyQualifiedName)»
                     return new Â«genTO.name»(defaultValue);
@@ -355,7 +382,7 @@ class ClassTemplate extends BaseTemplate {
 
     /**
      * Template method which generates JAVA class declaration.
-     * 
+     *
      * @param isInnerClass boolean value which specify if generated class is|isn't inner
      * @return string with class declaration in JAVA format
      */
@@ -381,7 +408,7 @@ class ClassTemplate extends BaseTemplate {
 
     /**
      * Template method which generates JAVA enum type.
-     * 
+     *
      * @return string with inner enum source code in JAVA format
      */
     def protected enumDeclarations() '''
@@ -395,14 +422,14 @@ class ClassTemplate extends BaseTemplate {
 
     def protected suidDeclaration() '''
         Â«IF genTO.SUID != null»
-            private static final long serialVersionUID = Â«genTO.SUID.value»L; 
+            private static final long serialVersionUID = Â«genTO.SUID.value»L;
         Â«ENDIF»
     '''
 
     /**
-     * Template method wich generates JAVA constants.
-     * 
-     * @return string with constants in JAVA format 
+     * Template method which generates JAVA constants.
+     *
+     * @return string with constants in JAVA format
      */
     def protected constantsDeclarations() '''
         Â«IF !consts.empty»
@@ -411,8 +438,8 @@ class ClassTemplate extends BaseTemplate {
                     Â«val cValue = c.value»
                     Â«IF cValue instanceof List<?>»
                         Â«val cValues = cValue as List<?>»
-                        private static final Â«List.importedName»<«Pattern.importedName»> Â«Constants.MEMBER_PATTERN_LIST» = new Â«ArrayList.importedName»<«Pattern.importedName»>();
-                        public static final Â«List.importedName»<String> Â«TypeConstants.PATTERN_CONSTANT_NAME» = Â«Arrays.importedName».asList(«
+                        private static final Â«List.importedName»<«Pattern.importedName»> Â«Constants.MEMBER_PATTERN_LIST»;
+                        public static final Â«List.importedName»<String> Â«TypeConstants.PATTERN_CONSTANT_NAME» = Â«ImmutableList.importedName».of(«
                         FOR v : cValues SEPARATOR ", "»«
                             IF v instanceof String»"«
                                 v as String»"«
@@ -435,9 +462,12 @@ class ClassTemplate extends BaseTemplate {
      */
     def protected generateStaticInicializationBlock() '''
         static {
+            final Â«List.importedName»<«Pattern.importedName»> l = new Â«ArrayList.importedName»<«Pattern.importedName»>();
             for (String regEx : Â«TypeConstants.PATTERN_CONSTANT_NAME») {
-                Â«Constants.MEMBER_PATTERN_LIST».add(Pattern.compile(regEx));
+                l.add(Pattern.compile(regEx));
             }
+
+            Â«Constants.MEMBER_PATTERN_LIST» = Â«ImmutableList.importedName».copyOf(l);
         }
     '''
 
index d3ac8d7eec5bc0c2e0e3c127143f8fbb77751155..921aaf0d7dfbbadd5fc0cb2c34a86e3467fd1161 100644 (file)
@@ -11,13 +11,13 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
-
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
 import java.lang.reflect.ParameterizedType;
 import java.net.URI;
 import java.util.ArrayList;
@@ -53,7 +53,7 @@ public class CompilationTestUtils {
      * instead of marking it with @After annotation to prevent removing
      * generated code if test fails.
      */
-    static void cleanUp(File... resourceDirs) {
+    static void cleanUp(final File... resourceDirs) {
         for (File resourceDir : resourceDirs) {
             if (resourceDir.exists()) {
                 deleteTestDir(resourceDir);
@@ -72,7 +72,7 @@ public class CompilationTestUtils {
      *            field type
      * @return field with given name if present in class
      */
-    static Field assertContainsField(Class<?> clazz, String name, Class<?> type) {
+    static Field assertContainsField(final Class<?> clazz, final String name, final Class<?> type) {
         try {
             Field f = clazz.getDeclaredField(name);
             assertEquals(type, f.getType());
@@ -99,8 +99,8 @@ public class CompilationTestUtils {
      * @param constructorArgs
      *            constructor arguments of class to test
      */
-    static void assertContainsFieldWithValue(Class<?> clazz, String name, Class<?> returnType, Object expectedValue,
-            Class<?>... constructorArgs) {
+    static void assertContainsFieldWithValue(final Class<?> clazz, final String name, final Class<?> returnType, final Object expectedValue,
+            final Class<?>... constructorArgs) {
         Object[] initargs = null;
         if (constructorArgs != null && constructorArgs.length > 0) {
             initargs = new Object[constructorArgs.length];
@@ -127,16 +127,27 @@ public class CompilationTestUtils {
      * @param initargs
      *            array of constructor values
      */
-    static void assertContainsFieldWithValue(Class<?> clazz, String name, Class<?> returnType, Object expectedValue,
-            Class<?>[] constructorArgs, Object... initargs) {
+    static void assertContainsFieldWithValue(final Class<?> clazz, final String name, final Class<?> returnType, final Object expectedValue,
+            final Class<?>[] constructorArgs, final Object... initargs) {
         Field f = assertContainsField(clazz, name, returnType);
         f.setAccessible(true);
+
+        final Object obj;
+        if ((f.getModifiers() & Modifier.STATIC) == 0) {
+            try {
+                Constructor<?> c = clazz.getDeclaredConstructor(constructorArgs);
+                obj = c.newInstance(initargs);
+            } catch (Exception e) {
+                throw new AssertionError("Failed to instantiate object for " + clazz, e);
+            }
+        } else {
+            obj = null;
+        }
+
         try {
-            Constructor<?> c = clazz.getDeclaredConstructor(constructorArgs);
-            Object o = c.newInstance(initargs);
-            assertEquals(expectedValue, f.get(o));
-        } catch (Exception e) {
-            throw new AssertionError("Failed to perform " + name + " field test", e);
+            assertEquals(expectedValue, f.get(obj));
+        } catch (IllegalArgumentException | IllegalAccessException e) {
+            throw new AssertionError("Failed to get field " + name + " of class " + clazz, e);
         }
     }
 
@@ -148,7 +159,7 @@ public class CompilationTestUtils {
      * @param args
      *            array of argument classes
      */
-    static Constructor<?> assertContainsConstructor(Class<?> clazz, Class<?>... args) {
+    static Constructor<?> assertContainsConstructor(final Class<?> clazz, final Class<?>... args) {
         try {
             return clazz.getDeclaredConstructor(args);
         } catch (NoSuchMethodException e) {
@@ -171,7 +182,7 @@ public class CompilationTestUtils {
      *            array of parameter type classes
      * @return method with given name, return type and parameter types
      */
-    static Method assertContainsMethod(Class<?> clazz, Class<?> returnType, String name, Class<?>... args) {
+    static Method assertContainsMethod(final Class<?> clazz, final Class<?> returnType, final String name, final Class<?>... args) {
         try {
             Method m = clazz.getDeclaredMethod(name, args);
             assertEquals(returnType, m.getReturnType());
@@ -194,7 +205,7 @@ public class CompilationTestUtils {
      * @param loader
      *            current class loader
      */
-    static void assertContainsMethod(Class<?> clazz, String returnTypeStr, String name, ClassLoader loader) {
+    static void assertContainsMethod(final Class<?> clazz, final String returnTypeStr, final String name, final ClassLoader loader) {
         Class<?> returnType;
         try {
             returnType = Class.forName(returnTypeStr, true, loader);
@@ -213,7 +224,7 @@ public class CompilationTestUtils {
      * @param clazz
      *            class to test
      */
-    static void assertContainsDefaultMethods(Class<?> clazz) {
+    static void assertContainsDefaultMethods(final Class<?> clazz) {
         assertContainsMethod(clazz, Integer.TYPE, "hashCode");
         assertContainsMethod(clazz, Boolean.TYPE, "equals", Object.class);
         assertContainsMethod(clazz, String.class, "toString");
@@ -230,7 +241,7 @@ public class CompilationTestUtils {
      *            constructor arguments
      * @throws Exception
      */
-    static void assertContainsRestrictionCheck(Constructor<?> constructor, String errorMsg, Object... args)
+    static void assertContainsRestrictionCheck(final Constructor<?> constructor, final String errorMsg, final Object... args)
             throws Exception {
         try {
             constructor.newInstance(args);
@@ -255,7 +266,7 @@ public class CompilationTestUtils {
      *            constructor arguments
      * @throws Exception
      */
-    static void assertContainsRestrictionCheck(Object obj, Method method, String errorMsg, Object... args)
+    static void assertContainsRestrictionCheck(final Object obj, final Method method, final String errorMsg, final Object... args)
             throws Exception {
         try {
             method.invoke(obj, args);
@@ -275,7 +286,7 @@ public class CompilationTestUtils {
      * @param clazz
      *            class to test
      */
-    static void assertContainsGetLengthOrRange(Class<?> clazz, boolean isLength) {
+    static void assertContainsGetLengthOrRange(final Class<?> clazz, final boolean isLength) {
         try {
             Method m = clazz.getDeclaredMethod(isLength ? "length" : "range");
             java.lang.reflect.Type returnType = m.getGenericReturnType();
@@ -306,7 +317,7 @@ public class CompilationTestUtils {
      * @param ifc
      *            expected interface
      */
-    static void assertImplementsIfc(Class<?> clazz, Class<?> ifc) {
+    static void assertImplementsIfc(final Class<?> clazz, final Class<?> ifc) {
         Class<?>[] interfaces = clazz.getInterfaces();
         List<Class<?>> ifcsList = Arrays.asList(interfaces);
         if (!ifcsList.contains(ifc)) {
@@ -323,7 +334,7 @@ public class CompilationTestUtils {
      * @param genericTypeName
      *            fully qualified name of expected parameter type
      */
-    static void testAugmentation(Class<?> clazz, String genericTypeName) {
+    static void testAugmentation(final Class<?> clazz, final String genericTypeName) {
         assertImplementsParameterizedIfc(clazz, AUGMENTATION, genericTypeName);
     }
 
@@ -338,7 +349,7 @@ public class CompilationTestUtils {
      * @param genericTypeName
      *            name of generic type
      */
-    static void assertImplementsParameterizedIfc(Class<?> clazz, String ifcName, String genericTypeName) {
+    static void assertImplementsParameterizedIfc(final Class<?> clazz, final String ifcName, final String genericTypeName) {
         ParameterizedType ifcType = null;
         for (java.lang.reflect.Type ifc : clazz.getGenericInterfaces()) {
             if (ifc instanceof ParameterizedType) {
@@ -363,7 +374,7 @@ public class CompilationTestUtils {
      * @param compiledOutputDir
      *            compiler output directory
      */
-    static void testCompilation(File sourcesOutputDir, File compiledOutputDir) {
+    static void testCompilation(final File sourcesOutputDir, final File compiledOutputDir) {
         JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
         StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null);
         List<File> filesList = getJavaFiles(sourcesOutputDir);
@@ -381,7 +392,7 @@ public class CompilationTestUtils {
      * @param count
      *            expected count of files in directory
      */
-    static void assertFilesCount(File dir, int count) {
+    static void assertFilesCount(final File dir, final int count) {
         File[] dirContent = dir.listFiles();
         if (dirContent == null) {
             throw new AssertionError("File " + dir + " doesn't exists or it's not a directory");
@@ -397,7 +408,7 @@ public class CompilationTestUtils {
      *            directory to search
      * @return List of java files found
      */
-    private static List<File> getJavaFiles(File directory) {
+    private static List<File> getJavaFiles(final File directory) {
         List<File> result = new ArrayList<>();
         File[] filesToRead = directory.listFiles();
         if (filesToRead != null) {
@@ -415,7 +426,7 @@ public class CompilationTestUtils {
         return result;
     }
 
-    static List<File> getSourceFiles(String path) throws Exception {
+    static List<File> getSourceFiles(final String path) throws Exception {
         final URI resPath = BaseCompilationTest.class.getResource(path).toURI();
         final File sourcesDir = new File(resPath);
         if (sourcesDir.exists()) {
@@ -431,7 +442,7 @@ public class CompilationTestUtils {
         }
     }
 
-    static void deleteTestDir(File file) {
+    static void deleteTestDir(final File file) {
         if (file.isDirectory()) {
             File[] filesToDelete = file.listFiles();
             if (filesToDelete != null) {
index 124fadb6cdc2305615ebb1cf402f828c338a44ad..929f8ead287f23bc2c0360bdb50330037dbfc116 100644 (file)
@@ -26,7 +26,6 @@ import static org.opendaylight.yangtools.sal.java.api.generator.test.Compilation
 import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.cleanUp;
 import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.getSourceFiles;
 import static org.opendaylight.yangtools.sal.java.api.generator.test.CompilationTestUtils.testCompilation;
-
 import com.google.common.collect.Range;
 import java.io.File;
 import java.lang.reflect.Constructor;
@@ -205,8 +204,9 @@ public class TypedefCompilationTest extends BaseCompilationTest {
         arg = "abcd";
         expectedMsg = String.format("Invalid length: %s, expected: %s.", arg, lengthConstraints);
         assertContainsRestrictionCheck(expectedConstructor, expectedMsg, arg);
-        obj = expectedConstructor.newInstance("hello world");
-        assertEquals(obj, defInst.invoke(null, "hello world"));
+
+        obj = expectedConstructor.newInstance("abcde");
+        assertEquals(obj, defInst.invoke(null, "abcde"));
 
         // typedef string-ext2
         assertFalse(stringExt2Class.isInterface());
@@ -226,8 +226,8 @@ public class TypedefCompilationTest extends BaseCompilationTest {
         arg = "abcde";
         expectedMsg = String.format("Invalid length: %s, expected: %s.", arg, lengthConstraints);
         assertContainsRestrictionCheck(expectedConstructor, expectedMsg, arg);
-        obj = expectedConstructor.newInstance("helloWorld");
-        assertEquals(obj, defInst.invoke(null, "helloWorld"));
+        obj = expectedConstructor.newInstance("abcdef");
+        assertEquals(obj, defInst.invoke(null, "abcdef"));
 
         // typedef string-ext3
         assertFalse(stringExt3Class.isInterface());
@@ -241,8 +241,8 @@ public class TypedefCompilationTest extends BaseCompilationTest {
         defInst = assertContainsMethod(stringExt3Class, stringExt3Class, "getDefaultInstance", String.class);
         // assertEquals(1, stringExt3Class.getDeclaredMethods().length);
 
-        obj = expectedConstructor.newInstance("helloWorld");
-        assertEquals(obj, defInst.invoke(null, "helloWorld"));
+        obj = expectedConstructor.newInstance("bbbbbb");
+        assertEquals(obj, defInst.invoke(null, "bbbbbb"));
 
         // typedef my-decimal-type
         assertFalse(myDecimalTypeClass.isInterface());
index a18f6edc17039b72c7ea0fab6943775a7b546179..30edbf4d01983543e6af8aa2633db8e3c9085000 100644 (file)
@@ -8,10 +8,8 @@
 package org.opendaylight.yangtools.objcache;
 
 import com.google.common.base.Preconditions;
-
 import javax.annotation.Nonnull;
 import javax.annotation.concurrent.GuardedBy;
-
 import org.opendaylight.yangtools.objcache.impl.StaticObjectCacheBinder;
 import org.opendaylight.yangtools.objcache.spi.IObjectCacheFactory;
 import org.opendaylight.yangtools.objcache.spi.NoopObjectCacheBinder;
@@ -22,6 +20,10 @@ import org.opendaylight.yangtools.objcache.spi.NoopObjectCacheBinder;
 public final class ObjectCacheFactory {
     private static volatile IObjectCacheFactory factory;
 
+    private ObjectCacheFactory() {
+        throw new UnsupportedOperationException("Utility class should not be instantiated");
+    }
+
     @GuardedBy("this")
     private static synchronized IObjectCacheFactory initialize() {
         // Double-check under lock
index c70fd8c85d7244ab1a54d130de80a86e5a17b662..a9970deee5100cfd2408f7f6bdbd9af84fdae014 100644 (file)
@@ -18,6 +18,10 @@ import java.util.List;
  */
 public final class LazyCollections {
 
+    private LazyCollections() {
+        throw new UnsupportedOperationException("Utility class should not be instantiated");
+    }
+
     /**
      * Add an element to a list, potentially transforming the list.
      *
index a24b67c5a94f61ab1d7625daefaef9be56fefd75..23e9dbc1c5a74df1c751ed433e2547880496d96f 100644 (file)
@@ -40,7 +40,7 @@ module isis-topology {
        typedef iso-net-id {
         description "ISO NET ID. RFC 1237";
         type string {
-            pattern '[0-9a-fA-F]{2}((.[0-9a-fA-F]{4}){6}*)';
+            pattern '[0-9a-fA-F]{2}((.[0-9a-fA-F]{4}){6})';
         }
     }
 
index 03860286cd21a68aa5b05a149b684206aa5d40bf..bb34d1e343f76f96856ff21faa9b01007376885c 100644 (file)
@@ -7,7 +7,12 @@
  */
 package org.opendaylight.yangtools.restconf.common;
 
-public class MediaTypes {
+public final class MediaTypes {
+
+    private MediaTypes() {
+        throw new UnsupportedOperationException("Utility class should not be instantiated");
+    }
+
     public static final String API = "application/vnd.yang.api";
     public static final String DATASTORE = "application/vnd.yang.datastore";
     public static final String DATA = "application/vnd.yang.data";
index 0ba364f74f21b0d84cf71d0b143907480153c21b..dc79f118c38ad079053d600af7d2c7798655aded 100644 (file)
@@ -76,7 +76,7 @@ public class RestconfUtilsTest {
                 .getAugmentation(IgpNodeAttributes1.class);
         assertNotNull(igpAttributes1);
         assertNotNull(igpAttributes1.getIsisNodeAttributes());
-        assertEquals("66", igpAttributes1.getIsisNodeAttributes().getIso().getIsoSystemId().getValue());
+        assertEquals("0000.1111.2222", igpAttributes1.getIsisNodeAttributes().getIso().getIsoSystemId().getValue());
     }
 
 }
index 47756de1346b7324ea57a06d6de9a0b8fccd31f5..ca5b499b5d394fd8d8a0a9dfe0e0428f6abdf0fc 100644 (file)
@@ -7,7 +7,7 @@
             <router-id>42.42.42.42</router-id>
             <isis-node-attributes xmlns="urn:TBD:params:xml:ns:yang:network:isis-topology">
                 <iso>
-                    <iso-system-id>66</iso-system-id>
+                    <iso-system-id>0000.1111.2222</iso-system-id>
                 </iso>
                 <ted>
                     <te-router-id-ipv4>42.42.42.42</te-router-id-ipv4>
@@ -15,4 +15,4 @@
             </isis-node-attributes>
         </igp-node-attributes>
     </node>
-</topology>
\ No newline at end of file
+</topology>
index 9840338bb9442bd82db429ef1a2379db6a45d2ee..934c90d9ae77aea68079ad3b0a91eb6489dda1bc 100644 (file)
@@ -479,8 +479,13 @@ public class InstanceIdentifier<T extends DataObject> implements Path<InstanceId
      *
      * @param id instance identifier
      * @return key associated with the last component
+     * @throws IllegalArgumentException if the supplied identifier type cannot have a key.
+     * @throws NullPointerException if id is null.
      */
     public static <N extends Identifiable<K> & DataObject, K extends Identifier<N>> K keyOf(final InstanceIdentifier<N> id) {
+        Preconditions.checkNotNull(id);
+        Preconditions.checkArgument(id instanceof KeyedInstanceIdentifier, "%s does not have a key", id);
+
         @SuppressWarnings("unchecked")
         final K ret = ((KeyedInstanceIdentifier<N, K>)id).getKey();
         return ret;
index 452b2fa99e78965f5949a83801f738db137be34b..aae0692e398ea3bbf3c9e9139971e11eae68eac1 100644 (file)
@@ -7,6 +7,7 @@
  */
 package org.opendaylight.yangtools.yang.common;
 
+import com.google.common.base.Objects;
 import java.io.Serializable;
 import java.net.URI;
 import java.net.URISyntaxException;
@@ -163,4 +164,9 @@ public final class QNameModule implements Immutable, Serializable {
         }
         return compositeURI;
     }
+
+    @Override
+    public String toString() {
+        return Objects.toStringHelper(this).omitNullValues().add("ns", getNamespace()).add("rev", getFormattedRevision()).toString();
+    }
 }
index fd50c95ab8c10bfab7ec04363d152995fa299d58..dbffc30acc292e83ba3d2ac8d6ec94065a8cdc64 100644 (file)
@@ -10,14 +10,20 @@ package org.opendaylight.yangtools.yang.common;
 
 import java.text.SimpleDateFormat;
 
-public class SimpleDateFormatUtil {
+public final class SimpleDateFormatUtil {
+
+    private SimpleDateFormatUtil() {
+        throw new UnsupportedOperationException("Utility class should not be instantiated");
+    }
 
     private static final ThreadLocal<SimpleDateFormat> REVISION_FORMAT = new ThreadLocal<SimpleDateFormat>() {
 
+        @Override
         protected SimpleDateFormat initialValue() {
             return new SimpleDateFormat("yyyy-MM-dd");
         };
 
+        @Override
         public void set(SimpleDateFormat value) {
             throw new UnsupportedOperationException();
         };
index 6ab21040c60eb14d42260841718261384dade6da..7a22b08650d2a9dab4f2f7befc6d5b0f217b543d 100644 (file)
@@ -7,13 +7,17 @@
  */
 package org.opendaylight.yangtools.yang.data.composite.node.schema.json;
 
+import com.google.common.collect.LinkedListMultimap;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
 import org.opendaylight.yangtools.yang.data.api.Node;
 
-import com.google.common.collect.LinkedListMultimap;
+public final class CnSnToNormalizedNodesUtils {
 
-public class CnSnToNormalizedNodesUtils {
+
+    private CnSnToNormalizedNodesUtils() {
+        throw new UnsupportedOperationException("Utility class should not be instantiated");
+    }
 
     public static LinkedListMultimap<QName, Node<?>> mapChildElementsForSingletonNode(Node<?> node) {
         return mapChildElements( ((CompositeNode)node).getValue());
index 3b501d50ebec4bfce1fee68e86259767ba314d4a..a7b14062170bab6c7896c49dcdacbb2d1922adac 100644 (file)
@@ -1,13 +1,11 @@
 <?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">
+<!-- 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>
@@ -29,8 +27,8 @@
                 <artifactId>maven-surefire-plugin</artifactId>
                 <version>${maven.surefire.version}</version>
                 <configuration>
-                    <argLine>-Dlog4j.configuration=log4j-test.xml
-                        -Xmx1500m ${jacoco.agent.ut.arg}</argLine>
+                <argLine>-Dlog4j.configuration=log4j-test.xml
+                    -Xmx1500m ${jacoco.agent.ut.arg}</argLine>
                     <redirectTestOutputToFile>true</redirectTestOutputToFile>
                 </configuration>
             </plugin>
@@ -88,8 +86,8 @@
             <scope>test</scope>
         </dependency>
         <dependency>
-          <groupId>org.mockito</groupId>
-          <artifactId>mockito-core</artifactId>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
         </dependency>
         <dependency>
             <groupId>org.slf4j</groupId>
index ed2ff2c35a9f04e2f1254a8389c94095d12f2dd7..17906a06e55dae95f2962ffb05cc36e624c321b9 100644 (file)
@@ -8,7 +8,6 @@
 package org.opendaylight.yangtools.yang.data.impl.codec;
 
 import java.util.Map.Entry;
-
 import org.opendaylight.yangtools.yang.common.QName;
 
 public class ValueWithQName<V> implements Entry<QName, V>{
@@ -26,6 +25,7 @@ public class ValueWithQName<V> implements Entry<QName, V>{
         return qname;
     }
 
+    @Override
     public V getValue() {
         return value;
     }
@@ -63,10 +63,12 @@ public class ValueWithQName<V> implements Entry<QName, V>{
         @SuppressWarnings("rawtypes")
         ValueWithQName other = (ValueWithQName) obj;
         if (qname == null) {
-            if (other.qname != null)
+            if (other.qname != null) {
                 return false;
-        } else if (!qname.equals(other.qname))
+            }
+        } else if (!qname.equals(other.qname)) {
             return false;
+        }
         if (value == null) {
             if (other.value != null) {
                 return false;
index 347cc42cdc0d0d811a5f92db9d2a564bba62dd4f..563641fd68161f87e7e2cdc401469880ee107100 100644 (file)
@@ -9,7 +9,6 @@ package org.opendaylight.yangtools.yang.data.impl.codec.xml;
 
 import java.net.URI;
 import java.util.Map.Entry;
-
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
index 97f676ae69bd62636764d138ea74e2ee4a678fb9..7f2c3019d35af9356115f33ff3ecc3da77e7a20f 100644 (file)
@@ -36,14 +36,15 @@ import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
  * {@link XMLStreamWriter}, resulting in a RFC 6020 XML encoding.
  */
 public final class XMLStreamNormalizedNodeStreamWriter implements NormalizedNodeStreamWriter {
-    private static final XmlStreamUtils UTILS = XmlStreamUtils.create(XmlUtils.DEFAULT_XML_CODEC_PROVIDER);
 
     private final XMLStreamWriter writer;
     private final SchemaTracker tracker;
+    private final XmlStreamUtils streamUtils;
 
     private XMLStreamNormalizedNodeStreamWriter(final XMLStreamWriter writer, final SchemaContext context, final SchemaPath path) {
         this.writer = Preconditions.checkNotNull(writer);
         this.tracker = SchemaTracker.create(context, path);
+        this.streamUtils = XmlStreamUtils.create(XmlUtils.DEFAULT_XML_CODEC_PROVIDER, context);
     }
 
     /**
@@ -82,7 +83,19 @@ public final class XMLStreamNormalizedNodeStreamWriter implements NormalizedNode
         try {
             writeStartElement(qname);
             if (value != null) {
-                UTILS.writeValue(writer, type, value);
+                streamUtils.writeValue(writer, type, value);
+            }
+            writer.writeEndElement();
+        } catch (XMLStreamException e) {
+            throw new IOException("Failed to emit element", e);
+        }
+    }
+
+    private void writeElement(final QName qname, final SchemaNode schemaNode, final Object value) throws IOException {
+        try {
+            writeStartElement(qname);
+            if (value != null) {
+                streamUtils.writeValue(writer, schemaNode, value);
             }
             writer.writeEndElement();
         } catch (XMLStreamException e) {
@@ -110,8 +123,7 @@ public final class XMLStreamNormalizedNodeStreamWriter implements NormalizedNode
     @Override
     public void leafNode(final NodeIdentifier name, final Object value) throws IOException {
         final LeafSchemaNode schema = tracker.leafNode(name);
-
-        writeElement(schema.getQName(), schema.getType(), value);
+        writeElement(schema.getQName(), schema, value);
     }
 
     @Override
@@ -122,7 +134,7 @@ public final class XMLStreamNormalizedNodeStreamWriter implements NormalizedNode
     @Override
     public void leafSetEntryNode(final Object value) throws IOException {
         final LeafListSchemaNode schema = tracker.leafSetEntryNode();
-        writeElement(schema.getQName(), schema.getType(), value);
+        writeElement(schema.getQName(), schema, value);
     }
 
     @Override
@@ -173,7 +185,7 @@ public final class XMLStreamNormalizedNodeStreamWriter implements NormalizedNode
         try {
             writeStartElement(qname);
             if (value != null) {
-                UTILS.writeValue(writer, (Node<?>)value, schema);
+                streamUtils.writeValue(writer, (Node<?>)value, schema);
             }
             writer.writeEndElement();
         } catch (XMLStreamException e) {
index 0375310ad80bf94193c12b4c388311a3fcf4623f..fa22e9847d3439fa4e32f94515241a86a4d5739c 100644 (file)
@@ -15,7 +15,6 @@ import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableList;
-
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -24,7 +23,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Set;
-
 import javax.activation.UnsupportedDataTypeException;
 import javax.annotation.Nonnull;
 import javax.xml.parsers.DocumentBuilder;
@@ -34,7 +32,6 @@ import javax.xml.stream.XMLOutputFactory;
 import javax.xml.stream.XMLStreamException;
 import javax.xml.stream.XMLStreamWriter;
 import javax.xml.transform.dom.DOMResult;
-
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.AttributesContainer;
 import org.opendaylight.yangtools.yang.data.api.CompositeNode;
@@ -44,6 +41,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
 import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
 import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
 import org.opendaylight.yangtools.yang.data.impl.codec.TypeDefinitionAwareCodec;
+import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
@@ -58,7 +56,9 @@ import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
 import org.opendaylight.yangtools.yang.model.util.InstanceIdentifierType;
+import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Attr;
@@ -66,7 +66,12 @@ import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.NodeList;
 
-public class XmlDocumentUtils {
+public final class XmlDocumentUtils {
+
+    private XmlDocumentUtils() {
+        throw new UnsupportedOperationException("Utility class should not be instantiated");
+    }
+
     private static class ElementWithSchemaContext {
         Element element;
         SchemaContext schemaContext;
@@ -97,12 +102,36 @@ public class XmlDocumentUtils {
      * Node Container Schema and transformed accordingly.
      *
      * @param data Data DOM root element
-     * @param schema Data Node Container Schema
+     * @param schemaNode Data Node Container Schema
      * @param codecProvider XML Codec Provider
      * @return new instance of XML Document
      * @throws UnsupportedDataTypeException
+     *
+     * @deprecated Use {@link #toDocument(org.opendaylight.yangtools.yang.data.api.CompositeNode, com.google.common.base.Optional, org.opendaylight.yangtools.yang.model.api.DataNodeContainer, XmlCodecProvider)} instead.
+     * The whole schema context allows for proper serialization of leafrefs.
+     */
+    @Deprecated
+    public static Document toDocument(final CompositeNode data, final DataNodeContainer schemaNode, final XmlCodecProvider codecProvider)
+            throws UnsupportedDataTypeException {
+        return toDocument(data, Optional.<SchemaContext>absent(), schemaNode, codecProvider);
+    }
+
+    /**
+     * Serializes data DOM node into a w3c DOM document. Whole schema context is used to resolve leafref elements.
+     *
+     * @param data Data DOM root element
+     * @param schemaContext Entire schema context for correct leafref resolution
+     * @param schema Data Node Container Schema
+     * @param codecProvider XML Codec Provider
+     * @return serialized w3c DOM document
+     * @throws UnsupportedDataTypeException
      */
-    public static Document toDocument(final CompositeNode data, final DataNodeContainer schema, final XmlCodecProvider codecProvider)
+    public static Document toDocument(final CompositeNode data, final SchemaContext schemaContext, final DataNodeContainer schemaNode, final XmlCodecProvider codecProvider)
+            throws UnsupportedDataTypeException {
+        return toDocument(data, Optional.of(schemaContext), schemaNode, codecProvider);
+    }
+
+    private static Document toDocument(final CompositeNode data, final Optional<SchemaContext> schemaContext, final DataNodeContainer schema, final XmlCodecProvider codecProvider)
             throws UnsupportedDataTypeException {
         Preconditions.checkNotNull(data);
         Preconditions.checkNotNull(schema);
@@ -114,7 +143,8 @@ public class XmlDocumentUtils {
         final DOMResult result = new DOMResult(getDocument());
         try {
             final XMLStreamWriter writer = FACTORY.createXMLStreamWriter(result);
-            XmlStreamUtils.create(codecProvider).writeDocument(writer, data, (SchemaNode)schema);
+            XmlStreamUtils xmlStreamUtils = schemaContext.isPresent() ? XmlStreamUtils.create(codecProvider, schemaContext.get()) : XmlStreamUtils.create(codecProvider);
+            xmlStreamUtils.writeDocument(writer, data, (SchemaNode) schema);
             writer.close();
             return (Document)result.getNode();
         } catch (XMLStreamException e) {
@@ -219,6 +249,8 @@ public class XmlDocumentUtils {
             return toSimpleNodeWithType(xmlElement, (LeafSchemaNode) schema, codecProvider,schemaCtx);
         } else if (schema instanceof LeafListSchemaNode) {
             return toSimpleNodeWithType(xmlElement, (LeafListSchemaNode) schema, codecProvider,schemaCtx);
+        } else if (schema instanceof AnyXmlSchemaNode) {
+            return toDomNode(xmlElement);
         }
         return null;
     }
@@ -243,7 +275,13 @@ public class XmlDocumentUtils {
 
     private static Object resolveValueFromSchemaType(final Element xmlElement, final DataSchemaNode schema, final TypeDefinition<?> type,
         final XmlCodecProvider codecProvider,final SchemaContext schemaCtx) {
-        final TypeDefinition<?> baseType = XmlUtils.resolveBaseTypeFrom(type);
+
+        TypeDefinition<?> baseType = XmlUtils.resolveBaseTypeFrom(type);
+        if (baseType instanceof LeafrefTypeDefinition) {
+            final LeafrefTypeDefinition leafrefTypeDefinition = (LeafrefTypeDefinition) baseType;
+            baseType = SchemaContextUtil.getBaseTypeForLeafRef(leafrefTypeDefinition, schemaCtx, schema);
+        }
+
         final String text = xmlElement.getTextContent();
         final Object value;
 
@@ -252,7 +290,7 @@ public class XmlDocumentUtils {
         } else if (baseType instanceof IdentityrefTypeDefinition) {
             value = InstanceIdentifierForXmlCodec.toIdentity(text, xmlElement, schemaCtx);
         } else {
-            final TypeDefinitionAwareCodec<?, ?> codec = codecProvider.codecFor(type);
+            final TypeDefinitionAwareCodec<?, ?> codec = codecProvider.codecFor(baseType);
             if (codec == null) {
                 LOG.info("No codec for schema {}, falling back to text", schema);
                 value = text;
index d0292d1029ce9cde5181aefb6d82d0f28b307d44..f167b41bb72f5274ba27bedfd0486da63ccf3a7a 100644 (file)
@@ -2,6 +2,7 @@ package org.opendaylight.yangtools.yang.data.impl.codec.xml;
 
 import com.google.common.annotations.Beta;
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import java.net.URI;
 import java.util.Collection;
@@ -25,10 +26,13 @@ import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
+import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -40,9 +44,15 @@ import org.slf4j.LoggerFactory;
 public class XmlStreamUtils {
     private static final Logger LOG = LoggerFactory.getLogger(XmlStreamUtils.class);
     private final XmlCodecProvider codecProvider;
+    private final Optional<SchemaContext> schemaContext;
 
     protected XmlStreamUtils(final XmlCodecProvider codecProvider) {
+        this(codecProvider, null);
+    }
+
+    private XmlStreamUtils(XmlCodecProvider codecProvider, SchemaContext schemaContext) {
         this.codecProvider = Preconditions.checkNotNull(codecProvider);
+        this.schemaContext = Optional.fromNullable(schemaContext);
     }
 
     /**
@@ -180,10 +190,8 @@ public class XmlStreamUtils {
 
         if (data instanceof SimpleNode<?>) {
             // Simple node
-            if (schema instanceof LeafListSchemaNode) {
-                writeValue(writer, ((LeafListSchemaNode) schema).getType(), data.getValue());
-            } else if (schema instanceof LeafSchemaNode) {
-                writeValue(writer, ((LeafSchemaNode) schema).getType(), data.getValue());
+            if (schema instanceof LeafListSchemaNode || schema instanceof LeafSchemaNode) {
+                writeValue(writer, schema, data.getValue());
             } else {
                 Object value = data.getValue();
                 if (value != null) {
@@ -264,7 +272,39 @@ public class XmlStreamUtils {
      * emitted by the caller.
      *
      * @param writer XML Stream writer
-     * @param type data type
+     * @param schemaNode Schema node that describes the value
+     * @param value data value
+     * @throws XMLStreamException if an encoding problem occurs
+     */
+    public void writeValue(final @Nonnull XMLStreamWriter writer, final @Nonnull SchemaNode schemaNode, final Object value) throws XMLStreamException {
+        if (value == null) {
+            LOG.debug("Value of {}:{} is null, not encoding it", schemaNode.getQName().getNamespace(), schemaNode.getQName().getLocalName());
+            return;
+        }
+
+        Preconditions.checkArgument(schemaNode instanceof LeafSchemaNode || schemaNode instanceof LeafListSchemaNode,
+                "Unable to write value for node %s, only nodes of type: leaf and leaf-list can be written at this point", schemaNode.getQName());
+
+        TypeDefinition<?> type = schemaNode instanceof LeafSchemaNode ?
+                ((LeafSchemaNode) schemaNode).getType():
+                ((LeafListSchemaNode) schemaNode).getType();
+
+        TypeDefinition<?> baseType = XmlUtils.resolveBaseTypeFrom(type);
+
+        if (schemaContext.isPresent() && baseType instanceof LeafrefTypeDefinition) {
+            LeafrefTypeDefinition leafrefTypeDefinition = (LeafrefTypeDefinition) baseType;
+            baseType = SchemaContextUtil.getBaseTypeForLeafRef(leafrefTypeDefinition, schemaContext.get(), schemaNode);
+        }
+
+        writeValue(writer, baseType, value);
+    }
+
+    /**
+     * Write a value into a XML stream writer. This method assumes the start and end of element is
+     * emitted by the caller.
+     *
+     * @param writer XML Stream writer
+     * @param type data type. In case of leaf ref this should be the type of leaf being referenced
      * @param value data value
      * @throws XMLStreamException if an encoding problem occurs
      */
@@ -273,8 +313,8 @@ public class XmlStreamUtils {
             LOG.debug("Value of {}:{} is null, not encoding it", type.getQName().getNamespace(), type.getQName().getLocalName());
             return;
         }
+        TypeDefinition<?> baseType = XmlUtils.resolveBaseTypeFrom(type);
 
-        final TypeDefinition<?> baseType = XmlUtils.resolveBaseTypeFrom(type);
         if (baseType instanceof IdentityrefTypeDefinition) {
             write(writer, (IdentityrefTypeDefinition) baseType, value);
         } else if (baseType instanceof InstanceIdentifierTypeDefinition) {
@@ -325,4 +365,8 @@ public class XmlStreamUtils {
             writer.writeCharacters(String.valueOf(value));
         }
     }
+
+    public static XmlStreamUtils create(XmlCodecProvider codecProvider, SchemaContext schemaContext) {
+        return new XmlStreamUtils(codecProvider, schemaContext);
+    }
 }
index 2ee7ee174e31a65b9370f89665958198698cfb03..c2081f37de9875f78e6c4ba2495f9c1bfadf3b50 100644 (file)
@@ -9,7 +9,6 @@ package org.opendaylight.yangtools.yang.data.impl.schema;
 
 import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
-import org.opendaylight.yangtools.yang.data.api.Node;
 import org.opendaylight.yangtools.yang.data.api.schema.AnyXmlNode;
 import org.opendaylight.yangtools.yang.data.api.schema.AugmentationNode;
 import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
index fe3d1841a2bd8b67041aa66b7cddaa40120cb4e9..3ac6f32b0871a27a5982e77c25af8c83eb8ae642 100644 (file)
@@ -8,27 +8,38 @@
 package org.opendaylight.yangtools.yang.data.impl.schema;
 
 import com.google.common.base.Preconditions;
-
 import java.io.IOException;
 import java.util.ArrayDeque;
 import java.util.Deque;
 import java.util.List;
-
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.ChoiceNode;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
 import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNode;
+import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
 import org.opendaylight.yangtools.yang.data.api.schema.stream.NormalizedNodeStreamWriter;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeAttrBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.DataContainerNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableAugmentationNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableChoiceNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableContainerNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapEntryNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableMapNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableOrderedMapNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListEntryNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableUnkeyedListNodeBuilder;
 
 /**
@@ -83,11 +94,10 @@ public class ImmutableNormalizedNodeStreamWriter implements NormalizedNodeStream
      * <p>
      * This method is useful for clients, which knows there will be one
      * top level node written, but does not know which type of {@link NormalizedNode}
-     * will be writen.
-     *
+     * will be written.
      *
      * @param result {@link NormalizedNodeResult} object which will hold result value.
-     * @return {@link NormalizedNodeStreamWriter} whcih will write item to supplied result holder.
+     * @return {@link NormalizedNodeStreamWriter} which will write item to supplied result holder.
      */
     public static final NormalizedNodeStreamWriter from(final NormalizedNodeResult result) {
         return new ImmutableNormalizedNodeStreamWriter(new NormalizedNodeResultBuilder(result));
@@ -127,9 +137,10 @@ public class ImmutableNormalizedNodeStreamWriter implements NormalizedNodeStream
     }
 
     @Override
-    public void startLeafSet(final NodeIdentifier name,final int childSizeHint) throws IllegalArgumentException {
+    public void startLeafSet(final NodeIdentifier name, final int childSizeHint) throws IllegalArgumentException {
         checkDataNodeContainer();
-        ListNodeBuilder<Object, LeafSetEntryNode<Object>> builder = Builders.leafSetBuilder();
+        ListNodeBuilder<Object, LeafSetEntryNode<Object>> builder = UNKNOWN_SIZE == childSizeHint ?
+                ImmutableLeafSetNodeBuilder.create() : ImmutableLeafSetNodeBuilder.create(childSizeHint);
         builder.withNodeIdentifier(name);
         enter(builder);
     }
@@ -145,53 +156,73 @@ public class ImmutableNormalizedNodeStreamWriter implements NormalizedNodeStream
     @Override
     public void anyxmlNode(final NodeIdentifier name, final Object value) throws IllegalArgumentException {
         checkDataNodeContainer();
-
-
     }
 
     @Override
-    public void startContainerNode(final NodeIdentifier name,final int childSizeHint) throws IllegalArgumentException {
+    public void startContainerNode(final NodeIdentifier name, final int childSizeHint) throws IllegalArgumentException {
         checkDataNodeContainer();
-        enter(Builders.containerBuilder().withNodeIdentifier(name));
+
+        final DataContainerNodeAttrBuilder<NodeIdentifier, ContainerNode> builder = UNKNOWN_SIZE == childSizeHint ?
+                ImmutableContainerNodeBuilder.create() : ImmutableContainerNodeBuilder.create(childSizeHint);
+        enter(builder.withNodeIdentifier(name));
     }
 
     @Override
-    public void startUnkeyedList(final NodeIdentifier name,final int childSizeHint) throws IllegalArgumentException {
+    public void startUnkeyedList(final NodeIdentifier name, final int childSizeHint) throws IllegalArgumentException {
         checkDataNodeContainer();
-        enter(Builders.unkeyedListBuilder().withNodeIdentifier(name));
+
+        final CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode> builder = UNKNOWN_SIZE == childSizeHint ?
+                ImmutableUnkeyedListNodeBuilder.create() : ImmutableUnkeyedListNodeBuilder.create(childSizeHint);
+        enter(builder.withNodeIdentifier(name));
     }
 
     @Override
-    public void startUnkeyedListItem(final NodeIdentifier name,final int childSizeHint) throws IllegalStateException {
+    public void startUnkeyedListItem(final NodeIdentifier name, final int childSizeHint) throws IllegalStateException {
         Preconditions.checkArgument(getCurrent() instanceof ImmutableUnkeyedListNodeBuilder);
-        enter(Builders.unkeyedListEntryBuilder().withNodeIdentifier(name));
+
+        final DataContainerNodeAttrBuilder<NodeIdentifier, UnkeyedListEntryNode> builder = UNKNOWN_SIZE == childSizeHint ?
+                ImmutableUnkeyedListEntryNodeBuilder.create() : ImmutableUnkeyedListEntryNodeBuilder.create(childSizeHint);
+        enter(builder.withNodeIdentifier(name));
     }
 
     @Override
-    public void startMapNode(final NodeIdentifier name,final int childSizeHint) throws IllegalArgumentException {
+    public void startMapNode(final NodeIdentifier name, final int childSizeHint) throws IllegalArgumentException {
         checkDataNodeContainer();
-        enter(Builders.mapBuilder().withNodeIdentifier(name));
+
+        final CollectionNodeBuilder<MapEntryNode, MapNode> builder = UNKNOWN_SIZE == childSizeHint ?
+                ImmutableMapNodeBuilder.create() : ImmutableMapNodeBuilder.create(childSizeHint);
+        enter(builder.withNodeIdentifier(name));
     }
 
     @Override
-    public void startMapEntryNode(final NodeIdentifierWithPredicates identifier,final int childSizeHint) throws IllegalArgumentException {
+    public void startMapEntryNode(final NodeIdentifierWithPredicates identifier, final int childSizeHint) throws IllegalArgumentException {
         if(!(getCurrent() instanceof NormalizedNodeResultBuilder)) {
             Preconditions.checkArgument(getCurrent() instanceof ImmutableMapNodeBuilder || getCurrent() instanceof ImmutableOrderedMapNodeBuilder);
         }
-        enter(Builders.mapEntryBuilder().withNodeIdentifier(identifier));
+
+        final DataContainerNodeAttrBuilder<NodeIdentifierWithPredicates, MapEntryNode> builder = UNKNOWN_SIZE == childSizeHint ?
+                ImmutableMapEntryNodeBuilder.create() : ImmutableMapEntryNodeBuilder.create(childSizeHint);
+        enter(builder.withNodeIdentifier(identifier));
     }
 
     @Override
-    public void startOrderedMapNode(final NodeIdentifier name,final int childSizeHint) throws IllegalArgumentException {
+    public void startOrderedMapNode(final NodeIdentifier name, final int childSizeHint) throws IllegalArgumentException {
         checkDataNodeContainer();
-        enter(Builders.orderedMapBuilder().withNodeIdentifier(name));
+
+        final CollectionNodeBuilder<MapEntryNode, OrderedMapNode> builder = UNKNOWN_SIZE == childSizeHint ?
+                ImmutableOrderedMapNodeBuilder.create() : ImmutableOrderedMapNodeBuilder.create(childSizeHint);
+        enter(builder.withNodeIdentifier(name));
     }
 
     @Override
-    public void startChoiceNode(final NodeIdentifier name,final int childSizeHint) throws IllegalArgumentException {
+    public void startChoiceNode(final NodeIdentifier name, final int childSizeHint) throws IllegalArgumentException {
         checkDataNodeContainer();
-        enter(Builders.choiceBuilder().withNodeIdentifier(name));
+
+        final DataContainerNodeBuilder<NodeIdentifier, ChoiceNode> builder = UNKNOWN_SIZE == childSizeHint ?
+                ImmutableChoiceNodeBuilder.create() : ImmutableChoiceNodeBuilder.create(childSizeHint);
+        enter(builder.withNodeIdentifier(name));
     }
+
     @Override
     public void startAugmentationNode(final AugmentationIdentifier identifier) throws IllegalArgumentException {
         checkDataNodeContainer();
index bb271684e967494043c1d13a7ff4f88d64856168..cb50fefc8df70e7da24a5d83e48c1dec08774646 100644 (file)
@@ -10,7 +10,6 @@ package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
@@ -20,7 +19,7 @@ import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNo
 import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableDataContainerNode;
 
 abstract class AbstractImmutableDataContainerNodeBuilder<I extends YangInstanceIdentifier.PathArgument, R extends DataContainerNode<I>> implements DataContainerNodeBuilder<I, R> {
-
+    private static final int DEFAULT_CAPACITY = 4;
     private Map<YangInstanceIdentifier.PathArgument, DataContainerChild<? extends YangInstanceIdentifier.PathArgument, ?>> value;
     private I nodeIdentifier;
 
@@ -33,17 +32,28 @@ abstract class AbstractImmutableDataContainerNodeBuilder<I extends YangInstanceI
     private boolean dirty;
 
     protected AbstractImmutableDataContainerNodeBuilder() {
-        this.value = new HashMap<>();
+        this.value = new HashMap<>(DEFAULT_CAPACITY);
         this.dirty = false;
     }
 
     protected AbstractImmutableDataContainerNodeBuilder(final int sizeHint) {
-        this.value = new HashMap<>(sizeHint);
+        this.value = new HashMap<>(DEFAULT_CAPACITY);
         this.dirty = false;
     }
 
     protected AbstractImmutableDataContainerNodeBuilder(final AbstractImmutableDataContainerNode<I> node) {
         this.nodeIdentifier = node.getIdentifier();
+
+        /*
+         * FIXME: BUG-2402: this call is not what we actually want. We are the
+         *        only user of getChildren(), and we really want this to be a
+         *        zero-copy operation if we happen to not modify the children.
+         *        If we do, we want to perform an efficient copy-on-write before
+         *        we make the change.
+         *
+         *        With this interface we end up creating a lot of short-lived
+         *        objects in case we modify the map -- see checkDirty().
+         */
         this.value = node.getChildren();
         this.dirty = true;
     }
@@ -63,6 +73,13 @@ abstract class AbstractImmutableDataContainerNodeBuilder<I extends YangInstanceI
 
     private void checkDirty() {
         if (dirty) {
+            /*
+             * FIXME: BUG-2402: This is the second part of the above. Note
+             *        that value here is usually a read-only view. Invocation
+             *        of this constructor will force instantiation of a wrapper
+             *        Map.Entry object, just to make sure this read path does
+             *        not modify the map.
+             */
             value = new HashMap<>(value);
             dirty = false;
         }
index 219f58c522165d174f7dc662f3fcc5371939cdf6..40c7a654d3fd8f33f5000ea24dd8839bffb64d7a 100644 (file)
@@ -7,15 +7,14 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
 
+import com.google.common.base.Preconditions;
 import java.util.Map;
-
+import java.util.Objects;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedValueAttrNode;
 
-import com.google.common.base.Preconditions;
-
 public class ImmutableLeafSetEntryNodeBuilder<T> extends AbstractImmutableNormalizedNodeBuilder<YangInstanceIdentifier.NodeWithValue, T, LeafSetEntryNode<T>> {
 
     public static <T> ImmutableLeafSetEntryNodeBuilder<T> create() {
@@ -31,7 +30,7 @@ public class ImmutableLeafSetEntryNodeBuilder<T> extends AbstractImmutableNormal
 
         ImmutableLeafSetEntryNode(final YangInstanceIdentifier.NodeWithValue nodeIdentifier, final T value, final Map<QName, String> attributes) {
             super(nodeIdentifier, value, attributes);
-            Preconditions.checkArgument(nodeIdentifier.getValue().equals(value),
+            Preconditions.checkArgument(Objects.deepEquals(nodeIdentifier.getValue(), value),
                     "Node identifier contains different value: %s than value itself: %s", nodeIdentifier, value);
         }
     }
index dd5048103c7a32f5ff3e9a62fe012ee27e4f354b..71b4bbc7606433dd53ee85ecbf709f21a99939dc 100644 (file)
@@ -7,11 +7,12 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
 
+import com.google.common.base.Optional;
+import com.google.common.collect.Iterables;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-
 import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.util.MapAdaptor;
 import org.opendaylight.yangtools.yang.common.QName;
@@ -25,16 +26,17 @@ import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNo
 import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedValueNode;
 
-import com.google.common.base.Optional;
-import com.google.common.collect.Iterables;
-
 public class ImmutableLeafSetNodeBuilder<T> implements ListNodeBuilder<T, LeafSetEntryNode<T>> {
-
+    private static final int DEFAULT_CAPACITY = 4;
     private final Map<YangInstanceIdentifier.NodeWithValue, LeafSetEntryNode<T>> value;
     private YangInstanceIdentifier.NodeIdentifier nodeIdentifier;
 
     protected ImmutableLeafSetNodeBuilder() {
-        value = new HashMap<>();
+        value = new HashMap<>(DEFAULT_CAPACITY);
+    }
+
+    protected ImmutableLeafSetNodeBuilder(final int sizeHint) {
+        value = new HashMap<>(sizeHint * 4 / 3);
     }
 
     protected ImmutableLeafSetNodeBuilder(final ImmutableLeafSetNode<T> node) {
@@ -46,6 +48,10 @@ public class ImmutableLeafSetNodeBuilder<T> implements ListNodeBuilder<T, LeafSe
         return new ImmutableLeafSetNodeBuilder<>();
     }
 
+    public static <T> ListNodeBuilder<T, LeafSetEntryNode<T>> create(final int sizeHint) {
+        return new ImmutableLeafSetNodeBuilder<>(sizeHint);
+    }
+
     public static <T> ListNodeBuilder<T, LeafSetEntryNode<T>> create(final LeafSetNode<T> node) {
         if (!(node instanceof ImmutableLeafSetNode<?>)) {
             throw new UnsupportedOperationException(String.format("Cannot initialize from class %s", node.getClass()));
index 98028944ffe4146df5a67cf729f9ba2050a77d7a..95d9aa2b81a1945168c78e209dd570fde77ac644 100644 (file)
@@ -7,10 +7,11 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
 
+import com.google.common.base.Optional;
+import com.google.common.collect.Iterables;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-
 import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.util.MapAdaptor;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
@@ -22,17 +23,17 @@ import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNo
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedNode;
 
-import com.google.common.base.Optional;
-import com.google.common.collect.Iterables;
-
-public class ImmutableMapNodeBuilder
-        implements CollectionNodeBuilder<MapEntryNode, MapNode> {
-
+public class ImmutableMapNodeBuilder implements CollectionNodeBuilder<MapEntryNode, MapNode> {
+    private static final int DEFAULT_CAPACITY = 4;
     private final Map<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> value;
     private YangInstanceIdentifier.NodeIdentifier nodeIdentifier;
 
     protected ImmutableMapNodeBuilder() {
-        this.value = new HashMap<>();
+        this.value = new HashMap<>(DEFAULT_CAPACITY);
+    }
+
+    protected ImmutableMapNodeBuilder(final int sizeHint) {
+        this.value = new HashMap<>(DEFAULT_CAPACITY);
     }
 
     protected ImmutableMapNodeBuilder(final ImmutableMapNode node) {
@@ -44,6 +45,10 @@ public class ImmutableMapNodeBuilder
         return new ImmutableMapNodeBuilder();
     }
 
+    public static CollectionNodeBuilder<MapEntryNode, MapNode> create(final int sizeHint) {
+        return new ImmutableMapNodeBuilder(sizeHint);
+    }
+
     public static CollectionNodeBuilder<MapEntryNode, MapNode> create(final MapNode node) {
         if (!(node instanceof ImmutableMapNode)) {
             throw new UnsupportedOperationException(String.format("Cannot initialize from class %s", node.getClass()));
@@ -113,10 +118,10 @@ public class ImmutableMapNodeBuilder
             return Optional.fromNullable(children.get(child));
         }
 
-               @Override
-               public Iterable<MapEntryNode> getValue() {
-                       return Iterables.unmodifiableIterable(children.values());
-               }
+        @Override
+        public Iterable<MapEntryNode> getValue() {
+            return Iterables.unmodifiableIterable(children.values());
+        }
 
         @Override
         protected int valueHashCode() {
index e7d68d992894f7a87b39039b12cf58545f847723..523ad51817a5b27af9ffa6865f33a0c9d17074da 100644 (file)
@@ -9,6 +9,9 @@ package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
 
 import com.google.common.base.Optional;
 import com.google.common.collect.Iterables;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
 import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
@@ -20,19 +23,19 @@ import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNo
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedNode;
 
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-
-public class ImmutableOrderedMapNodeBuilder
-        implements CollectionNodeBuilder<MapEntryNode, OrderedMapNode> {
-
+public class ImmutableOrderedMapNodeBuilder implements CollectionNodeBuilder<MapEntryNode, OrderedMapNode> {
+    private static final int DEFAULT_CAPACITY = 4;
     private Map<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> value;
     private YangInstanceIdentifier.NodeIdentifier nodeIdentifier;
-    private boolean dirty = false;
+    private boolean dirty;
 
     protected ImmutableOrderedMapNodeBuilder() {
-        this.value = new LinkedHashMap<>();
+        this.value = new LinkedHashMap<>(DEFAULT_CAPACITY);
+        this.dirty = false;
+    }
+
+    protected ImmutableOrderedMapNodeBuilder(final int sizeHint) {
+        this.value = new LinkedHashMap<>(DEFAULT_CAPACITY);
         this.dirty = false;
     }
 
@@ -46,6 +49,10 @@ public class ImmutableOrderedMapNodeBuilder
         return new ImmutableOrderedMapNodeBuilder();
     }
 
+    public static CollectionNodeBuilder<MapEntryNode, OrderedMapNode> create(final int sizeHint) {
+        return new ImmutableOrderedMapNodeBuilder(sizeHint);
+    }
+
     public static CollectionNodeBuilder<MapEntryNode, OrderedMapNode> create(final MapNode node) {
         if (!(node instanceof ImmutableOrderedMapNode)) {
             throw new UnsupportedOperationException(String.format("Cannot initialize from class %s", node.getClass()));
@@ -145,9 +152,9 @@ public class ImmutableOrderedMapNodeBuilder
             return children.size();
         }
 
-               @Override
-               public Iterable<MapEntryNode> getValue() {
-                       return Iterables.unmodifiableIterable(children.values());
-               }
+        @Override
+        public Iterable<MapEntryNode> getValue() {
+            return Iterables.unmodifiableIterable(children.values());
+        }
     }
 }
index 25d6dab768bd54b2143507c076216710079f882d..7787f3f18f2536f3f3949b142f179d49cedafcef 100644 (file)
@@ -17,8 +17,6 @@ import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNo
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.valid.DataValidationException;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 
-import com.google.common.base.Preconditions;
-
 public class ImmutableOrderedMapNodeSchemaAwareBuilder extends ImmutableOrderedMapNodeBuilder {
 
     private final ListSchemaNode schema;
index 66f81cadff5f75bc1b23cc9cbf915395830fda13..9eab2ba09816bd45d76faca4344d4b06273767f8 100644 (file)
@@ -7,9 +7,11 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
 
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import java.util.Collections;
 import java.util.LinkedList;
 import java.util.List;
-
 import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
@@ -21,14 +23,10 @@ import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNo
 import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedValueNode;
 
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-
 public class ImmutableUnkeyedListNodeBuilder implements CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode> {
-
     private List<UnkeyedListEntryNode> value;
     private YangInstanceIdentifier.NodeIdentifier nodeIdentifier;
-    private boolean dirty = false;
+    private boolean dirty;
 
     protected ImmutableUnkeyedListNodeBuilder() {
         this.value = new LinkedList<>();
@@ -46,6 +44,10 @@ public class ImmutableUnkeyedListNodeBuilder implements CollectionNodeBuilder<Un
         return new ImmutableUnkeyedListNodeBuilder();
     }
 
+    public static CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode> create(final int sizeHint) {
+        return new ImmutableUnkeyedListNodeBuilder();
+    }
+
     public static CollectionNodeBuilder<UnkeyedListEntryNode, UnkeyedListNode> create(final UnkeyedListNode node) {
         if (!(node instanceof ImmutableUnkeyedListNode)) {
             throw new UnsupportedOperationException(String.format("Cannot initialize from class %s", node.getClass()));
@@ -95,7 +97,11 @@ public class ImmutableUnkeyedListNodeBuilder implements CollectionNodeBuilder<Un
     @Override
     public UnkeyedListNode build() {
         dirty = true;
-        return new ImmutableUnkeyedListNode(nodeIdentifier, ImmutableList.copyOf(value));
+        if (value.isEmpty()) {
+            return new EmptyImmutableUnkeyedListNode(nodeIdentifier);
+        } else {
+            return new ImmutableUnkeyedListNode(nodeIdentifier, ImmutableList.copyOf(value));
+        }
     }
 
     @Override
@@ -109,6 +115,37 @@ public class ImmutableUnkeyedListNodeBuilder implements CollectionNodeBuilder<Un
         return withoutChild(key);
     }
 
+    protected static final class EmptyImmutableUnkeyedListNode extends AbstractImmutableNormalizedNode<YangInstanceIdentifier.NodeIdentifier, Iterable<UnkeyedListEntryNode>> implements Immutable, UnkeyedListNode {
+        protected EmptyImmutableUnkeyedListNode(final NodeIdentifier nodeIdentifier) {
+            super(nodeIdentifier);
+        }
+
+        @Override
+        public Iterable<UnkeyedListEntryNode> getValue() {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public UnkeyedListEntryNode getChild(final int position) {
+            return null;
+        }
+
+        @Override
+        public int getSize() {
+            return 0;
+        }
+
+        @Override
+        protected boolean valueEquals(final AbstractImmutableNormalizedNode<?, ?> other) {
+            return Collections.EMPTY_LIST.equals(other.getValue());
+        }
+
+        @Override
+        protected int valueHashCode() {
+            return Collections.EMPTY_LIST.hashCode();
+        }
+    }
+
     protected static final class ImmutableUnkeyedListNode extends
             AbstractImmutableNormalizedValueNode<YangInstanceIdentifier.NodeIdentifier, Iterable<UnkeyedListEntryNode>>
             implements Immutable, UnkeyedListNode {
index 01bfe32b2811d9afaf93040f6c8c112af899bdf7..b6ac22617abcb44feb63367c750a764c5ef9a23c 100644 (file)
@@ -8,49 +8,20 @@
 package org.opendaylight.yangtools.yang.data.impl.schema.nodes;
 
 import com.google.common.base.Optional;
-
-import java.util.Collections;
 import java.util.Map;
-
 import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
 import org.opendaylight.yangtools.yang.data.api.schema.DataContainerNode;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 public abstract class AbstractImmutableDataContainerNode<K extends PathArgument> extends AbstractImmutableNormalizedNode<K, Iterable<DataContainerChild<? extends PathArgument, ?>>> implements Immutable, DataContainerNode<K> {
-    private static final Logger LOG = LoggerFactory.getLogger(AbstractImmutableDataContainerNode.class);
     private final Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> children;
 
     public AbstractImmutableDataContainerNode(
             final Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> children, final K nodeIdentifier) {
         super(nodeIdentifier);
 
-        /*
-         * There is a code path where AbstractImmutableDataContainerNodeBuilder can reflect
-         * the collection acquired via getChildren() back to us. This is typically the case
-         * in the datastore where transactions cancel each other out, leaving an unmodified
-         * node. In that case we want to skip wrapping the map again (and again and again).
-         *
-         * In a perfect world, Collection.unmodifiableMap() would be doing the instanceof
-         * check which would stop the proliferation. Unfortunately this not the case and the
-         * 'unmodifiable' trait is not exposed by anything we can query. Furthermore the API
-         * contract there is sufficiently vague so an implementation may actually return a
-         * different implementation based on input map -- for example
-         * Collections.unmodifiableMap(Collections.emptyMap()) returning the same thing as
-         * Collections.emptyMap().
-         *
-         * This means that we have to perform the instantiation here (as opposed to once at
-         * class load time) and then compare the classes.
-         */
-        final Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> pub = Collections.unmodifiableMap(children);
-        if (children.getClass().equals(pub.getClass())) {
-            LOG.trace("Reusing already-unmodifiable children {}", children);
-            this.children = children;
-        } else {
-            this.children = pub;
-        }
+        this.children = UnmodifiableChildrenMap.create(children);
     }
 
     @Override
@@ -68,6 +39,15 @@ public abstract class AbstractImmutableDataContainerNode<K extends PathArgument>
         return children.hashCode();
     }
 
+    /**
+     * DO NOT USE THIS METHOD.
+     *
+     * This is an implementation-internal API and no outside users should use it. If you do,
+     * you are asking for trouble, as the returned object is not guaranteed to conform to
+     * java.util.Map interface.
+     *
+     * @return An unmodifiable view if this node's children.
+     */
     public final Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> getChildren() {
         return children;
     }
index e90db03c6440ae77cee001360d6586335f0c2a2a..52eb7650f12ac363ff5027a5fe29e4a3e88805b1 100644 (file)
@@ -10,7 +10,10 @@ package org.opendaylight.yangtools.yang.data.impl.schema.nodes;
 import com.google.common.base.Objects;
 import com.google.common.base.Objects.ToStringHelper;
 import com.google.common.collect.ImmutableMap;
+
+import java.util.Arrays;
 import java.util.Map;
+
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.AttributesContainer;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
@@ -53,17 +56,20 @@ public abstract class AbstractImmutableNormalizedValueAttrNode<K extends YangIns
 
     @Override
     protected boolean valueEquals(final AbstractImmutableNormalizedNode<?, ?> other) {
-        // We can not call directly getValue.equals because of Empty Type Definition leaves
-        // which allways have NULL value
-        if (!Objects.equal(getValue(), other.getValue())) {
+        // We can not call directly getValue.equals because of Empty Type
+        // Definition leaves which allways have NULL value
+
+        if (!java.util.Objects.deepEquals(getValue(), other.getValue())) {
             return false;
         }
 
-// FIXME: are attributes part of hashCode/equals?
-//        final Set<Entry<QName, String>> tas = getAttributes().entrySet();
-//        final Set<Entry<QName, String>> oas = container.getAttributes().entrySet();
-//
-//        return tas.containsAll(oas) && oas.containsAll(tas);
+        // FIXME: are attributes part of hashCode/equals?
+        // final Set<Entry<QName, String>> tas = getAttributes().entrySet();
+        // final Set<Entry<QName, String>> oas =
+        // container.getAttributes().entrySet();
+        //
+        // return tas.containsAll(oas) && oas.containsAll(tas);
         return true;
     }
+
 }
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/UnmodifiableChildrenMap.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/UnmodifiableChildrenMap.java
new file mode 100644 (file)
index 0000000..98598aa
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * 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.yang.data.impl.schema.nodes;
+
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableMap;
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.data.api.schema.DataContainerChild;
+
+/**
+ * Internal equivalent of {@link Collections}' unmodifiable Map. It does not retain
+ * keySet/entrySet references, thus lowering the memory overhead.
+ */
+final class UnmodifiableChildrenMap implements Map<PathArgument, DataContainerChild<? extends PathArgument, ?>>, Serializable {
+    private static final long serialVersionUID = 1L;
+    private final Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> delegate;
+    private transient Collection<DataContainerChild<? extends PathArgument, ?>> values;
+
+    private UnmodifiableChildrenMap(final Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> delegate) {
+        this.delegate = Preconditions.checkNotNull(delegate);
+    }
+
+    /**
+     * Create an unmodifiable view of a particular map. Does not perform unnecessary
+     * encapsulation if the map is known to be already unmodifiable.
+     *
+     * @param map Backing map
+     * @return Unmodifiable view
+     */
+    static Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> create(final Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> map) {
+        if (map instanceof UnmodifiableChildrenMap) {
+            return map;
+        }
+        if (map instanceof ImmutableMap) {
+            return map;
+        }
+        if (map.isEmpty()) {
+            return Collections.emptyMap();
+        }
+
+        return new UnmodifiableChildrenMap(map);
+    }
+
+    @Override
+    public int size() {
+        return delegate.size();
+    }
+
+    @Override
+    public boolean isEmpty() {
+        return delegate.isEmpty();
+    }
+
+    @Override
+    public boolean containsKey(final Object key) {
+        return delegate.containsKey(key);
+    }
+
+    @Override
+    public boolean containsValue(final Object value) {
+        return delegate.containsValue(value);
+    }
+
+    @Override
+    public DataContainerChild<? extends PathArgument, ?> get(final Object key) {
+        return delegate.get(key);
+    }
+
+    @Override
+    public DataContainerChild<? extends PathArgument, ?> put(final PathArgument key,
+            final DataContainerChild<? extends PathArgument, ?> value) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public DataContainerChild<? extends PathArgument, ?> remove(final Object key) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void putAll(final Map<? extends PathArgument, ? extends DataContainerChild<? extends PathArgument, ?>> m) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void clear() {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public Set<PathArgument> keySet() {
+        return Collections.unmodifiableSet(delegate.keySet());
+    }
+
+    @Override
+    public Collection<DataContainerChild<? extends PathArgument, ?>> values() {
+        if (values == null) {
+            values = Collections.unmodifiableCollection(delegate.values());
+        }
+        return values;
+    }
+
+    @Override
+    public Set<Entry<PathArgument, DataContainerChild<? extends PathArgument, ?>>> entrySet() {
+        /*
+         * Okay, this is not as efficient as it could be -- we could save ourselves the
+         * map instantiation. The cost of that would be re-implementation of a read-only
+         * Map.Entry to ensure our delegate is never modified.
+         *
+         * Let's skip that and use whatever the JRE gives us instead.
+         */
+        return Collections.unmodifiableMap(delegate).entrySet();
+    }
+
+    @Override
+    public boolean equals(final Object o) {
+        return this == o || delegate.equals(o);
+    }
+
+    @Override
+    public int hashCode() {
+        return delegate.hashCode();
+    }
+
+    @Override
+    public String toString() {
+        return delegate.toString();
+    }
+}
index 7ca902092c6bd9d852b0006fb5aee9ad458a531b..52aa03eed2be09bd1d526d5f13e56980b0481a12 100644 (file)
@@ -7,9 +7,11 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.tree;
 
+import static com.google.common.base.Preconditions.checkArgument;
 import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.Iterables;
+import java.util.Map;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
 import org.opendaylight.yangtools.yang.data.api.schema.MapNode;
@@ -18,7 +20,6 @@ import org.opendaylight.yangtools.yang.data.api.schema.NormalizedNodeContainer;
 import org.opendaylight.yangtools.yang.data.api.schema.OrderedLeafSetNode;
 import org.opendaylight.yangtools.yang.data.api.schema.OrderedMapNode;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.DataValidationFailedException;
-import org.opendaylight.yangtools.yang.data.api.schema.tree.ModificationType;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.ModifiedNodeDoesNotExistException;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.MutableTreeNode;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.spi.TreeNode;
@@ -37,10 +38,6 @@ import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 
-import java.util.Map;
-
-import static com.google.common.base.Preconditions.checkArgument;
-
 abstract class NormalizedNodeContainerModificationStrategy extends SchemaAwareApplyOperation {
 
     private final Class<? extends NormalizedNode<?, ?>> nodeClass;
index f51c0c63fdecc65c56a42634adbb6a079b25988b..491594d1c4649c7370f74b5be036fb1bb60a14e6 100644 (file)
@@ -12,11 +12,9 @@ import com.google.common.base.Preconditions;
 import com.google.common.base.Predicate;
 import com.google.common.base.Predicates;
 import com.google.common.collect.Iterables;
-
 import java.util.AbstractMap.SimpleEntry;
 import java.util.Iterator;
 import java.util.Map;
-
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
 import org.opendaylight.yangtools.yang.data.api.schema.tree.StoreTreeNode;
@@ -85,7 +83,7 @@ public final class TreeNodeUtils {
             nesting++;
         }
         if(current.isPresent()) {
-            final YangInstanceIdentifier currentPath = YangInstanceIdentifier.create(path.getPath().subList(0, nesting));
+            final YangInstanceIdentifier currentPath = YangInstanceIdentifier.create(Iterables.limit(path.getPathArguments(), nesting));
             return new SimpleEntry<YangInstanceIdentifier,T>(currentPath,current.get());
         }
 
@@ -96,8 +94,7 @@ public final class TreeNodeUtils {
          * present. At any rate we check state just to be on the safe side.
          */
         Preconditions.checkState(nesting > 0);
-        final YangInstanceIdentifier parentPath = YangInstanceIdentifier.create(path.getPath().subList(0, nesting - 1));
-
+        final YangInstanceIdentifier parentPath = YangInstanceIdentifier.create(Iterables.limit(path.getPathArguments(), nesting - 1));
         return new SimpleEntry<YangInstanceIdentifier,T>(parentPath,parent.get());
     }
 
index 6832748bdaf49656883a864a016b7b60d670e1f2..c4787d5ba2dc4cad26a01e3695da3861e8502d38 100644 (file)
@@ -9,33 +9,40 @@
 package org.opendaylight.yangtools.yang.data.impl.codec.xml;
 
 import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
 import com.google.common.base.Optional;
-import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
-
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.net.URI;
+import java.net.URISyntaxException;
 import java.util.AbstractMap;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Map;
-
 import javax.xml.stream.XMLOutputFactory;
 import javax.xml.stream.XMLStreamWriter;
-
 import org.custommonkey.xmlunit.Diff;
 import org.custommonkey.xmlunit.XMLUnit;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.data.api.Node;
-import org.opendaylight.yangtools.yang.data.api.SimpleNode;
 import org.opendaylight.yangtools.yang.data.impl.ImmutableCompositeNode;
-import org.opendaylight.yangtools.yang.data.impl.NodeFactory;
-import org.opendaylight.yangtools.yang.data.impl.SimpleNodeTOImpl;
+import org.opendaylight.yangtools.yang.model.api.DataNodeContainer;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
+import org.opendaylight.yangtools.yang.model.util.InstanceIdentifierType;
+import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
+import org.opendaylight.yangtools.yang.model.util.StringType;
 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
 import org.w3c.dom.Document;
 
@@ -43,6 +50,21 @@ public class XmlStreamUtilsTest {
 
     public static final XMLOutputFactory XML_OUTPUT_FACTORY = XMLOutputFactory.newFactory();
 
+    private static SchemaContext schemaContext;
+    private static Module leafRefModule;
+
+    @BeforeClass
+    public static void initialize() throws URISyntaxException {
+        final YangParserImpl yangParser = new YangParserImpl();
+        final File file = new File(XmlStreamUtils.class.getResource("/leafref-test.yang").toURI());
+        schemaContext = yangParser.parseFiles(Arrays.asList(file));
+        assertNotNull(schemaContext);
+        assertEquals(1,schemaContext.getModules().size());
+        leafRefModule = schemaContext.getModules().iterator().next();
+        assertNotNull(leafRefModule);
+    }
+
+
     @Test
     public void testWriteAttribute() throws Exception {
         final ByteArrayOutputStream out = new ByteArrayOutputStream();
@@ -80,6 +102,50 @@ public class XmlStreamUtilsTest {
         assertTrue("Xml differs: " + diff.toString(), identical);
     }
 
+    /**
+     * One leafref reference to other leafref via relative references
+     */
+    @Test
+    public void testLeafRefRelativeChaining() {
+        getTargetNodeForLeafRef("leafname3",StringType.class);
+    }
+
+    @Test
+    public void testLeafRefRelative() {
+        getTargetNodeForLeafRef("pointToStringLeaf",StringType.class);
+    }
+
+    @Test
+    public void testLeafRefAbsoluteWithSameTarget() {
+        getTargetNodeForLeafRef("absname",InstanceIdentifierType.class);
+    }
+
+    /**
+     * Tests relative path with double point inside path (e. g. "../../lf:interface/../lf:cont2/lf:stringleaf")
+     */
+    @Ignore //ignored because this isn't implemented
+    @Test
+    public void testLeafRefWithDoublePointInPath() {
+        getTargetNodeForLeafRef("lf-with-double-point-inside",StringType.class);
+    }
+
+    @Test
+    public void testLeafRefRelativeAndAbsoluteWithSameTarget() {
+        final TypeDefinition<?> targetNodeForAbsname = getTargetNodeForLeafRef("absname",InstanceIdentifierType.class);
+        final TypeDefinition<?> targetNodeForRelname = getTargetNodeForLeafRef("relname",InstanceIdentifierType.class);
+        assertEquals(targetNodeForAbsname, targetNodeForRelname);
+    }
+
+    private TypeDefinition<?> getTargetNodeForLeafRef(final String nodeName, final Class<?> clas) {
+        final LeafSchemaNode schemaNode = findSchemaNodeWithLeafrefType(leafRefModule, nodeName);
+        assertNotNull(schemaNode);
+        final LeafrefTypeDefinition leafrefTypedef = findLeafrefType(schemaNode);
+        assertNotNull(leafrefTypedef);
+        final TypeDefinition<?> targetBaseType = SchemaContextUtil.getBaseTypeForLeafRef(leafrefTypedef, schemaContext, schemaNode);
+        assertEquals("Wrong class found.", clas, targetBaseType.getClass());
+        return targetBaseType;
+    }
+
     @Test
     public void testEmptyNodeWithAttribute() throws Exception {
         final ByteArrayOutputStream out = new ByteArrayOutputStream();
@@ -126,4 +192,29 @@ public class XmlStreamUtilsTest {
             return QName.create(namespace, revision, localName);
         }
     }
-}
+
+    private LeafSchemaNode findSchemaNodeWithLeafrefType(final DataNodeContainer module, final String nodeName) {
+        for (final DataSchemaNode childNode : module.getChildNodes()) {
+            if (childNode instanceof DataNodeContainer) {
+                LeafSchemaNode leafrefFromRecursion = findSchemaNodeWithLeafrefType((DataNodeContainer)childNode, nodeName);
+                if (leafrefFromRecursion != null) {
+                    return leafrefFromRecursion;
+                }
+            } else if (childNode.getQName().getLocalName().equals(nodeName) && childNode instanceof LeafSchemaNode) {
+                final TypeDefinition<?> leafSchemaNodeType = ((LeafSchemaNode)childNode).getType();
+                if (leafSchemaNodeType instanceof LeafrefTypeDefinition) {
+                    return (LeafSchemaNode)childNode;
+                }
+            }
+        }
+        return null;
+    }
+
+    private LeafrefTypeDefinition findLeafrefType(final LeafSchemaNode schemaNode) {
+        final TypeDefinition<?> type = schemaNode.getType();
+        if (type instanceof LeafrefTypeDefinition) {
+            return (LeafrefTypeDefinition)type;
+        }
+        return null;
+    }
+}
\ No newline at end of file
diff --git a/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableNormalizedValueAttrNodeTest.java b/yang/yang-data-impl/src/test/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableNormalizedValueAttrNodeTest.java
new file mode 100644 (file)
index 0000000..778bf25
--- /dev/null
@@ -0,0 +1,329 @@
+/**
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.nodes;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+
+public class AbstractImmutableNormalizedValueAttrNodeTest {
+
+    private static QName ROOT_QNAME = QName.create("urn:test", "2014-03-13",
+            "root");
+    private static QName LEAF_QNAME = QName.create(ROOT_QNAME, "my-leaf");
+    private static QName SAME_LEAF_QNAME = QName.create(ROOT_QNAME, "my-leaf");
+    private static QName OTHER_LEAF_QNAME = QName.create(ROOT_QNAME,
+            "my-other-leaf");
+
+    @Test
+    public void equalsByteTest() {
+
+        byte[] valueNull = null;
+        byte[] equalValueNull = null;
+
+        LeafNode<byte[]> leafNodeNull = ImmutableNodes.leafNode(LEAF_QNAME,
+                valueNull);
+        LeafNode<byte[]> equalLeafNodeNull = ImmutableNodes.leafNode(
+                SAME_LEAF_QNAME, equalValueNull);
+
+        assertTrue(leafNodeNull.equals(leafNodeNull));
+        assertTrue(leafNodeNull.equals(equalLeafNodeNull));
+        assertTrue(equalLeafNodeNull.equals(leafNodeNull));
+
+        byte[] value = "test".getBytes();
+        byte[] equalValue = "test".getBytes();
+
+        LeafNode<byte[]> leafNode = ImmutableNodes.leafNode(LEAF_QNAME, value);
+        LeafNode<byte[]> equalLeafNode = ImmutableNodes.leafNode(
+                SAME_LEAF_QNAME, equalValue);
+
+        assertTrue(leafNode.equals(leafNode));
+        assertTrue(leafNode.equals(equalLeafNode));
+        assertTrue(equalLeafNode.equals(leafNode));
+
+        Byte[] value2 = new Byte[] { new Byte("1"), new Byte("2") };
+        Byte[] equalValue2 = new Byte[] { new Byte("1"), new Byte("2") };
+
+        LeafNode<Byte[]> leafNode2 = ImmutableNodes
+                .leafNode(LEAF_QNAME, value2);
+        LeafNode<Byte[]> equalLeafNode2 = ImmutableNodes.leafNode(
+                SAME_LEAF_QNAME, equalValue2);
+
+        assertTrue(leafNode2.equals(leafNode2));
+        assertTrue(leafNode2.equals(equalLeafNode2));
+        assertTrue(equalLeafNode2.equals(leafNode2));
+
+        byte[][] value3 = new byte[][] { "test".getBytes(), "test2".getBytes() };
+        byte[][] equalValue3 = new byte[][] { "test".getBytes(),
+                "test2".getBytes() };
+
+        LeafNode<byte[][]> leafNode3 = ImmutableNodes.leafNode(LEAF_QNAME,
+                value3);
+        LeafNode<byte[][]> equalLeafNode3 = ImmutableNodes.leafNode(
+                SAME_LEAF_QNAME, equalValue3);
+
+        assertTrue(leafNode3.equals(leafNode3));
+        assertTrue(leafNode3.equals(equalLeafNode3));
+        assertTrue(equalLeafNode3.equals(leafNode3));
+
+        Byte[][] value4 = new Byte[][] {
+                new Byte[] { new Byte("1"), new Byte("2") },
+                new Byte[] { new Byte("3"), new Byte("4") } };
+        Byte[][] equalValue4 = new Byte[][] {
+                new Byte[] { new Byte("1"), new Byte("2") },
+                new Byte[] { new Byte("3"), new Byte("4") } };
+
+        LeafNode<Byte[][]> leafNode4 = ImmutableNodes.leafNode(LEAF_QNAME,
+                value4);
+        LeafNode<Byte[][]> equalLeafNode4 = ImmutableNodes.leafNode(
+                SAME_LEAF_QNAME, equalValue4);
+
+        assertTrue(leafNode4.equals(leafNode4));
+        assertTrue(leafNode4.equals(equalLeafNode4));
+        assertTrue(equalLeafNode4.equals(leafNode4));
+
+        Byte value6 = new Byte("1");
+        Byte equalValue6 = new Byte("1");
+
+        LeafNode<Byte> leafNode6 = ImmutableNodes.leafNode(LEAF_QNAME, value6);
+        LeafNode<Byte> equalLeafNode6 = ImmutableNodes.leafNode(
+                SAME_LEAF_QNAME, equalValue6);
+
+        assertTrue(leafNode6.equals(leafNode6));
+        assertTrue(leafNode6.equals(equalLeafNode6));
+        assertTrue(equalLeafNode6.equals(leafNode6));
+
+        String value5 = new String("test");
+        String equalValue5 = new String("test");
+
+        LeafNode<String> leafNode5 = ImmutableNodes
+                .leafNode(LEAF_QNAME, value5);
+        LeafNode<String> equalLeafNode5 = ImmutableNodes.leafNode(
+                SAME_LEAF_QNAME, equalValue5);
+
+        assertTrue(leafNode5.equals(leafNode5));
+        assertTrue(leafNode5.equals(equalLeafNode5));
+        assertTrue(equalLeafNode5.equals(leafNode5));
+
+    }
+
+    @Test
+    public void notEqualByteTest() {
+
+        byte[] value = "test".getBytes();
+        byte[] equalValue = "test".getBytes();
+
+        LeafNode<byte[]> leafNode = ImmutableNodes.leafNode(LEAF_QNAME, value);
+        LeafNode<byte[]> otherLeafNode = ImmutableNodes.leafNode(
+                OTHER_LEAF_QNAME, equalValue);
+
+        assertFalse(leafNode.equals(null));
+        assertFalse(leafNode.equals(new Object()));
+        assertFalse(leafNode.equals(otherLeafNode));
+        assertFalse(otherLeafNode.equals(leafNode));
+
+        byte[] value1 = "test".getBytes();
+        byte[] otherValue1 = "test1".getBytes();
+
+        LeafNode<byte[]> leafNode1 = ImmutableNodes
+                .leafNode(LEAF_QNAME, value1);
+        LeafNode<byte[]> otherLeafNode1 = ImmutableNodes.leafNode(
+                SAME_LEAF_QNAME, otherValue1);
+
+        assertFalse(leafNode1.equals(otherLeafNode1));
+        assertFalse(otherLeafNode1.equals(leafNode1));
+
+        Byte[] value2 = new Byte[] { new Byte("1"), new Byte("1") };
+        Byte[] otherValue2 = new Byte[] { new Byte("1"), new Byte("2") };
+
+        LeafNode<Byte[]> leafNode2 = ImmutableNodes
+                .leafNode(LEAF_QNAME, value2);
+        LeafNode<Byte[]> otherLeafNode2 = ImmutableNodes.leafNode(
+                SAME_LEAF_QNAME, otherValue2);
+
+        assertFalse(leafNode2.equals(otherLeafNode2));
+        assertFalse(otherLeafNode2.equals(leafNode2));
+
+        byte[][] value3 = new byte[][] { "test".getBytes(), "test2".getBytes() };
+        byte[][] otherValue3 = new byte[][] { "test".getBytes(),
+                "test3".getBytes() };
+
+        LeafNode<byte[][]> leafNode3 = ImmutableNodes.leafNode(LEAF_QNAME,
+                value3);
+        LeafNode<byte[][]> otherLeafNode3 = ImmutableNodes.leafNode(
+                SAME_LEAF_QNAME, otherValue3);
+
+        assertFalse(leafNode3.equals(otherLeafNode3));
+        assertFalse(otherLeafNode3.equals(leafNode3));
+
+        Byte[][] value4 = new Byte[][] {
+                new Byte[] { new Byte("1"), new Byte("2") },
+                new Byte[] { new Byte("3"), new Byte("4") } };
+        Byte[][] otherValue4 = new Byte[][] {
+                new Byte[] { new Byte("1"), new Byte("2") },
+                new Byte[] { new Byte("3"), new Byte("5") } };
+
+        LeafNode<Byte[][]> leafNode4 = ImmutableNodes.leafNode(LEAF_QNAME,
+                value4);
+        LeafNode<Byte[][]> otherLeafNode4 = ImmutableNodes.leafNode(
+                SAME_LEAF_QNAME, otherValue4);
+
+        assertFalse(leafNode4.equals(otherLeafNode4));
+        assertFalse(otherLeafNode4.equals(leafNode4));
+
+        Byte value6 = new Byte("1");
+        Byte otherValue6 = new Byte("2");
+
+        LeafNode<Byte> leafNode6 = ImmutableNodes.leafNode(LEAF_QNAME, value6);
+        LeafNode<Byte> otherLeafNode6 = ImmutableNodes.leafNode(
+                SAME_LEAF_QNAME, otherValue6);
+
+        assertFalse(leafNode6.equals(otherLeafNode6));
+        assertFalse(otherLeafNode6.equals(leafNode6));
+
+        String value5 = new String("test");
+        String otherValue5 = new String("test2");
+
+        LeafNode<String> leafNode5 = ImmutableNodes
+                .leafNode(LEAF_QNAME, value5);
+        LeafNode<String> otherLeafNode5 = ImmutableNodes.leafNode(
+                SAME_LEAF_QNAME, otherValue5);
+
+        assertFalse(leafNode5.equals(otherLeafNode5));
+        assertFalse(otherLeafNode5.equals(leafNode5));
+        assertFalse(leafNode5.equals(leafNode));
+        assertFalse(leafNode5.equals(leafNode1));
+        assertFalse(leafNode5.equals(leafNode2));
+        assertFalse(leafNode5.equals(leafNode3));
+        assertFalse(leafNode5.equals(leafNode4));
+        assertFalse(leafNode5.equals(leafNode6));
+        assertFalse(leafNode.equals(leafNode5));
+        assertFalse(leafNode1.equals(leafNode5));
+        assertFalse(leafNode2.equals(leafNode5));
+        assertFalse(leafNode3.equals(leafNode5));
+        assertFalse(leafNode4.equals(leafNode5));
+        assertFalse(leafNode6.equals(leafNode5));
+
+        byte[] valueNull = null;
+
+        LeafNode<byte[]> leafNodeNull = ImmutableNodes.leafNode(
+                SAME_LEAF_QNAME, valueNull);
+        assertFalse(leafNodeNull.equals(leafNode));
+        assertFalse(leafNode.equals(leafNodeNull));
+
+        byte[] byteValue = new byte[] { new Byte("1").byteValue(),
+                new Byte("1").byteValue() };
+
+        LeafNode<byte[]> byteLeafNode = ImmutableNodes.leafNode(
+                SAME_LEAF_QNAME, byteValue);
+        assertFalse(byteLeafNode.equals(leafNode2));
+        assertFalse(leafNode2.equals(byteLeafNode));
+
+    }
+
+    @Test
+    public void equalsOtherTypesTest() {
+
+        char[] valueChar = "test".toCharArray();
+        char[] equalValueChar = "test".toCharArray();
+
+        LeafNode<char[]> leafNodeChar = ImmutableNodes.leafNode(LEAF_QNAME,
+                valueChar);
+        LeafNode<char[]> equalLeafNodeChar = ImmutableNodes.leafNode(
+                SAME_LEAF_QNAME, equalValueChar);
+
+        assertTrue(leafNodeChar.equals(leafNodeChar));
+        assertTrue(leafNodeChar.equals(equalLeafNodeChar));
+        assertTrue(equalLeafNodeChar.equals(leafNodeChar));
+
+        boolean[] value = new boolean[] { true, false };
+        boolean[] equalValue = new boolean[] { true, false };
+
+        LeafNode<boolean[]> leafNode = ImmutableNodes.leafNode(LEAF_QNAME,
+                value);
+        LeafNode<boolean[]> equalLeafNode = ImmutableNodes.leafNode(
+                SAME_LEAF_QNAME, equalValue);
+
+        assertTrue(leafNode.equals(leafNode));
+        assertTrue(leafNode.equals(equalLeafNode));
+        assertTrue(equalLeafNode.equals(leafNode));
+
+        int[] value2 = new int[] { 1, 2 };
+        int[] equalValue2 = new int[] { 1, 2 };
+
+        LeafNode<int[]> leafNode2 = ImmutableNodes.leafNode(LEAF_QNAME, value2);
+        LeafNode<int[]> equalLeafNode2 = ImmutableNodes.leafNode(
+                SAME_LEAF_QNAME, equalValue2);
+
+        assertTrue(leafNode2.equals(leafNode2));
+        assertTrue(leafNode2.equals(equalLeafNode2));
+        assertTrue(equalLeafNode2.equals(leafNode2));
+
+        short[] value3 = new short[] { 1, 2 };
+        short[] equalValue3 = new short[] { 1, 2 };
+
+        LeafNode<short[]> leafNode3 = ImmutableNodes.leafNode(LEAF_QNAME,
+                value3);
+        LeafNode<short[]> equalLeafNode3 = ImmutableNodes.leafNode(
+                SAME_LEAF_QNAME, equalValue3);
+
+        assertTrue(leafNode3.equals(leafNode3));
+        assertTrue(leafNode3.equals(equalLeafNode3));
+        assertTrue(equalLeafNode3.equals(leafNode3));
+
+        long[] value4 = new long[] { 1, 2 };
+        long[] equalValue4 = new long[] { 1, 2 };
+
+        LeafNode<long[]> leafNode4 = ImmutableNodes
+                .leafNode(LEAF_QNAME, value4);
+        LeafNode<long[]> equalLeafNode4 = ImmutableNodes.leafNode(
+                SAME_LEAF_QNAME, equalValue4);
+
+        assertTrue(leafNode4.equals(leafNode4));
+        assertTrue(leafNode4.equals(equalLeafNode4));
+        assertTrue(equalLeafNode4.equals(leafNode4));
+
+        double[] value6 = new double[] { 1, 2 };
+        double[] equalValue6 = new double[] { 1, 2 };
+
+        LeafNode<double[]> leafNode6 = ImmutableNodes.leafNode(LEAF_QNAME,
+                value6);
+        LeafNode<double[]> equalLeafNode6 = ImmutableNodes.leafNode(
+                SAME_LEAF_QNAME, equalValue6);
+
+        assertTrue(leafNode6.equals(leafNode6));
+        assertTrue(leafNode6.equals(equalLeafNode6));
+        assertTrue(equalLeafNode6.equals(leafNode6));
+
+        float[] value5 = new float[] { 1, 2 };
+        float[] equalValue5 = new float[] { 1, 2 };
+
+        LeafNode<float[]> leafNode5 = ImmutableNodes.leafNode(LEAF_QNAME,
+                value5);
+        LeafNode<float[]> equalLeafNode5 = ImmutableNodes.leafNode(
+                SAME_LEAF_QNAME, equalValue5);
+
+        assertTrue(leafNode5.equals(leafNode5));
+        assertTrue(leafNode5.equals(equalLeafNode5));
+        assertTrue(equalLeafNode5.equals(leafNode5));
+
+        assertFalse(leafNode.equals(leafNode5));
+        assertFalse(leafNode2.equals(leafNode5));
+        assertFalse(leafNode3.equals(leafNode5));
+        assertFalse(leafNode4.equals(leafNode5));
+        assertFalse(leafNodeChar.equals(leafNode5));
+        assertFalse(leafNode6.equals(leafNode5));
+
+        assertFalse(leafNode5.equals(leafNode));
+        assertFalse(leafNode5.equals(leafNode2));
+        assertFalse(leafNode5.equals(leafNode3));
+        assertFalse(leafNode5.equals(leafNode4));
+        assertFalse(leafNode5.equals(leafNodeChar));
+        assertFalse(leafNode5.equals(leafNode6));
+    }
+
+}
diff --git a/yang/yang-data-impl/src/test/resources/leafref-test.yang b/yang/yang-data-impl/src/test/resources/leafref-test.yang
new file mode 100644 (file)
index 0000000..3d31c89
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * 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
+ */
+module leafref-test {
+    yang-version 1;
+    namespace "urn:opendaylight:yangtools:leafref:test";
+    prefix "lt";
+
+    revision 2014-11-04 {
+        description "Test deserialization value of leafref type.";
+    }
+
+    container interface {
+        leaf simpleValue {
+            type instance-identifier;
+        }
+    }
+
+    container cont2 {
+        container cont3 {
+            leaf leafname3 {
+                type leafref {
+                    path "../../pointToStringLeaf";
+                }
+            }
+        }
+        leaf pointToStringLeaf {
+            type leafref {
+                path "../stringleaf";
+            }
+        }
+        leaf stringleaf {
+            type string;
+        }
+        leaf absname {
+            type leafref {
+                path "/lt:interface/lt:simpleValue";
+            }
+        }
+        leaf relname {
+            type leafref {
+                path "../../lt:interface/lt:simpleValue";
+            }
+        }
+
+        leaf lf-with-double-point-inside {
+            type leafref {
+                path "../../lt:interface/../lt:cont2/lt:stringleaf";
+            }
+        }
+    }
+}
\ No newline at end of file
index bd518fd00e35c14fa17175daf7eda2a39f4527ad..e4674caaa95a42d705fca62080dfc561d6a3e6a2 100644 (file)
@@ -61,8 +61,9 @@ final class ChoiceNodeModification extends
             detectedCase = detectedCaseForChild.get();
         }
 
-        if (detectedCase == null)
+        if (detectedCase == null) {
             return childrenToProcess;
+        }
 
         // Filter out child nodes that do not belong to detected case =
         // Nodes from other cases present in actual
index 55327ea2a80811cbad6d8f4834fdb0a9e95168c5..e6235bb6b8c7321ca95644ea8f8ab63e23714a9e 100644 (file)
@@ -66,8 +66,9 @@ final class LeafSetNodeModification implements Modification<LeafListSchemaNode,
     }
 
     private Optional<LeafSetNode<?>> build(LeafListSchemaNode schemaNode, List<LeafSetEntryNode<?>> resultNodes) {
-        if(resultNodes.isEmpty())
+        if(resultNodes.isEmpty()) {
             return Optional.absent();
+        }
 
         ListNodeBuilder<Object, LeafSetEntryNode<Object>> b = Builders.leafSetBuilder(schemaNode);
         for (LeafSetEntryNode<?> resultNode : resultNodes) {
index 51996a8449e5c0f7a173820ed355992bb07a636e..41268b905e12985dbed6000d4ddb869dc3a0b8a2 100644 (file)
@@ -26,12 +26,14 @@ public class MapNodeModification implements Modification<ListSchemaNode, MapNode
                                     Optional<MapNode> modification, OperationStack operationStack) throws DataModificationException {
 
         // Merge or None operation on parent, leaving actual if modification not present
-        if (!modification.isPresent())
+        if (!modification.isPresent()) {
             return actual;
+        }
 
         Map<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> resultNodes = Maps.newLinkedHashMap();
-        if(actual.isPresent())
+        if(actual.isPresent()) {
             resultNodes.putAll(mapEntries(actual.get()));
+        }
 
         // TODO implement ordering for modification nodes
 
@@ -82,8 +84,9 @@ public class MapNodeModification implements Modification<ListSchemaNode, MapNode
     }
 
     private Optional<MapNode> build(ListSchemaNode schema, Map<YangInstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> resultNodes) {
-        if(resultNodes.isEmpty())
+        if(resultNodes.isEmpty()) {
             return Optional.absent();
+        }
 
         CollectionNodeBuilder<MapEntryNode, MapNode> b = Builders.mapBuilder(schema);
 
index 83a706133623d458c8c201373b415b8367f25fcc..132edfc347bdb7dd2405aefd755cfc832a118bd9 100644 (file)
@@ -11,6 +11,7 @@ import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Splitter;
 import com.google.common.collect.Iterables;
+import java.util.Arrays;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
@@ -21,6 +22,8 @@ import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
@@ -30,6 +33,8 @@ import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.model.api.SchemaNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -508,8 +513,7 @@ public final class SchemaContextUtil {
             Preconditions.checkArgument(module != null, "Failed to resolve xpath: no module found for prefix %s in module %s",
                     modulePrefix, parentModule.getName());
 
-            // FIXME: Module should have a QNameModule handle
-            return QName.create(module.getNamespace(), module.getRevision(), prefixedName.next());
+            return QName.create(module.getQNameModule(), prefixedName.next());
         } else {
             return QName.create(parentModule.getNamespace(), parentModule.getRevision(), prefixedPathPart);
         }
@@ -566,32 +570,43 @@ public final class SchemaContextUtil {
      *            Yang Module
      * @param relativeXPath
      *            Non conditional Revision Aware Relative XPath
-     * @param leafrefSchemaPath
-     *            Schema Path for Leafref
+     * @param actualSchemaNode
+     *            actual schema node
      * @return list of QName
      */
     private static Iterable<QName> resolveRelativeXPath(final SchemaContext context, final Module module,
-            final RevisionAwareXPath relativeXPath, final SchemaNode leafrefParentNode) {
+            final RevisionAwareXPath relativeXPath, final SchemaNode actualSchemaNode) {
         Preconditions.checkArgument(context != null, "Schema Context reference cannot be NULL");
         Preconditions.checkArgument(module != null, "Module reference cannot be NULL");
         Preconditions.checkArgument(relativeXPath != null, "Non Conditional Revision Aware XPath cannot be NULL");
         Preconditions.checkState(!relativeXPath.isAbsolute(),
                 "Revision Aware XPath MUST be relative i.e. MUST contains ../, "
                         + "for non relative Revision Aware XPath use findDataSchemaNode method");
-        Preconditions.checkState(leafrefParentNode.getPath() != null,
+        Preconditions.checkState(actualSchemaNode.getPath() != null,
                 "Schema Path reference for Leafref cannot be NULL");
 
         final Iterable<String> xpaths = SLASH_SPLITTER.split(relativeXPath.toString());
 
         // Find out how many "parent" components there are
         // FIXME: is .contains() the right check here?
+        // FIXME: case ../../node1/node2/../node3/../node4
         int colCount = 0;
         for (Iterator<String> it = xpaths.iterator(); it.hasNext() && it.next().contains(".."); ) {
             ++colCount;
         }
 
-        final Iterable<QName> parent = leafrefParentNode.getPath().getPathFromRoot();
-        return Iterables.concat(Iterables.limit(parent, Iterables.size(parent) - colCount),
+        final Iterable<QName> schemaNodePath = actualSchemaNode.getPath().getPathFromRoot();
+
+        if (Iterables.size(schemaNodePath) - colCount >= 0) {
+            return Iterables.concat(Iterables.limit(schemaNodePath, Iterables.size(schemaNodePath) - colCount),
+                    Iterables.transform(Iterables.skip(xpaths, colCount), new Function<String, QName>() {
+                        @Override
+                        public QName apply(final String input) {
+                            return stringPathPartToQName(context, module, input);
+                        }
+                    }));
+        }
+        return Iterables.concat(schemaNodePath,
                 Iterables.transform(Iterables.skip(xpaths, colCount), new Function<String, QName>() {
                     @Override
                     public QName apply(final String input) {
@@ -599,4 +614,104 @@ public final class SchemaContextUtil {
                     }
                 }));
     }
+
+    /**
+     * Extracts the base type of node on which schema node points to. If target node is again of type LeafrefTypeDefinition, methods will be call recursively until it reach concrete
+     * type definition.
+     *
+     * @param typeDefinition
+     *            type of node which will be extracted
+     * @param schemaContext
+     *            Schema Context
+     * @param schema
+     *            Schema Node
+     * @return recursively found type definition this leafref is pointing to or null if the xpath is incorrect (null is there to preserve backwards compatibility)
+     */
+    public static TypeDefinition<?> getBaseTypeForLeafRef(final LeafrefTypeDefinition typeDefinition, final SchemaContext schemaContext, final SchemaNode schema) {
+        RevisionAwareXPath pathStatement = typeDefinition.getPathStatement();
+        pathStatement = new RevisionAwareXPathImpl(stripConditionsFromXPathString(pathStatement), pathStatement.isAbsolute());
+
+        final Module parentModule = SchemaContextUtil.findParentModule(schemaContext, schema);
+
+        final DataSchemaNode dataSchemaNode;
+        if(pathStatement.isAbsolute()) {
+            dataSchemaNode = (DataSchemaNode) SchemaContextUtil.findDataSchemaNode(schemaContext, parentModule, pathStatement);
+        } else {
+            dataSchemaNode = (DataSchemaNode) SchemaContextUtil.findDataSchemaNodeForRelativeXPath(schemaContext, parentModule, schema, pathStatement);
+        }
+
+        // FIXME this is just to preserve backwards compatibility since yangtools do not mind wrong leafref xpaths
+        // and current expected behaviour for such cases is to just use pure string
+        // This should throw an exception about incorrect XPath in leafref
+        if(dataSchemaNode == null) {
+            return null;
+        }
+
+        final TypeDefinition<?> targetTypeDefinition = typeDefinition(dataSchemaNode);
+
+        if(targetTypeDefinition instanceof LeafrefTypeDefinition) {
+            return getBaseTypeForLeafRef(((LeafrefTypeDefinition) targetTypeDefinition), schemaContext, dataSchemaNode);
+        } else {
+            return targetTypeDefinition;
+        }
+    }
+
+    /**
+     * Removes conditions from xPath pointed to target node.
+     *
+     * @param pathStatement
+     *            xPath to target node
+     * @return string representation of xPath without conditions
+     *
+     */
+    private static String stripConditionsFromXPathString(final RevisionAwareXPath pathStatement) {
+        return pathStatement.toString().replaceAll("\\[.*\\]", "");
+    }
+
+    /**
+     * Extracts the base type of leaf schema node until it reach concrete type of TypeDefinition.
+     *
+     * @param node
+     *            a node representing LeafSchemaNode
+     * @return concrete type definition of node value
+     */
+    private static TypeDefinition<? extends Object> typeDefinition(final LeafSchemaNode node) {
+        TypeDefinition<?> baseType = node.getType();
+        while (baseType.getBaseType() != null) {
+            baseType = baseType.getBaseType();
+        }
+        return baseType;
+    }
+
+    /**
+     * Extracts the base type of leaf schema node until it reach concrete type of TypeDefinition.
+     *
+     * @param node
+     *            a node representing LeafListSchemaNode
+     * @return concrete type definition of node value
+     */
+    private static TypeDefinition<? extends Object> typeDefinition(final LeafListSchemaNode node) {
+        TypeDefinition<?> baseType = node.getType();
+        while (baseType.getBaseType() != null) {
+            baseType = baseType.getBaseType();
+        }
+        return baseType;
+    }
+
+    /**
+     * Gets the base type of DataSchemaNode value.
+     *
+     * @param node
+     *            a node representing DataSchemaNode
+     * @return concrete type definition of node value
+     */
+    private static TypeDefinition<? extends Object> typeDefinition(final DataSchemaNode node) {
+        if (node instanceof LeafListSchemaNode) {
+            return typeDefinition((LeafListSchemaNode) node);
+        } else if (node instanceof LeafSchemaNode) {
+            return typeDefinition((LeafSchemaNode) node);
+        } else {
+            throw new IllegalArgumentException("Unhandled parameter types: " + Arrays.<Object> asList(node).toString());
+        }
+    }
 }
index ac9358c72eb55494f9affb955ff918747f8126d8..48d75a0feec6ac8e1afa9962fe051b2fdb2c099a 100644 (file)
@@ -105,7 +105,9 @@ fragment HEX : [0-9a-fA-F] ;
           
 END_IDENTIFIER_SEMICOLON : ';' -> type(SEMICOLON),popMode;
 END_IDENTIFIER_LEFT_BRACE : '{' ->type(LEFT_BRACE), popMode;
+
+START_INNER_BLOCK_COMMENT : '/*' ->pushMode(BLOCK_COMMENT_MODE), skip ;
+
 fragment SUB_STRING : ('"' (ESC | ~["])*'"') | ('\'' (ESC | ~['])*'\'') ;
 
 STRING: ((~( '\r' | '\n' | '\t' | ' ' | ';' | '{' | '"' | '\'')~( '\r' | '\n' | '\t' | ' ' | ';' | '{' )* ) | SUB_STRING ) ->popMode;// IDENTIFIER ;
index 4e3649c44fc192d76e2c754b531c33beb611a17b..d99f774a9aa72f4668aefcd833f0a6cc0a45022a 100644 (file)
@@ -36,7 +36,7 @@ public final class ListSchemaNodeBuilder extends AbstractDocumentedDataNodeConta
         DataSchemaNodeBuilder, AugmentationTargetBuilder {
     private ListSchemaNodeImpl instance;
     private boolean userOrdered;
-    private List<String> keys;
+    private Set<String> keys;
     private List<QName> keyDefinition;
     // SchemaNode args
     private SchemaPath schemaPath;
@@ -155,11 +155,11 @@ public final class ListSchemaNodeBuilder extends AbstractDocumentedDataNodeConta
         return augmentationBuilders;
     }
 
-    public List<String> getKeys() {
+    public Set<String> getKeys() {
         return keys;
     }
 
-    public void setKeys(final List<String> keys) {
+    public void setKeys(final Set<String> keys) {
         this.keys = keys;
     }
 
index 493db98790228763756264aef69cc54f752c3dc2..eaece86cadde4c6b930228fd38c2d95cb55d85ff 100644 (file)
@@ -12,13 +12,14 @@ import static com.google.common.base.Preconditions.checkState;
 import com.google.common.base.CharMatcher;
 import com.google.common.base.Optional;
 import com.google.common.base.Splitter;
-import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Set;
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
 import org.antlr.v4.runtime.ParserRuleContext;
@@ -305,15 +306,15 @@ public final class ParserListenerUtils {
     }
 
     /**
-     * Create java.util.List of key node names.
+     * Create java.util.LinkedHashSet of key node names.
      *
      * @param ctx
      *            Key_stmtContext context
-     * @return YANG list key as java.util.List of key node names
+     * @return YANG list key as java.util.LinkedHashSet of key node names
      */
-    public static List<String> createListKey(final Key_stmtContext ctx) {
-        String keyDefinition = stringFromNode(ctx);
-        return Lists.newArrayList(KEYDEF_SPLITTER.split(keyDefinition));
+    public static Set<String> createListKey(final Key_stmtContext ctx) {
+        final String keyDefinition = stringFromNode(ctx);
+        return Sets.<String>newLinkedHashSet(KEYDEF_SPLITTER.split(keyDefinition));
     }
 
     /**
index fdaaf33d8865c085dec2ee0c34526962d7f67f14..e5127b3142f1082f47f4789ffaa7acae875bc4b4 100644 (file)
@@ -34,6 +34,7 @@ import java.util.Date;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.TreeMap;
 import org.antlr.v4.runtime.tree.ParseTree;
 import org.antlr.v4.runtime.tree.ParseTreeWalker;
@@ -216,7 +217,7 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
     public void enterBelongs_to_stmt(final YangParser.Belongs_to_stmtContext ctx) {
         final String belongsTo = stringFromNode(ctx);
         TreeMap<Date, URI> context = namespaceContext.get(belongsTo);
-        Map.Entry<Date, URI> entry = context.firstEntry();
+        final Map.Entry<Date, URI> entry = context.firstEntry();
         // TODO
         // Submodule will contain namespace and revision from module to which it
         // belongs. If there are multiple modules with same name and different
@@ -272,7 +273,7 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
     public void enterMeta_stmts(final YangParser.Meta_stmtsContext ctx) {
         enterLog("meta_stmt", "", ctx.getStart().getLine());
         for (int i = 0; i < ctx.getChildCount(); i++) {
-            ParseTree child = ctx.getChild(i);
+            final ParseTree child = ctx.getChild(i);
             if (child instanceof Organization_stmtContext) {
                 final String organization = stringFromNode(child);
                 moduleBuilder.setOrganization(organization);
@@ -373,9 +374,9 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
 
         Date includeRevision = null;
         for (int i = 0; i < ctx.getChildCount(); i++) {
-            ParseTree treeNode = ctx.getChild(i);
+            final ParseTree treeNode = ctx.getChild(i);
             if (treeNode instanceof Revision_date_stmtContext) {
-                String importRevisionStr = stringFromNode(treeNode);
+                final String importRevisionStr = stringFromNode(treeNode);
                 try {
                     includeRevision = SIMPLE_DATE_FORMAT.parse(importRevisionStr);
                 } catch (ParseException e) {
@@ -397,8 +398,8 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         enterLog(AUGMENT_STR, augmentPath, line);
         stack.push();
 
-        SchemaPath targetPath = parseXPathString(augmentPath, line);
-        AugmentationSchemaBuilder builder = moduleBuilder.addAugment(line, augmentPath, targetPath, augmentOrder++);
+        final SchemaPath targetPath = parseXPathString(augmentPath, line);
+        final AugmentationSchemaBuilder builder = moduleBuilder.addAugment(line, augmentPath, targetPath, augmentOrder++);
 
         for (int i = 0; i < ctx.getChildCount(); i++) {
             ParseTree child = ctx.getChild(i);
@@ -428,16 +429,16 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         final int line = ctx.getStart().getLine();
         final String extName = stringFromNode(ctx);
         enterLog("extension", extName, line);
-        QName qname = QName.create(moduleQName, extName);
-        SchemaPath path = stack.addNodeToPath(qname);
+        final QName qname = QName.create(moduleQName, extName);
+        final SchemaPath path = stack.addNodeToPath(qname);
 
-        ExtensionBuilder builder = moduleBuilder.addExtension(qname, line, path);
+        final ExtensionBuilder builder = moduleBuilder.addExtension(qname, line, path);
         parseSchemaNodeArgs(ctx, builder);
 
         String argument = null;
         boolean yin = false;
         for (int i = 0; i < ctx.getChildCount(); i++) {
-            ParseTree child = ctx.getChild(i);
+            final ParseTree child = ctx.getChild(i);
             if (child instanceof Argument_stmtContext) {
                 argument = stringFromNode(child);
                 yin = parseYinValue((Argument_stmtContext) child);
@@ -461,10 +462,10 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         final int line = ctx.getStart().getLine();
         final String typedefName = stringFromNode(ctx);
         enterLog("typedef", typedefName, line);
-        QName typedefQName = QName.create(moduleQName, typedefName);
-        SchemaPath path = stack.addNodeToPath(typedefQName);
+        final QName typedefQName = QName.create(moduleQName, typedefName);
+        final SchemaPath path = stack.addNodeToPath(typedefQName);
 
-        TypeDefinitionBuilder builder = moduleBuilder.addTypedef(line, typedefQName, path);
+        final TypeDefinitionBuilder builder = moduleBuilder.addTypedef(line, typedefQName, path);
         parseSchemaNodeArgs(ctx, builder);
         builder.setUnits(parseUnits(ctx));
         builder.setDefaultValue(parseDefault(ctx));
@@ -510,14 +511,14 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
                 case "union":
                     qname = BaseTypes.UNION_QNAME;
                     stack.addNodeToPath(qname);
-                    UnionTypeBuilder unionBuilder = moduleBuilder.addUnionType(line, moduleQName.getModule());
-                    Builder parent = moduleBuilder.getActualNode();
+                    final UnionTypeBuilder unionBuilder = moduleBuilder.addUnionType(line, moduleQName.getModule());
+                    final Builder parent = moduleBuilder.getActualNode();
                     unionBuilder.setParent(parent);
                     moduleBuilder.enterNode(unionBuilder);
                     break;
                 case "identityref":
                     qname = BaseTypes.IDENTITYREF_QNAME;
-                    SchemaPath path = stack.addNodeToPath(qname);
+                    final SchemaPath path = stack.addNodeToPath(qname);
                     moduleBuilder.addIdentityrefType(line, path, getIdentityrefBase(typeBody));
                     break;
                 default:
@@ -528,7 +529,7 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
                 }
             }
         } else {
-            TypeAwareBuilder parent = (TypeAwareBuilder) moduleBuilder.getActualNode();
+            final TypeAwareBuilder parent = (TypeAwareBuilder) moduleBuilder.getActualNode();
             if (typeBody == null) {
                 parent.setTypeQName(typeQName);
                 moduleBuilder.markActualNodeDirty();
@@ -565,7 +566,7 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
             if (prefix.equals(moduleBuilder.getPrefix())) {
                 qname = QName.create(moduleQName, name);
             } else {
-                ModuleImport imp = moduleBuilder.getImport(prefix);
+                final ModuleImport imp = moduleBuilder.getImport(prefix);
                 if (imp == null) {
                     LOG.debug("Error in module {} at line {}: No import found with prefix {}", moduleName, line, prefix);
                     throw new YangParseException(moduleName, line, "Error in module " + moduleName
@@ -609,10 +610,10 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         final int line = ctx.getStart().getLine();
         final String groupName = stringFromNode(ctx);
         enterLog("grouping", groupName, line);
-        QName groupQName = QName.create(moduleQName, groupName);
-        SchemaPath path = stack.addNodeToPath(groupQName);
+        final QName groupQName = QName.create(moduleQName, groupName);
+        final SchemaPath path = stack.addNodeToPath(groupQName);
 
-        GroupingBuilder builder = moduleBuilder.addGrouping(ctx.getStart().getLine(), groupQName, path);
+        final GroupingBuilder builder = moduleBuilder.addGrouping(ctx.getStart().getLine(), groupQName, path);
         parseSchemaNodeArgs(ctx, builder);
 
         moduleBuilder.enterNode(builder);
@@ -630,10 +631,10 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         final String containerName = stringFromNode(ctx);
         enterLog("container", containerName, line);
 
-        QName containerQName = QName.create(moduleQName, containerName);
-        SchemaPath path = stack.addNodeToPath(containerQName);
+        final QName containerQName = QName.create(moduleQName, containerName);
+        final SchemaPath path = stack.addNodeToPath(containerQName);
 
-        ContainerSchemaNodeBuilder builder = moduleBuilder.addContainerNode(line, containerQName, path);
+        final ContainerSchemaNodeBuilder builder = moduleBuilder.addContainerNode(line, containerQName, path);
         parseSchemaNodeArgs(ctx, builder);
         parseConstraints(ctx, builder.getConstraints());
         builder.setConfiguration(getConfig(ctx, builder, moduleName, line));
@@ -661,10 +662,10 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         final String leafName = stringFromNode(ctx);
         enterLog("leaf", leafName, line);
 
-        QName leafQName = QName.create(moduleQName, leafName);
-        SchemaPath path = stack.addNodeToPath(leafQName);
+        final QName leafQName = QName.create(moduleQName, leafName);
+        final SchemaPath path = stack.addNodeToPath(leafQName);
 
-        LeafSchemaNodeBuilder builder = moduleBuilder.addLeafNode(line, leafQName, path);
+        final LeafSchemaNodeBuilder builder = moduleBuilder.addLeafNode(line, leafQName, path);
         parseSchemaNodeArgs(ctx, builder);
         parseConstraints(ctx, builder.getConstraints());
         builder.setConfiguration(getConfig(ctx, builder, moduleName, line));
@@ -672,7 +673,7 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         String defaultStr = null;
         String unitsStr = null;
         for (int i = 0; i < ctx.getChildCount(); i++) {
-            ParseTree child = ctx.getChild(i);
+            final ParseTree child = ctx.getChild(i);
             if (child instanceof Default_stmtContext) {
                 defaultStr = stringFromNode(child);
             } else if (child instanceof Units_stmtContext) {
@@ -698,7 +699,7 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         final SchemaPath groupingPath = parseXPathString(groupingPathStr, line);
         enterLog("uses", groupingPathStr, line);
 
-        UsesNodeBuilder builder = moduleBuilder.addUsesNode(line, groupingPath);
+        final UsesNodeBuilder builder = moduleBuilder.addUsesNode(line, groupingPath);
 
         moduleBuilder.enterNode(builder);
     }
@@ -716,11 +717,11 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         enterLog(AUGMENT_STR, augmentPath, line);
         stack.push();
 
-        SchemaPath targetPath = parseXPathString(augmentPath, line);
-        AugmentationSchemaBuilder builder = moduleBuilder.addAugment(line, augmentPath, targetPath, augmentOrder++);
+        final SchemaPath targetPath = parseXPathString(augmentPath, line);
+        final AugmentationSchemaBuilder builder = moduleBuilder.addAugment(line, augmentPath, targetPath, augmentOrder++);
 
         for (int i = 0; i < ctx.getChildCount(); i++) {
-            ParseTree child = ctx.getChild(i);
+            final ParseTree child = ctx.getChild(i);
             if (child instanceof Description_stmtContext) {
                 builder.setDescription(stringFromNode(child));
             } else if (child instanceof Reference_stmtContext) {
@@ -747,7 +748,7 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         final String refineString = stringFromNode(ctx);
         enterLog("refine", refineString, ctx.getStart().getLine());
 
-        RefineHolderImpl refine = parseRefine(ctx, moduleName);
+        final RefineHolderImpl refine = parseRefine(ctx, moduleName);
         moduleBuilder.addRefine(refine);
         moduleBuilder.enterNode(refine);
     }
@@ -763,10 +764,10 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         final int line = ctx.getStart().getLine();
         final String leafListName = stringFromNode(ctx);
         enterLog("leaf-list", leafListName, line);
-        QName leafListQName = QName.create(moduleQName, leafListName);
-        SchemaPath path = stack.addNodeToPath(leafListQName);
+        final QName leafListQName = QName.create(moduleQName, leafListName);
+        final SchemaPath path = stack.addNodeToPath(leafListQName);
 
-        LeafListSchemaNodeBuilder builder = moduleBuilder.addLeafListNode(line, leafListQName, path);
+        final LeafListSchemaNodeBuilder builder = moduleBuilder.addLeafListNode(line, leafListQName, path);
         moduleBuilder.enterNode(builder);
 
         parseSchemaNodeArgs(ctx, builder);
@@ -796,10 +797,10 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         final String listName = stringFromNode(ctx);
         enterLog("list", listName, line);
 
-        QName listQName = QName.create(moduleQName, listName);
-        SchemaPath path = stack.addNodeToPath(listQName);
+        final QName listQName = QName.create(moduleQName, listName);
+        final SchemaPath path = stack.addNodeToPath(listQName);
 
-        ListSchemaNodeBuilder builder = moduleBuilder.addListNode(line, listQName, path);
+        final ListSchemaNodeBuilder builder = moduleBuilder.addListNode(line, listQName, path);
         moduleBuilder.enterNode(builder);
 
         parseSchemaNodeArgs(ctx, builder);
@@ -807,13 +808,13 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         builder.setConfiguration(getConfig(ctx, builder, moduleName, line));
 
         for (int i = 0; i < ctx.getChildCount(); ++i) {
-            ParseTree childNode = ctx.getChild(i);
+            final ParseTree childNode = ctx.getChild(i);
             if (childNode instanceof Ordered_by_stmtContext) {
                 final Ordered_by_stmtContext orderedBy = (Ordered_by_stmtContext) childNode;
                 final boolean userOrdered = parseUserOrdered(orderedBy);
                 builder.setUserOrdered(userOrdered);
             } else if (childNode instanceof Key_stmtContext) {
-                List<String> key = createListKey((Key_stmtContext) childNode);
+                final Set<String> key = createListKey((Key_stmtContext) childNode);
                 builder.setKeys(key);
             }
         }
@@ -831,10 +832,10 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         final String anyXmlName = stringFromNode(ctx);
         enterLog("anyxml", anyXmlName, line);
 
-        QName anyXmlQName = QName.create(moduleQName, anyXmlName);
-        SchemaPath path = stack.addNodeToPath(anyXmlQName);
+        final QName anyXmlQName = QName.create(moduleQName, anyXmlName);
+        final SchemaPath path = stack.addNodeToPath(anyXmlQName);
 
-        AnyXmlBuilder builder = moduleBuilder.addAnyXml(line, anyXmlQName, path);
+        final AnyXmlBuilder builder = moduleBuilder.addAnyXml(line, anyXmlQName, path);
         moduleBuilder.enterNode(builder);
 
         parseSchemaNodeArgs(ctx, builder);
@@ -854,10 +855,10 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         final String choiceName = stringFromNode(ctx);
         enterLog("choice", choiceName, line);
 
-        QName choiceQName = QName.create(moduleQName, choiceName);
-        SchemaPath path = stack.addNodeToPath(choiceQName);
+        final QName choiceQName = QName.create(moduleQName, choiceName);
+        final SchemaPath path = stack.addNodeToPath(choiceQName);
 
-        ChoiceBuilder builder = moduleBuilder.addChoice(line, choiceQName, path);
+        final ChoiceBuilder builder = moduleBuilder.addChoice(line, choiceQName, path);
         moduleBuilder.enterNode(builder);
 
         parseSchemaNodeArgs(ctx, builder);
@@ -866,9 +867,9 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
 
         // set 'default' case
         for (int i = 0; i < ctx.getChildCount(); i++) {
-            ParseTree child = ctx.getChild(i);
+            final ParseTree child = ctx.getChild(i);
             if (child instanceof Default_stmtContext) {
-                String defaultCase = stringFromNode(child);
+                final String defaultCase = stringFromNode(child);
                 builder.setDefaultCase(defaultCase);
                 break;
             }
@@ -887,10 +888,10 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         final String caseName = stringFromNode(ctx);
         enterLog("case", caseName, line);
 
-        QName caseQName = QName.create(moduleQName, caseName);
-        SchemaPath path = stack.addNodeToPath(caseQName);
+        final QName caseQName = QName.create(moduleQName, caseName);
+        final SchemaPath path = stack.addNodeToPath(caseQName);
 
-        ChoiceCaseBuilder builder = moduleBuilder.addCase(line, caseQName, path);
+        final ChoiceCaseBuilder builder = moduleBuilder.addCase(line, caseQName, path);
         moduleBuilder.enterNode(builder);
 
         parseSchemaNodeArgs(ctx, builder);
@@ -909,10 +910,10 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         final String notificationName = stringFromNode(ctx);
         enterLog("notification", notificationName, line);
 
-        QName notificationQName = QName.create(moduleQName, notificationName);
-        SchemaPath path = stack.addNodeToPath(notificationQName);
+        final QName notificationQName = QName.create(moduleQName, notificationName);
+        final SchemaPath path = stack.addNodeToPath(notificationQName);
 
-        NotificationBuilder builder = moduleBuilder.addNotification(line, notificationQName, path);
+        final NotificationBuilder builder = moduleBuilder.addNotification(line, notificationQName, path);
         moduleBuilder.enterNode(builder);
 
         parseSchemaNodeArgs(ctx, builder);
@@ -951,13 +952,12 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         final String rpcName = stringFromNode(ctx);
         enterLog("rpc", rpcName, line);
 
-        QName rpcQName = QName.create(moduleQName, rpcName);
-        SchemaPath path = stack.addNodeToPath(rpcQName);
+        final QName rpcQName = QName.create(moduleQName, rpcName);
+        final SchemaPath path = stack.addNodeToPath(rpcQName);
 
-        RpcDefinitionBuilder rpcBuilder = moduleBuilder.addRpc(line, rpcQName, path);
+        final RpcDefinitionBuilder rpcBuilder = moduleBuilder.addRpc(line, rpcQName, path);
         moduleBuilder.enterNode(rpcBuilder);
 
-
         parseSchemaNodeArgs(ctx, rpcBuilder);
     }
 
@@ -973,10 +973,10 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         final String input = "input";
         enterLog(input, input, line);
 
-        QName rpcQName = QName.create(moduleQName, input);
-        SchemaPath path = stack.addNodeToPath(rpcQName);
+        final QName rpcQName = QName.create(moduleQName, input);
+        final SchemaPath path = stack.addNodeToPath(rpcQName);
 
-        ContainerSchemaNodeBuilder builder = moduleBuilder.addRpcInput(line, rpcQName, path);
+        final ContainerSchemaNodeBuilder builder = moduleBuilder.addRpcInput(line, rpcQName, path);
         moduleBuilder.enterNode(builder);
         builder.setConfiguration(true);
 
@@ -996,10 +996,10 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         final String output = "output";
         enterLog(output, output, line);
 
-        QName rpcQName = QName.create(moduleQName, output);
-        SchemaPath path = stack.addNodeToPath(rpcQName);
+        final QName rpcQName = QName.create(moduleQName, output);
+        final SchemaPath path = stack.addNodeToPath(rpcQName);
 
-        ContainerSchemaNodeBuilder builder = moduleBuilder.addRpcOutput(path, rpcQName, line);
+        final ContainerSchemaNodeBuilder builder = moduleBuilder.addRpcOutput(path, rpcQName, line);
         moduleBuilder.enterNode(builder);
         builder.setConfiguration(true);
 
@@ -1019,10 +1019,10 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         final String featureName = stringFromNode(ctx);
         enterLog("feature", featureName, line);
 
-        QName featureQName = QName.create(moduleQName, featureName);
-        SchemaPath path = stack.addNodeToPath(featureQName);
+        final QName featureQName = QName.create(moduleQName, featureName);
+        final SchemaPath path = stack.addNodeToPath(featureQName);
 
-        FeatureBuilder featureBuilder = moduleBuilder.addFeature(line, featureQName, path);
+        final FeatureBuilder featureBuilder = moduleBuilder.addFeature(line, featureQName, path);
         moduleBuilder.enterNode(featureBuilder);
 
         parseSchemaNodeArgs(ctx, featureBuilder);
@@ -1047,8 +1047,8 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         String reference = null;
         String deviate = null;
 
-        SchemaPath targetPath = parseXPathString(targetPathStr, line);
-        DeviationBuilder builder = moduleBuilder.addDeviation(line, targetPath);
+        final SchemaPath targetPath = parseXPathString(targetPathStr, line);
+        final DeviationBuilder builder = moduleBuilder.addDeviation(line, targetPath);
         moduleBuilder.enterNode(builder);
 
         for (int i = 0; i < ctx.getChildCount(); i++) {
@@ -1098,15 +1098,15 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         enterLog("identity", identityName, line);
 
         final QName identityQName = QName.create(moduleQName, identityName);
-        SchemaPath path = stack.addNodeToPath(identityQName);
+        final SchemaPath path = stack.addNodeToPath(identityQName);
 
-        IdentitySchemaNodeBuilder builder = moduleBuilder.addIdentity(identityQName, line, path);
+        final IdentitySchemaNodeBuilder builder = moduleBuilder.addIdentity(identityQName, line, path);
         moduleBuilder.enterNode(builder);
 
         parseSchemaNodeArgs(ctx, builder);
 
         for (int i = 0; i < ctx.getChildCount(); i++) {
-            ParseTree child = ctx.getChild(i);
+            final ParseTree child = ctx.getChild(i);
             if (child instanceof Base_stmtContext) {
                 String baseIdentityName = stringFromNode(child);
                 builder.setBaseIdentityName(baseIdentityName);
@@ -1145,7 +1145,7 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
         enterLog("unknown-node", nodeParameter, line);
 
         final String nodeTypeStr = ctx.getChild(0).getText();
-        QName nodeType = parseQName(nodeTypeStr, line);
+        final QName nodeType = parseQName(nodeTypeStr, line);
 
         QName qname = null;
         try {
@@ -1168,9 +1168,9 @@ public final class YangParserListenerImpl extends YangParserBaseListener {
             qname = nodeType;
         }
 
-        SchemaPath path = stack.addNodeToPath(qname);
+        final SchemaPath path = stack.addNodeToPath(qname);
 
-        UnknownSchemaNodeBuilderImpl builder = moduleBuilder.addUnknownSchemaNode(line, qname, path);
+        final UnknownSchemaNodeBuilderImpl builder = moduleBuilder.addUnknownSchemaNode(line, qname, path);
         builder.setNodeType(nodeType);
         builder.setNodeParameter(nodeParameter);
 
index e6e357dc0e9664f21595bf54066caea591071500..ebe602d5a72c42a06fec63899b8d63a0d8b9d2ce 100644 (file)
@@ -63,7 +63,7 @@ final class SharedSchemaContextFactory implements SchemaContextFactory {
             return repository.getSchemaSource(input, ASTSchemaSource.class);
         }
     };
-    private final Cache<Collection<SourceIdentifier>, SchemaContext> cache = CacheBuilder.newBuilder().softValues().build();
+    private final Cache<Collection<SourceIdentifier>, SchemaContext> cache = CacheBuilder.newBuilder().weakValues().build();
 
     private final AsyncFunction<List<ASTSchemaSource>, SchemaContext> assembleSources = new AsyncFunction<List<ASTSchemaSource>, SchemaContext>() {
         @Override