Merge "Improved sorting of augmentations before code generation."
authorTony Tkacik <ttkacik@cisco.com>
Fri, 6 Jun 2014 08:24:42 +0000 (08:24 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Fri, 6 Jun 2014 08:24:42 +0000 (08:24 +0000)
88 files changed:
code-generator/binding-generator-impl/src/main/java/org/opendaylight/yangtools/sal/binding/generator/impl/BindingGeneratorImpl.xtend
common/checkstyle-logging/pom.xml
common/checkstyle-logging/src/main/java/org/opendaylight/yangtools/checkstyle/CheckLoggingUtil.java
common/checkstyle-logging/src/main/java/org/opendaylight/yangtools/checkstyle/LoggerDeclarationsCountCheck.java [new file with mode: 0644]
common/checkstyle-logging/src/main/java/org/opendaylight/yangtools/checkstyle/LoggerFactoryClassParameterCheck.java
common/checkstyle-logging/src/main/java/org/opendaylight/yangtools/checkstyle/LoggerMustBeSlf4jCheck.java
common/checkstyle-logging/src/main/java/org/opendaylight/yangtools/checkstyle/LoggerVariableModifiersCheck.java
common/checkstyle-logging/src/main/java/org/opendaylight/yangtools/checkstyle/LoggerVariableNameCheck.java
common/checkstyle-logging/src/main/resources/checkstyle-logging.xml
common/checkstyle-logging/src/test/java/org/opendaylight/yangtools/checkstyle/CheckCodingStyleTestClass.java [new file with mode: 0644]
common/checkstyle-logging/src/test/java/org/opendaylight/yangtools/checkstyle/CheckLoggingTestClass.java
common/checkstyle-logging/src/test/java/org/opendaylight/yangtools/checkstyle/CheckstyleTest.java
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/AbstractRegistration.java
common/concepts/src/main/java/org/opendaylight/yangtools/concepts/ListenerRegistration.java
common/util/pom.xml
common/util/src/main/java/org/opendaylight/yangtools/util/ExecutorServiceUtil.java [new file with mode: 0644]
model/ietf/ietf-restconf/src/main/yang/ietf-restconf@2013-10-19.yang
yang/yang-binding/src/main/java/org/opendaylight/yangtools/yang/binding/util/BindingReflections.java
yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/QName.java
yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/RpcError.java
yang/yang-common/src/main/java/org/opendaylight/yangtools/yang/common/RpcResult.java
yang/yang-data-api/pom.xml
yang/yang-data-api/src/main/java/org/opendaylight/yangtools/yang/data/api/InstanceIdentifier.java
yang/yang-data-api/src/test/java/org/opendaylight/yangtools/yang/data/api/InstanceIdentifierTest.java [new file with mode: 0644]
yang/yang-data-impl/pom.xml
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/codec/TypeDefinitionAwareCodec.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/schema/builder/impl/ImmutableLeafNodeBuilder.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/ImmutableOrderedLeafSetNodeBuilder.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/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/AbstractImmutableNormalizedNode.java
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableNormalizedValueAttrNode.java [moved from yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableNormalizedAttrNode.java with 87% similarity]
yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableNormalizedValueNode.java [new file with mode: 0644]
yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/ChoiceNode.java
yang/yang-model-api/src/main/java/org/opendaylight/yangtools/yang/model/api/DataSchemaNode.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/AbstractSignedInteger.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/AbstractUnsignedInteger.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/BaseConstraints.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/BaseTypes.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/BinaryType.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/BitsType.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/BooleanType.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/DataNodeIterator.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/Decimal64.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/EmptyType.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/EnumerationType.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/ExtendedType.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/IdentityrefType.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/InstanceIdentifier.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/Int16.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/Int32.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/Int64.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/Int8.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/Leafref.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/LengthConstraintImpl.java [new file with mode: 0644]
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/PatternConstraintImpl.java [new file with mode: 0644]
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/RangeConstraintImpl.java [new file with mode: 0644]
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/RevisionAwareXPathImpl.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/StringType.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/Uint16.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/Uint32.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/Uint64.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/Uint8.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/UnionType.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/UnknownType.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/YangTypesConverter.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/package-info.java [new file with mode: 0644]
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/repo/AbstractCachingSchemaSourceProvider.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/repo/AdvancedSchemaSourceProvider.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/repo/FilesystemSchemaCachingProvider.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/repo/SchemaService.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/repo/SchemaSourceProvider.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/repo/SchemaSourceProviders.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/repo/SchemaSourceTransformation.java [new file with mode: 0644]
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/repo/SourceIdentifier.java
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/repo/TransformingSourceProvider.java [new file with mode: 0644]
yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/repo/package-info.java [new file with mode: 0644]
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YangParserImpl.java
yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/util/ParserUtils.java
yang/yang-parser-impl/src/test/java/org/opendaylight/yangtools/yang/parser/impl/YangParserNegativeTest.java
yang/yang-parser-impl/src/test/resources/negative-scenario/duplicity/augment0.yang
yang/yang-parser-impl/src/test/resources/negative-scenario/duplicity/augment1.yang
yang/yang-parser-impl/src/test/resources/negative-scenario/duplicity/augment2.yang

index 82a191eb44288371129f55d67c3ae9b4be6d3320..d2341b73309964759b57476237ea1e1a0ab159d9 100644 (file)
@@ -1571,7 +1571,6 @@ public class BindingGeneratorImpl implements BindingGenerator {
     private def GeneratedTypeBuilder addDefaultInterfaceDefinition(String packageName, SchemaNode schemaNode,
         Type parent) {
         val it = addRawInterfaceDefinition(packageName, schemaNode, "");
-        qnameConstant(BindingMapping.QNAME_STATIC_FIELD_NAME,schemaNode.QName);
         if (parent === null) {
             addImplementsType(DATA_OBJECT);
         } else {
@@ -1643,6 +1642,7 @@ public class BindingGeneratorImpl implements BindingGenerator {
 
         //FIXME: Validation of name conflict
         val newType = new GeneratedTypeBuilderImpl(packageName, genTypeName);
+        qnameConstant(newType,BindingMapping.QNAME_STATIC_FIELD_NAME,schemaNode.QName);
         newType.addComment(schemaNode.getDescription());
         if (!genTypeBuilders.containsKey(packageName)) {
             val Map<String, GeneratedTypeBuilder> builders = new HashMap();
index 775c15a3f37b5fd0e5d2f0bccd6f3330a3d05f92..8960ca957905eb09cc83ded500a3ac9332c43828 100644 (file)
@@ -1,3 +1,12 @@
+<?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">
   <modelVersion>4.0.0</modelVersion>
   <parent>
@@ -11,7 +20,7 @@
     <dependency>
       <groupId>com.puppycrawl.tools</groupId>
       <artifactId>checkstyle</artifactId>
-      <version>5.6</version>
+      <version>5.7</version>
     </dependency>
     <dependency>
         <groupId>org.slf4j</groupId>
index 37d203cf2cf715f754b32b356461d77e27ac2446..0747a85e0adb7ca07f3a5d69d181d519f8f9a258 100644 (file)
@@ -45,7 +45,7 @@ public class CheckLoggingUtil {
         return identifier.getText();
     }
 
-    public static boolean itsAFieldVariable(final DetailAST aAST) {
+    public static boolean isAFieldVariable(final DetailAST aAST) {
         return aAST.getParent().getType() == TokenTypes.OBJBLOCK;
     }
 
@@ -60,4 +60,12 @@ public class CheckLoggingUtil {
         return LOG_METHODS.contains(methodName);
     }
 
+    public static String getClassName(final DetailAST aAST) {
+        DetailAST parent = aAST.getParent();
+        while(parent.getType() != TokenTypes.CLASS_DEF && parent.getType() != TokenTypes.ENUM_DEF) {
+            parent = parent.getParent();
+        }
+        return parent.findFirstToken(TokenTypes.IDENT).getText();
+    }
+
 }
diff --git a/common/checkstyle-logging/src/main/java/org/opendaylight/yangtools/checkstyle/LoggerDeclarationsCountCheck.java b/common/checkstyle-logging/src/main/java/org/opendaylight/yangtools/checkstyle/LoggerDeclarationsCountCheck.java
new file mode 100644 (file)
index 0000000..51bbe3e
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * 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.checkstyle;
+
+import static org.opendaylight.yangtools.checkstyle.CheckLoggingUtil.isAFieldVariable;
+
+import com.puppycrawl.tools.checkstyle.api.Check;
+import com.puppycrawl.tools.checkstyle.api.DetailAST;
+import com.puppycrawl.tools.checkstyle.api.TokenTypes;
+
+public class LoggerDeclarationsCountCheck extends Check {
+
+    private static final String LOG_MESSAGE = "Logger might be declared only once.";
+    private String prevClassName = "";
+
+    @Override
+    public int[] getDefaultTokens() {
+        return new int[]{TokenTypes.VARIABLE_DEF};
+    }
+
+    @Override
+    public void visitToken(DetailAST aAST) {
+        if (CheckLoggingUtil.isLoggerType(aAST) && isAFieldVariable(aAST)) {
+            final String className = CheckLoggingUtil.getClassName(aAST);
+            if(this.prevClassName.equals(className)) {
+                log(aAST.getLineNo(), LOG_MESSAGE);
+            }
+            this.prevClassName = className;
+        }
+    }
+
+    @Override
+    public void finishTree(DetailAST aRootAST) {
+        super.finishTree(aRootAST);
+        this.prevClassName = "";
+    }
+
+}
index 5975b8e54b032eca4751289f8d2122fd02f08efd..95915250e46c90222dbc2f9c81497143ba53325b 100644 (file)
@@ -26,7 +26,7 @@ public class LoggerFactoryClassParameterCheck extends Check {
     public void visitToken(DetailAST aAST) {
         final String methodName = CheckLoggingUtil.getMethodName(aAST);
         if(methodName.equals(METHOD_NAME)) {
-            final String className = getClassName(aAST);
+            final String className = CheckLoggingUtil.getClassName(aAST);
             final String parameter = aAST.findFirstToken(TokenTypes.ELIST).getFirstChild().getFirstChild().getFirstChild().getText();
             if(!parameter.equals(className)) {
                 log(aAST.getLineNo(), LOG_MESSAGE);
@@ -34,12 +34,4 @@ public class LoggerFactoryClassParameterCheck extends Check {
         }
     }
 
-    private String getClassName(final DetailAST aAST) {
-        DetailAST parent = aAST.getParent();
-        while(parent.getType() != TokenTypes.CLASS_DEF && parent.getType() != TokenTypes.ENUM_DEF) {
-            parent = parent.getParent();
-        }
-        return parent.findFirstToken(TokenTypes.IDENT).getText();
-    }
-
 }
index 2871403f398213643377faa4128ae95f6d6d6536..a78eec8528968514caf388528845c2986e77753e 100644 (file)
@@ -29,7 +29,7 @@ public class LoggerMustBeSlf4jCheck extends Check {
     public void visitToken(DetailAST aAST) {
         if(aAST.getType() == TokenTypes.VARIABLE_DEF) {
             final String typeName = CheckLoggingUtil.getTypeName(aAST);
-            if (CheckLoggingUtil.itsAFieldVariable(aAST) && typeName.contains("." + LOGGER_TYPE_NAME)) {
+            if (CheckLoggingUtil.isAFieldVariable(aAST) && typeName.contains("." + LOGGER_TYPE_NAME)) {
                 if(!typeName.equals(LOGGER_TYPE_FULL_NAME)) {
                     log(aAST.getLineNo(), LOG_MESSAGE);
                 }
index e3ef112f18cd51bbeaee489e2a61f092b27a7cb3..63249cba40f2aaf92931982b56de8d64903c0573 100644 (file)
@@ -23,7 +23,7 @@ public class LoggerVariableModifiersCheck extends Check {
 
     @Override
     public void visitToken(DetailAST aAST) {
-        if (CheckLoggingUtil.itsAFieldVariable(aAST) && CheckLoggingUtil.isLoggerType(aAST) && !hasPrivatStaticFinalModifier(aAST)) {
+        if (CheckLoggingUtil.isAFieldVariable(aAST) && CheckLoggingUtil.isLoggerType(aAST) && !hasPrivatStaticFinalModifier(aAST)) {
             log(aAST.getLineNo(), LOG_MESSAGE);
         }
     }
index 7569f141dd3ca203e8e1f6ef68b2f2c056f06e79..615f9148c03843cc50fe4df3718085bec0723d3f 100644 (file)
@@ -26,7 +26,7 @@ public class LoggerVariableNameCheck extends Check {
     @Override
     public void visitToken(DetailAST aAST) {
         final String variableName = CheckLoggingUtil.getVariableName(aAST);
-        if (CheckLoggingUtil.itsAFieldVariable(aAST) && CheckLoggingUtil.isLoggerType(aAST) && !variableName.equals(LOGGER_VAR_NAME)) {
+        if (CheckLoggingUtil.isAFieldVariable(aAST) && CheckLoggingUtil.isLoggerType(aAST) && !variableName.equals(LOGGER_VAR_NAME)) {
             log(aAST.getLineNo(), LOG_MESSAGE);
         }
     }
index 6d7bc62d7c34f1409d2842e73f122aa6625036e0..b404a3e6bee0aae1f1ea2d8160f038423a3ed3f1 100644 (file)
       <module name="org.opendaylight.yangtools.checkstyle.LogMessagePlaceholderCountCheck" />
     </module>
 
+    <module name="TreeWalker">
+        <module name="org.opendaylight.yangtools.checkstyle.LoggerDeclarationsCountCheck"/>
+    </module>
+
+    <module name="FileTabCharacter">
+        <property name="eachLine" value="true"/>
+    </module>
+
     <module name="RegexpSingleline">
-        <property name="format" value="(\.|\b)Logger "/>
-        <property name="message" value="Logger might be declared only once."/>
-        <property name="minimum" value="0"/>
-        <property name="maximum" value="1"/>
+        <property name="format" value="\s+$"/>
+        <property name="message" value="Line has trailing spaces."/>
+    </module>
+
+    <module name="RegexpMultiline">
+        <property name="format" value="(\r\n|\r)"/>
+        <property name="message" value="Line has Windows line delimiter."/>
+    </module>
+
+    <module name="TreeWalker">
+        <module name="Indentation">
+            <property name="caseIndent" value="0"/>
+            <property name="throwsIndent" value="8"/>
+        </module>
+
+        <module name="UnusedImports"/>
+
+        <module name="ImportOrder">
+            <property name="ordered" value="true"/>
+            <property name="separated" value="true"/>
+            <property name="option" value="above"/>
+        </module>
     </module>
 </module>
\ No newline at end of file
diff --git a/common/checkstyle-logging/src/test/java/org/opendaylight/yangtools/checkstyle/CheckCodingStyleTestClass.java b/common/checkstyle-logging/src/test/java/org/opendaylight/yangtools/checkstyle/CheckCodingStyleTestClass.java
new file mode 100644 (file)
index 0000000..9a18b37
--- /dev/null
@@ -0,0 +1,26 @@
+/*\r
+ * Copyright (c) 2014 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+\r
+package org.opendaylight.yangtools.checkstyle;\r
+\r
+import java.util.Comparator;\r
+import java.util.Map;\r
+\r
+import static java.lang.String.CASE_INSENSITIVE_ORDER;\r
+\r
+import com.google.common.collect.Maps;\r
+import com.google.common.collect.Lists;\r
+\r
+public class CheckCodingStyleTestClass {\r
+\r
+       public CheckCodingStyleTestClass() {\r
+               Comparator<String> string = CASE_INSENSITIVE_ORDER; \r
+               \r
+          Map<String, String> map = Maps.newHashMap();\r
+       }\r
+}\r
index 6a2b170c5efa6cdcbe4c7a681ccf779ff2121121..8b771f952a3b67776a1a1bb53fc733554cd36ab5 100644 (file)
@@ -34,4 +34,4 @@ public class CheckLoggingTestClass {
         LOG.warn("foo {}", string);
         LOG.warn("foo {}", string, e);
     }
-}
\ No newline at end of file
+}
index a12daf92bfa8733c0a5293ba5fc0edec56370ffc..89f4cf39f60695ddc863a4c2102a47520025baad 100644 (file)
@@ -56,12 +56,19 @@ public class CheckstyleTest {
     @Test
     public void testLoggerChecks() throws Exception {
         verify(CheckLoggingTestClass.class, "15: Logger must be declared as private static final.", "15: Logger name should be LOG.",
-                "16: Logger might be declared only once.", "16: Logger must be slf4j.", "22: Line contains printStacktrace", 
+                "17: Logger might be declared only once.", "16: Logger must be slf4j.", "22: Line contains printStacktrace",
                 "23: Line contains console output", "24: Line contains console output",
                 "15: LoggerFactory.getLogger Class argument is incorrect.", "20: Log message contains string concatenation.",
                 "26: Log message placeholders count is incorrect.", "32: Log message placeholders count is incorrect");
     }
 
+    @Test
+    public void testCodingChecks() {
+        verify(CheckCodingStyleTestClass.class, "9: Line has Windows line delimiter.", "14: Wrong order for", "24:1: Line contains a tab character.",
+                "22: Line has trailing spaces.", "22: ctor def child at indentation level 16 not at correct indentation, 8", "17:8: Unused import",
+                "23: Line has trailing spaces.");
+    }
+
     private void verify(final Class<?> testClass, final String... expectedMessages) {
         final String filePath = System.getProperty("user.dir") + File.separator + "src" + File.separator + "test" + File.separator + "java" + File.separator + testClass.getName().replaceAll("\\.", "/") + ".java";
         final File testFile = new File(filePath);
index 50f19fc9e3ef596c56754909889b3d308a66e673..1a2c7f32f824cb9732cdaaa4068bd78378e5ac20 100644 (file)
@@ -7,7 +7,7 @@
  */
 package org.opendaylight.yangtools.concepts;
 
-import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;
 
 /**
  * Utility registration handle. It is a convenience for register-style method
@@ -16,8 +16,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
  * installed.
  */
 public abstract class AbstractRegistration implements AutoCloseable {
-    private AtomicBoolean closed = new AtomicBoolean();
-    
+    private static final AtomicIntegerFieldUpdater<AbstractRegistration> CLOSED_UPDATER =
+            AtomicIntegerFieldUpdater.newUpdater(AbstractRegistration.class, "closed");
+    private volatile int closed = 0;
+
     /**
      * Remove the state referenced by this registration. This method is
      * guaranteed to be called at most once. The referenced state must be
@@ -25,9 +27,19 @@ public abstract class AbstractRegistration implements AutoCloseable {
      */
     protected abstract void removeRegistration();
 
+    /**
+     * Query the state of this registration. Returns true if it was
+     * closed.
+     *
+     * @return true if the registration was closed, false otherwise.
+     */
+    protected final boolean isClosed() {
+        return CLOSED_UPDATER.get(this) != 0;
+    }
+
     @Override
     public final void close() {
-        if (closed.compareAndSet(false, true)) {
+        if (CLOSED_UPDATER.compareAndSet(this, 0, 1)) {
             removeRegistration();
         }
     }
index 8fe2d8ff8b1bfce523077599f315e5038196f54e..a798f2ef6d0053707bc0693dd4b4f5cd467fcd96 100644 (file)
@@ -18,7 +18,7 @@ public interface ListenerRegistration<T extends EventListener> extends ObjectReg
     /**
      * Unregister the listener. No events should be delivered to the listener
      * once this method returns successfully. While the interface contract
-     * allows an implementation to ignore the occurence of RuntimeExceptions,
+     * allows an implementation to ignore the occurrence of RuntimeExceptions,
      * implementations are strongly encouraged to deal with such exceptions
      * internally and to ensure invocations of this method do not fail in such
      * circumstances.
index 77f81902054dfa333e0b9c0248a607ed36fcb69f..146b009d438035a45b06e1779b9e792350dccb05 100644 (file)
                 <artifactId>maven-bundle-plugin</artifactId>
                 <extensions>true</extensions>
                 <configuration>
-                    <Export-Package>org.opendaylight.yangtools.util</Export-Package>
-                    <Embed-Dependency>java-concurrent-hash-trie-map;inline=true</Embed-Dependency>
+                    <instructions>
+                        <Export-Package>org.opendaylight.yangtools.util</Export-Package>
+                        <Embed-Dependency>java-concurrent-hash-trie-map;inline=true</Embed-Dependency>
+                    </instructions>
                 </configuration>
             </plugin>
         </plugins>
diff --git a/common/util/src/main/java/org/opendaylight/yangtools/util/ExecutorServiceUtil.java b/common/util/src/main/java/org/opendaylight/yangtools/util/ExecutorServiceUtil.java
new file mode 100644 (file)
index 0000000..36f729f
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * 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.util;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.RejectedExecutionException;
+import java.util.concurrent.RejectedExecutionHandler;
+import java.util.concurrent.ThreadPoolExecutor;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.util.concurrent.ForwardingBlockingQueue;
+
+/**
+ * Utility methods for dealing with {@link ExecutorService}s.
+ */
+public final class ExecutorServiceUtil {
+    private static final class WaitInQueueExecutionHandler implements RejectedExecutionHandler {
+        @Override
+        public void rejectedExecution(final Runnable r, final ThreadPoolExecutor executor) {
+            try {
+                executor.getQueue().put(r);
+            } catch (InterruptedException e) {
+                LOG.debug("Intterupted while waiting for queue", e);
+                throw new RejectedExecutionException("Interrupted while waiting for queue", e);
+            }
+        }
+    }
+
+    private static final Logger LOG = LoggerFactory.getLogger(ExecutorServiceUtil.class);
+    private static final RejectedExecutionHandler WAIT_IN_QUEUE_HANDLER = new WaitInQueueExecutionHandler();
+
+    private ExecutorServiceUtil() {
+        throw new UnsupportedOperationException("Utility class");
+    }
+
+    /**
+     * Create a {@link BlockingQueue} which does not allow for non-blocking addition to the queue.
+     * This is useful with {@link #waitInQueueExecutionHandler()} to turn force a
+     * {@link ThreadPoolExecutor} to create as many threads as it is configured to before starting
+     * to fill the queue.
+     *
+     * @param delegate Backing blocking queue.
+     * @return A new blocking queue backed by the delegate
+     */
+    public <E> BlockingQueue<E> offerFailingBlockingQueue(final BlockingQueue<E> delegate) {
+        return new ForwardingBlockingQueue<E>() {
+            @Override
+            public boolean offer(final E o) {
+                return false;
+            }
+
+            @Override
+            protected BlockingQueue<E> delegate() {
+                return delegate;
+            }
+        };
+    }
+
+    /**
+     * Return a {@link RejectedExecutionHandler} which blocks on the {@link ThreadPoolExecutor}'s
+     * backing queue if a new thread cannot be spawned.
+     *
+     * @return A shared RejectedExecutionHandler instance.
+     */
+    public RejectedExecutionHandler waitInQueueExecutionHandler() {
+        return WAIT_IN_QUEUE_HANDLER;
+    }
+}
index a389b197d67b5d7785a396e7d2d719b7d4359b88..83bb378351309d8ca38dd53b54f034680a3915de 100644 (file)
@@ -2,7 +2,7 @@ module ietf-restconf {
   namespace "urn:ietf:params:xml:ns:yang:ietf-restconf";
   prefix "restconf";
 
-  import ietf-yang-types { prefix yang; }
+  import ietf-yang-types { prefix yang; revision-date 2013-07-15; }
   import ietf-inet-types { prefix inet; }
 
   organization
index 0b057a194bc86b1d79a8218b67e820eb88dee819..d6c1d7b75138ab6da9ad5290cc83f4714459b7a3 100644 (file)
@@ -441,29 +441,103 @@ public class BindingReflections {
 
         @Override
         public Optional<QName> load(final Class<?> key) throws Exception {
+            return resolveQNameNoCache(key);
+        }
+    }
+
+    /**
+     *
+     * Tries to resolve QName for supplied class.
+     *
+     * Looks up for static field with name from constant {@link BindingMapping#QNAME_STATIC_FIELD_NAME}
+     * and returns value if present.
+     *
+     * If field is not present uses {@link #computeQName(Class)} to compute QName for missing types.
+     *
+     * @param key
+     * @return
+     */
+    private static Optional<QName> resolveQNameNoCache(final Class<?> key) {
+        try {
+            Field field = key.getField(BindingMapping.QNAME_STATIC_FIELD_NAME);
+            Object obj = field.get(null);
+            if (obj instanceof QName) {
+                return Optional.of((QName) obj);
+            }
+
+        } catch (NoSuchFieldException e) {
+            return Optional.of(computeQName(key));
+
+        } catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
+            /*
+             *
+             * It is safe to log this this exception on debug, since
+             * this method should not fail. Only failures are possible if
+             * the runtime / backing.
+             *
+             */
+            LOG.debug("Unexpected exception during extracting QName for {}",key,e);
+        }
+        return Optional.absent();
+    }
+
+    /**
+     * Computes QName for supplied class
+     *
+     * Namespace and revision are same as {@link YangModuleInfo}
+     * associated with supplied class.
+     * <p>
+     * If class is
+     * <ul>
+     *  <li>rpc input: local name is "input".
+     *  <li>rpc output: local name is "output".
+     *  <li>augmentation: local name is "module name".
+     * </ul>
+     *
+     * There is also fallback, if it is not possible to compute QName
+     * using following algorithm returns module QName.
+     *
+     * FIXME: Extend this algorithm to also provide QName for YANG modeled simple types.
+     *
+     * @throws IllegalStateException If YangModuleInfo could not be resolved
+     * @throws IllegalArgumentException If supplied class was not derived from YANG model.
+     *
+     */
+    @SuppressWarnings({ "rawtypes", "unchecked" })
+    private static QName computeQName(final Class key) {
+        if(isBindingClass(key)) {
+            YangModuleInfo moduleInfo;
             try {
-                Field field = key.getField(BindingMapping.QNAME_STATIC_FIELD_NAME);
-                Object obj = field.get(null);
-                if (obj instanceof QName) {
-                    return Optional.of((QName) obj);
-                }
-            } catch (NoSuchFieldException e) {
-                if (Augmentation.class.isAssignableFrom(key)) {
-                    YangModuleInfo moduleInfo = getModuleInfo(key);
-                    return Optional.of(QName.create(moduleInfo.getNamespace(), moduleInfo.getRevision(),
-                            moduleInfo.getName()));
+                moduleInfo = getModuleInfo(key);
+            } catch (Exception e) {
+                throw new IllegalStateException("Unable to get QName for " + key + ". YangModuleInfo was not found.",e);
+            }
+            final QName module = getModuleQName(moduleInfo);
+            if (Augmentation.class.isAssignableFrom(key)) {
+                return module;
+            } else if(isRpcType(key)) {
+                final String className = key.getSimpleName();
+                if(className.endsWith(BindingMapping.RPC_OUTPUT_SUFFIX)) {
+                    return QName.create(module,"output");
+                } else {
+                    return QName.create(module,"input");
                 }
-            } catch (SecurityException | IllegalArgumentException | IllegalAccessException e) {
-                /*
-                 *
-                 * It is safe to log this this exception on debug, since
-                 * this method should not fail. Only failures are possible if
-                 * the runtime / backing.
-                 *
-                 */
-                LOG.debug("Unexpected exception during extracting QName for {}",key,e);
             }
-            return Optional.absent();
+            /*
+             *  Fallback for Binding types which fo not have QNAME
+             *  field
+             */
+            return module;
+        } else {
+            throw new IllegalArgumentException("Supplied class "+key+"is not derived from YANG.");
         }
     }
+
+    public static QName getModuleQName(final YangModuleInfo moduleInfo) {
+        checkArgument(moduleInfo != null, "moduleInfo must not be null.");
+        return QName.create(moduleInfo.getNamespace(), moduleInfo.getRevision(),
+                moduleInfo.getName());
+    }
+
+
 }
index 09a2625697526410a40daac992aeca7f9f06768c..e31239dd8fbd49a0069a64602fb94c01c3c722b4 100644 (file)
@@ -30,14 +30,18 @@ import org.opendaylight.yangtools.concepts.Immutable;
  * same local name, but from different schemas.
  *
  * <ul>
- * <li><b>XMLNamespace</b> - the namespace assigned to the YANG module which
+ * <li><b>XMLNamespace</b> - {@link #getNamespace()} - the namespace assigned to the YANG module which
  * defined element, type, procedure or notification.</li>
- * <li><b>Revision</b> - the revision of the YANG module which describes the
+ * <li><b>Revision</b> - {@link #getRevision()} - the revision of the YANG module which describes the
  * element</li>
- * <li><b>LocalName</b> - the YANG schema identifier which were defined for this
+ * <li><b>LocalName</b> - {@link #getLocalName()} - the YANG schema identifier which were defined for this
  * node in the YANG module</li>
  * </ul>
  *
+ * QName may also have <code>prefix</code> assigned, but prefix does not
+ * affect equality and identity of two QNames and carry only information
+ * which may be useful for serializers / deserializers.
+ *
  *
  */
 public final class QName implements Immutable, Serializable, Comparable<QName> {
@@ -47,22 +51,26 @@ public final class QName implements Immutable, Serializable, Comparable<QName> {
     static final String QNAME_LEFT_PARENTHESIS = "(";
     static final String QNAME_RIGHT_PARENTHESIS = ")";
 
-    private static final Pattern QNAME_PATTERN_FULL = Pattern.compile(
-            "^\\((.+)\\" + QNAME_REVISION_DELIMITER + "(.+)\\)(.+)$");
-    private static final Pattern QNAME_PATTERN_NO_REVISION = Pattern.compile(
-           "^\\((.+)\\)(.+)$");
-    private static final Pattern QNAME_PATTERN_NO_NAMESPACE_NO_REVISION = Pattern.compile(
-            "^(.+)$");
+    private static final Pattern QNAME_PATTERN_FULL = Pattern.compile("^\\((.+)\\" + QNAME_REVISION_DELIMITER
+            + "(.+)\\)(.+)$");
+    private static final Pattern QNAME_PATTERN_NO_REVISION = Pattern.compile("^\\((.+)\\)(.+)$");
+    private static final Pattern QNAME_PATTERN_NO_NAMESPACE_NO_REVISION = Pattern.compile("^(.+)$");
 
-    private static final char[] ILLEGAL_CHARACTERS = new char[] {'?', '(', ')', '&'};
+    private static final char[] ILLEGAL_CHARACTERS = new char[] { '?', '(', ')', '&' };
 
-    //Mandatory
+    // Mandatory
     private final QNameModule module;
-    //Mandatory
+    // Mandatory
     private final String localName;
-    //Nullable
+    // Nullable
     private final String prefix;
 
+    private QName(final QNameModule module, final String prefix, final String localName) {
+        this.localName = checkLocalName(localName);
+        this.prefix = prefix;
+        this.module = module;
+    }
+
     /**
      * QName Constructor.
      *
@@ -74,11 +82,10 @@ public final class QName implements Immutable, Serializable, Comparable<QName> {
      *            locally defined prefix assigned to local name
      * @param localName
      *            YANG schema identifier
+     *
      */
     public QName(final URI namespace, final Date revision, final String prefix, final String localName) {
-        this.localName = checkLocalName(localName);
-        this.prefix = prefix;
-        this.module = QNameModule.create(namespace, revision);
+        this(QNameModule.create(namespace, revision), prefix, localName);
     }
 
     /**
@@ -101,11 +108,10 @@ public final class QName implements Immutable, Serializable, Comparable<QName> {
             throw new IllegalArgumentException("Parameter 'localName' must be a non-empty string.");
         }
 
-        for (char c: ILLEGAL_CHARACTERS) {
+        for (char c : ILLEGAL_CHARACTERS) {
             if (localName.indexOf(c) != -1) {
                 throw new IllegalArgumentException(String.format(
-                        "Parameter 'localName':'%s' contains illegal character '%s'",
-                        localName, c));
+                        "Parameter 'localName':'%s' contains illegal character '%s'", localName, c));
             }
         }
         return localName;
@@ -120,18 +126,30 @@ public final class QName implements Immutable, Serializable, Comparable<QName> {
      *            the revision of the YANG module
      * @param localName
      *            YANG schema identifier
+     *
+     * @deprecated Use {@link #create(URI, Date, String)} instead.
      */
+    @Deprecated
     public QName(final URI namespace, final Date revision, final String localName) {
-        this(namespace, revision, null, localName);
+        this(QNameModule.create(namespace, revision), null, localName);
     }
 
+    /**
+     * Construct new QName which reuses namespace, revision and prefix from
+     * base.
+     *
+     * @param base
+     * @param localName
+     * @deprecated Use {@link #create(QName, String)} instead.
+     */
+    @Deprecated
     public QName(final QName base, final String localName) {
         this(base.getNamespace(), base.getRevision(), base.getPrefix(), localName);
     }
 
     /**
-     * @deprecated Use {@link #create(String)} instead.
-     * This implementation is broken.
+     * @deprecated Use {@link #create(String)} instead. This implementation is
+     *             broken.
      */
     @Deprecated
     public QName(final String input) throws ParseException {
@@ -169,7 +187,7 @@ public final class QName implements Immutable, Serializable, Comparable<QName> {
         matcher = QNAME_PATTERN_NO_NAMESPACE_NO_REVISION.matcher(input);
         if (matcher.matches()) {
             String localName = matcher.group(1);
-            return new QName((URI)null, localName);
+            return new QName((URI) null, localName);
         }
         throw new IllegalArgumentException("Invalid input:" + input);
     }
@@ -224,6 +242,17 @@ public final class QName implements Immutable, Serializable, Comparable<QName> {
         return result;
     }
 
+    /**
+     *
+     * Compares the specified object with this list for equality.  Returns
+     * <tt>true</tt> if and only if the specified object is also instance of
+     * {@link QName} and its {@link #getLocalName()}, {@link #getNamespace()} and
+     * {@link #getRevision()} are equals to same properties of this instance.
+     *
+     * @param o the object to be compared for equality with this QName
+     * @return <tt>true</tt> if the specified object is equal to this QName
+     *
+     */
     @Override
     public boolean equals(final Object obj) {
         if (this == obj) {
@@ -257,20 +286,48 @@ public final class QName implements Immutable, Serializable, Comparable<QName> {
         return true;
     }
 
-    public static QName create(final QName base, final String localName){
+    public static QName create(final QName base, final String localName) {
         return new QName(base, localName);
     }
 
-    public static QName create(final URI namespace, final Date revision, final String localName){
-        return new QName(namespace, revision, localName);
+    /**
+     *
+     * Creates new QName.
+     *
+     * @param namespace Namespace of QName or null if namespace is undefined.
+     * @param revision Revision of namespace or null if revision is unspecified.
+     * @param localName Local name part of QName. MUST NOT BE null.
+     * @return Instance of QName
+     */
+    public static QName create(final URI namespace, final Date revision, final String localName) {
+        return new QName(QNameModule.create(namespace, revision), null,localName);
     }
 
-
-    public static QName create(final String namespace, final String revision, final String localName) throws IllegalArgumentException{
+    /**
+     *
+     * Creates new QName.
+     *
+     * @param namespace
+     *            Namespace of QName, MUST NOT BE Null.
+     * @param revision
+     *            Revision of namespace / YANG module. MUST NOT BE null, MUST BE
+     *            in format <code>YYYY-mm-dd</code>.
+     * @param localName
+     *            Local name part of QName. MUST NOT BE null.
+     * @return
+     * @throws NullPointerException
+     *             If any of paramaters is null.
+     * @throws IllegalArgumentException
+     *             If <code>namespace</code> is not valid URI or
+     *             <code>revision</code> is not according to format
+     *             <code>YYYY-mm-dd</code>.
+     */
+    public static QName create(final String namespace, final String revision, final String localName)
+            throws IllegalArgumentException {
         final URI namespaceUri;
         try {
             namespaceUri = new URI(namespace);
-        }  catch (URISyntaxException ue) {
+        } catch (URISyntaxException ue) {
             throw new IllegalArgumentException(String.format("Namespace '%s' is not a valid URI", namespace), ue);
         }
 
@@ -293,10 +350,26 @@ public final class QName implements Immutable, Serializable, Comparable<QName> {
         return sb.toString();
     }
 
+    /**
+     * Return string representation of revision in format
+     * <code>YYYY-mm-dd</code>
+     *
+     * YANG Specification defines format for <code>revision</code> as
+     * YYYY-mm-dd. This format for revision is reused accross multiple places
+     * such as capabilities URI, YANG modules, etc.
+     *
+     * @return String representation of revision or null, if revision is not
+     *         set.
+     */
     public String getFormattedRevision() {
         return module.getFormattedRevision();
     }
 
+    /**
+     * Creates copy of this with revision and prefix unset.
+     *
+     * @return copy of this QName with revision and prefix unset.
+     */
     public QName withoutRevision() {
         return QName.create(getNamespace(), null, localName);
     }
@@ -304,18 +377,46 @@ public final class QName implements Immutable, Serializable, Comparable<QName> {
     public static Date parseRevision(final String formatedDate) {
         try {
             return getRevisionFormat().parse(formatedDate);
-        } catch (ParseException| RuntimeException e) {
-            throw new IllegalArgumentException(String.format("Revision '%s'is not in a supported format", formatedDate), e);
+        } catch (ParseException | RuntimeException e) {
+            throw new IllegalArgumentException(
+                    String.format("Revision '%s'is not in a supported format", formatedDate), e);
         }
     }
 
+    /**
+     * Formats {@link Date} representing revision to format
+     * <code>YYYY-mm-dd</code>
+     *
+     * YANG Specification defines format for <code>revision</code> as
+     * YYYY-mm-dd. This format for revision is reused accross multiple places
+     * such as capabilities URI, YANG modules, etc.
+     *
+     * @param revision
+     *            Date object to format or null
+     * @return String representation or null if the input was null.
+     */
     public static String formattedRevision(final Date revision) {
-        if(revision == null) {
+        if (revision == null) {
             return null;
         }
         return getRevisionFormat().format(revision);
     }
 
+    /**
+     *
+     * Compares this QName to other, without comparing revision.
+     *
+     * Compares instance of this to other instance of QName and returns true if
+     * both instances have equal <code>localName</code> ({@link #getLocalName()}
+     * ) and <code>namespace</code> ({@link #getNamespace()}).
+     *
+     * @param other
+     *            Other QName. Must not be null.
+     * @return true if this instance and other have equals localName and
+     *         namespace.
+     * @throws NullPointerException
+     *             if <code>other</code> is null.
+     */
     public boolean isEqualWithoutRevision(final QName other) {
         return localName.equals(other.getLocalName()) && Objects.equals(getNamespace(), other.getNamespace());
     }
index ba76a274118a19d96d3e460a291b7aa592ddeff6..d207791f2a64a68ff2aca14a5f4660427f3ed0ef 100644 (file)
@@ -7,19 +7,87 @@
  */
 package org.opendaylight.yangtools.yang.common;
 
+/**
+ *
+ * Representation of Error in YANG enabled system.
+ *
+ * Which may be send / received by YANG modeled / enabled systems.
+ *
+ */
 public interface RpcError {
+
+    /**
+     *
+     * Returns error severity, as determined by component reporting the error.
+     *
+     * @return error severity
+     */
     ErrorSeverity getSeverity();
 
+    /**
+     *
+     * Returns a string identifying the error condition.
+     *
+     * @return string identifying the error condition.
+     */
     String getTag();
 
+    /**
+     *
+     * Returns a string identifying the data-model-specific or
+     * implementation-specific error condition, if one exists. This element will
+     * not be present if no appropriate application error-tag can be associated
+     * with a particular error condition. If a data-model-specific and an
+     * implementation-specific error-app-tag both exist, then the
+     * data-model-specific value MUST be used by the reporter.
+     *
+     * @return Returns a string identifying the data-model-specific or
+     *         implementation-specific error condition, or null if does not
+     *         exists.
+     */
     String getApplicationTag();
 
+    /**
+     *
+     * Returns a string suitable for human display that describes the error
+     * condition. This element will not be present if no appropriate message is
+     * provided for a particular error condition.
+     *
+     * @return returns an error description for human display.
+     */
     String getMessage();
 
+    /**
+     *
+     * Contains protocol- or data-model-specific error content. This value may
+     * be not be present if no such error content is provided for a particular
+     * error condition.
+     *
+     * The list in Appendix A defines any mandatory error-info content for each
+     * error. After any protocol-mandated content, a data model definition MAY
+     * mandate that certain application-layer error information be included in
+     * the error-info container.
+     *
+     * An implementation MAY include additional information to provide extended
+     * and/or implementation- specific debugging information.
+     *
+     * @return
+     */
     String getInfo();
-    
+
+    /**
+     *
+     * Return a cause if available.
+     *
+     * @return cause of this error, if error was triggered by exception.
+     */
     Throwable getCause();
-    
+
+    /**
+     * Returns the conceptual layer that on which the error occurred.
+     *
+     * @return the conceptual layer that on which the error occurred.
+     */
     ErrorType getErrorType();
 
     public enum ErrorSeverity {
index dc697f517802e7e06263af4931d63c5c66ce245e..4cc40822336ac7c50bb64de9edffc64e70984458 100644 (file)
@@ -9,10 +9,37 @@ package org.opendaylight.yangtools.yang.common;
 
 import java.util.Collection;
 
+/**
+ *
+ * Result of call to YANG enabled system.
+ *
+ *
+ * @param <T> Return type
+ */
 public interface RpcResult<T> {
+
+    /**
+     * True if processing of request was successful
+     *
+     * @return true if processing was successful.
+     */
     boolean isSuccessful();
 
+    /**
+     *
+     * Returns result of call or null if no result is available.
+     *
+     * @return result of call or null if no result is available.
+     *
+     */
     T getResult();
 
+    /**
+     *
+     * Returns set of errors and warnings which occured during processing
+     * the request.
+     *
+     * @return
+     */
     Collection<RpcError> getErrors();
 }
index 3be2ad3f659551fcf9e7206f9defaa6b9e8b979b..dd492c6b9657cd26a1b529851520c4fc875796ce 100644 (file)
           <groupId>org.opendaylight.yangtools</groupId>
           <artifactId>yang-model-api</artifactId>
         </dependency>
+        <dependency>
+          <groupId>junit</groupId>
+          <artifactId>junit</artifactId>
+          <scope>test</scope>
+        </dependency>
     </dependencies>
 </project>
index 951e27f743dfb7d16883b6255da1f7116e6b7c59..c3af9052ec1917f5032a32a39067256ed3a547c2 100644 (file)
@@ -8,8 +8,12 @@
 package org.opendaylight.yangtools.yang.data.api;
 
 import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
 import java.util.Set;
 
 import org.opendaylight.yangtools.concepts.Builder;
@@ -120,6 +124,28 @@ public class InstanceIdentifier implements Path<InstanceIdentifier>, Immutable,
         }
     }
 
+    static int hashCode( Object value ) {
+        if( value == null ) {
+            return 0;
+        }
+
+        if( value.getClass().equals( byte[].class ) ) {
+            return Arrays.hashCode( (byte[])value );
+        }
+
+        if( value.getClass().isArray() ) {
+            int hash = 0;
+            int length = Array.getLength( value );
+            for( int i = 0; i < length; i++ ) {
+                hash += Objects.hashCode( Array.get( value, i ) );
+            }
+
+            return hash;
+        }
+
+        return Objects.hashCode( value );
+    }
+
     // Static factories & helpers
 
     public static InstanceIdentifier of(final QName name) {
@@ -227,8 +253,7 @@ public class InstanceIdentifier implements Path<InstanceIdentifier>, Immutable,
         }
 
         public NodeIdentifierWithPredicates(final QName node, final QName key, final Object value) {
-            this.nodeType = node;
-            this.keyValues = ImmutableMap.of(key, value);
+            this( node, ImmutableMap.of(key, value) );
         }
 
         @Override
@@ -244,11 +269,20 @@ public class InstanceIdentifier implements Path<InstanceIdentifier>, Immutable,
         public int hashCode() {
             final int prime = 31;
             int result = 1;
-            result = prime * result + ((keyValues == null) ? 0 : keyValues.hashCode());
+            result = prime * result + ((keyValues == null) ? 0 : hashKeyValues());
             result = prime * result + ((nodeType == null) ? 0 : nodeType.hashCode());
             return result;
         }
 
+        private int hashKeyValues() {
+            int hash = 0;
+            for( Entry<QName,Object> entry: keyValues.entrySet() ) {
+                hash += Objects.hashCode( entry.getKey() ) + InstanceIdentifier.hashCode( entry.getValue() );
+            }
+
+            return hash;
+        }
+
         @Override
         public boolean equals(final Object obj) {
             if (this == obj) {
@@ -265,7 +299,7 @@ public class InstanceIdentifier implements Path<InstanceIdentifier>, Immutable,
                 if (other.keyValues != null) {
                     return false;
                 }
-            } else if (!keyValues.equals(other.keyValues)) {
+            } else if (!keyValuesEquals(other.keyValues)) {
                 return false;
             }
             if (nodeType == null) {
@@ -278,6 +312,24 @@ public class InstanceIdentifier implements Path<InstanceIdentifier>, Immutable,
             return true;
         }
 
+        private boolean keyValuesEquals( Map<QName, Object> otherKeyValues ) {
+            if( otherKeyValues == null || keyValues.size() != otherKeyValues.size() ) {
+                return false;
+            }
+
+            boolean result = true;
+            for( Entry<QName,Object> entry: keyValues.entrySet() ) {
+                if( !otherKeyValues.containsKey( entry.getKey() ) ||
+                    !Objects.deepEquals( entry.getValue(), otherKeyValues.get( entry.getKey() ) ) ) {
+
+                    result = false;
+                    break;
+                }
+            }
+
+            return result;
+        }
+
         @Override
         public String toString() {
             return nodeType + "[" + keyValues + "]";
@@ -312,7 +364,7 @@ public class InstanceIdentifier implements Path<InstanceIdentifier>, Immutable,
         public int hashCode() {
             final int prime = 31;
             int result = 1;
-            result = prime * result + ((value == null) ? 0 : value.hashCode());
+            result = prime * result + ((value == null) ? 0 : InstanceIdentifier.hashCode( value ) );
             result = prime * result + ((nodeType == null) ? 0 : nodeType.hashCode());
             return result;
         }
@@ -329,21 +381,7 @@ public class InstanceIdentifier implements Path<InstanceIdentifier>, Immutable,
                 return false;
             }
             NodeWithValue other = (NodeWithValue) obj;
-            if (value == null) {
-                if (other.value != null) {
-                    return false;
-                }
-            } else if (!value.equals(other.value)) {
-                return false;
-            }
-            if (nodeType == null) {
-                if (other.nodeType != null) {
-                    return false;
-                }
-            } else if (!nodeType.equals(other.nodeType)) {
-                return false;
-            }
-            return true;
+            return Objects.deepEquals(value, other.value) && Objects.equals(nodeType, other.nodeType);
         }
 
         @Override
diff --git a/yang/yang-data-api/src/test/java/org/opendaylight/yangtools/yang/data/api/InstanceIdentifierTest.java b/yang/yang-data-api/src/test/java/org/opendaylight/yangtools/yang/data/api/InstanceIdentifierTest.java
new file mode 100644 (file)
index 0000000..827e4f3
--- /dev/null
@@ -0,0 +1,302 @@
+/*
+ * Copyright (c) 2014 Brocade Communications 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.api;
+
+import static org.junit.Assert.*;
+import static org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
+
+import java.util.Collections;
+import java.util.Map.Entry;
+
+import org.junit.Test;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeWithValue;
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+/**
+ * Unit tests for InstanceIdentifier.
+ *
+ * @author Thomas Pantelis
+ */
+public class InstanceIdentifierTest {
+
+    static QName nodeName1 = QName.create("test", "2014-5-28", "node1");
+    static QName nodeName2 = QName.create("test", "2014-5-28", "node2");
+    static QName nodeName3 = QName.create("test", "2014-5-28", "node3");
+    static QName nodeName4 = QName.create("test", "2014-5-28", "node4");
+    static QName key1 = QName.create("test", "2014-5-28", "key1");
+    static QName key2 = QName.create("test", "2014-5-28", "key2");
+    static QName key3 = QName.create("test", "2014-5-28", "key3");
+
+    @Test
+    public void testHashCodeEquals() {
+
+        InstanceIdentifier id1 = new InstanceIdentifier(
+                Lists.newArrayList(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName2)));
+        InstanceIdentifier id2 = new InstanceIdentifier(
+                Lists.newArrayList(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName2)));
+        InstanceIdentifier id3 = new InstanceIdentifier(
+                Lists.newArrayList(new NodeIdentifier(nodeName2), new NodeIdentifier(nodeName1)));
+        InstanceIdentifier id4 = new InstanceIdentifier(
+                Lists.newArrayList(new NodeIdentifier(nodeName1)));
+
+        assertEquals( "hashCode", id1.hashCode(), id2.hashCode() );
+        assertEquals( "equals", true, id1.equals( id2 ) );
+
+        assertEquals( "equals", false, id1.equals( id3 ) );
+        assertEquals( "equals", false, id1.equals( id4 ) );
+        assertEquals( "equals", false, id1.equals( new Object() ) );
+    }
+
+    @Test
+    public void testNode() {
+
+        InstanceIdentifier id = new InstanceIdentifier(
+                Lists.newArrayList(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName2)));
+
+        InstanceIdentifier newID = id.node( nodeName3 );
+
+        assertNotNull( "InstanceIdentifier is null", newID );
+        assertEquals( "Path size", 3, newID.getPath().size() );
+        assertEquals( "PathArg 1 node type", nodeName1, newID.getPath().get(0).getNodeType() );
+        assertEquals( "PathArg 2 node type", nodeName2, newID.getPath().get(1).getNodeType() );
+        assertEquals( "PathArg 3 node type", nodeName3, newID.getPath().get(2).getNodeType() );
+
+        newID = id.node( new NodeIdentifier( nodeName3 ) );
+
+        assertNotNull( "InstanceIdentifier is null", newID );
+        assertEquals( "Path size", 3, newID.getPath().size() );
+        assertEquals( "PathArg 1 node type", nodeName1, newID.getPath().get(0).getNodeType() );
+        assertEquals( "PathArg 2 node type", nodeName2, newID.getPath().get(1).getNodeType() );
+        assertEquals( "PathArg 3 node type", nodeName3, newID.getPath().get(2).getNodeType() );
+    }
+
+    @Test
+    public void testRelativeTo() {
+
+        InstanceIdentifier id1 = new InstanceIdentifier(
+                Lists.newArrayList(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName2),
+                                   new NodeIdentifier(nodeName3), new NodeIdentifier(nodeName4)));
+        InstanceIdentifier id2 = new InstanceIdentifier(
+                Lists.newArrayList(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName2)));
+        InstanceIdentifier id3 = new InstanceIdentifier(
+                Lists.newArrayList(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName2)));
+
+        Optional<InstanceIdentifier> relative = id1.relativeTo( id2 );
+
+        assertEquals( "isPresent", true, relative.isPresent() );
+        assertEquals( "Path size", 2, relative.get().getPath().size() );
+        assertEquals( "PathArg 1 node type", nodeName3, relative.get().getPath().get(0).getNodeType() );
+        assertEquals( "PathArg 2 node type", nodeName4, relative.get().getPath().get(1).getNodeType() );
+
+        relative = id2.relativeTo( id3 );
+        assertEquals( "isPresent", true, relative.isPresent() );
+        assertEquals( "Path size", 0, relative.get().getPath().size() );
+
+        relative = id2.relativeTo( id1 );
+        assertEquals( "isPresent", false, relative.isPresent() );
+    }
+
+    @Test
+    public void testContains() {
+
+        InstanceIdentifier id1 = new InstanceIdentifier(
+                Lists.newArrayList(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName2),
+                                   new NodeIdentifier(nodeName3), new NodeIdentifier(nodeName4)));
+        InstanceIdentifier id2 = new InstanceIdentifier(
+                Lists.newArrayList(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName2)));
+        InstanceIdentifier id3 = new InstanceIdentifier(
+                Lists.newArrayList(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName2)));
+        InstanceIdentifier id4 = new InstanceIdentifier(
+                Lists.newArrayList(new NodeIdentifier(nodeName1), new NodeIdentifier(nodeName3)));
+
+        assertEquals( "contains", true, id2.contains( id1 ) );
+        assertEquals( "contains", true, id2.contains( id3 ) );
+        assertEquals( "contains", false, id1.contains( id2 ) );
+        assertEquals( "contains", false, id2.contains( id4 ) );
+    }
+
+    @Test
+    public void testOf() {
+
+        InstanceIdentifier newID = InstanceIdentifier.of( nodeName1 );
+
+        assertNotNull( "InstanceIdentifier is null", newID );
+        assertEquals( "Path size", 1, newID.getPath().size() );
+        assertEquals( "PathArg 1 node type", nodeName1, newID.getPath().get(0).getNodeType() );
+
+        assertNotNull( newID.toString() ); // for code coverage
+    }
+
+    @Test
+    public void testBuilder() {
+
+        InstanceIdentifier newID = InstanceIdentifier.builder()
+                .node( nodeName1 )
+                .nodeWithKey( nodeName2, Collections.<QName,Object>singletonMap( key1, "foo" ) )
+                .nodeWithKey( nodeName3, key2, "bar" ).build();
+
+        assertNotNull( "InstanceIdentifier is null", newID );
+        assertEquals( "Path size", 3, newID.getPath().size() );
+        assertEquals( "PathArg 1 node type", nodeName1, newID.getPath().get(0).getNodeType() );
+        verifyNodeIdentifierWithPredicates( "PathArg 2", newID.getPath().get(1), nodeName2, key1, "foo" );
+        verifyNodeIdentifierWithPredicates( "PathArg 3", newID.getPath().get(2), nodeName3, key2, "bar" );
+
+        newID = InstanceIdentifier.builder( newID ).node( nodeName4 ).build();
+
+        assertNotNull( "InstanceIdentifier is null", newID );
+        assertEquals( "Path size", 4, newID.getPath().size() );
+        assertEquals( "PathArg 1 node type", nodeName1, newID.getPath().get(0).getNodeType() );
+        assertEquals( "PathArg 2 node type", nodeName2, newID.getPath().get(1).getNodeType() );
+        assertEquals( "PathArg 3 node type", nodeName3, newID.getPath().get(2).getNodeType() );
+        assertEquals( "PathArg 4 node type", nodeName4, newID.getPath().get(3).getNodeType() );
+
+        newID = InstanceIdentifier.builder( nodeName1 ).build();
+
+        assertNotNull( "InstanceIdentifier is null", newID );
+        assertEquals( "Path size", 1, newID.getPath().size() );
+        assertEquals( "PathArg 1 node type", nodeName1, newID.getPath().get(0).getNodeType() );
+    }
+
+    private void verifyNodeIdentifierWithPredicates(String prefix,
+                               PathArgument arg, QName nodeName, QName key, Object value ) {
+
+        assertNotNull( prefix + " is null", arg );
+        assertEquals( prefix + " class", NodeIdentifierWithPredicates.class, arg.getClass() );
+        NodeIdentifierWithPredicates node = (NodeIdentifierWithPredicates)arg;
+        assertEquals( prefix + " node type", nodeName, node.getNodeType() );
+        assertEquals( prefix + " key values map size", 1, node.getKeyValues().size() );
+        Entry<QName, Object> entry = node.getKeyValues().entrySet().iterator().next();
+        assertEquals( prefix + " key values map entry key", key, entry.getKey() );
+        assertEquals( prefix + " key values map entry value", value, entry.getValue() );
+    }
+
+    @Test
+    public void testNodeIdentifierWithPredicates() {
+
+        NodeIdentifierWithPredicates node1 = new NodeIdentifierWithPredicates( nodeName1, key1, "foo" );
+        verifyNodeIdentifierWithPredicates( "NodeIdentifierWithPredicates", node1, nodeName1, key1, "foo" );
+
+        NodeIdentifierWithPredicates node2 = new NodeIdentifierWithPredicates( nodeName1, key1, "foo" );
+
+        assertEquals( "hashCode", node1.hashCode(), node2.hashCode() );
+        assertEquals( "equals", true, node1.equals( node2 ) );
+
+        assertEquals( "equals", false,
+                      node1.equals( new NodeIdentifierWithPredicates( nodeName2, key1, "foo" ) ) );
+        assertEquals( "equals", false,
+                      node1.equals( new NodeIdentifierWithPredicates( nodeName1, key2, "foo" ) ) );
+        assertEquals( "equals", false,
+                      node1.equals( new NodeIdentifierWithPredicates( nodeName1, key1, "bar" ) ) );
+        assertEquals( "equals", false, node1.equals( new Object() ) );
+
+        assertNotNull( node1.toString() ); // for code coverage
+
+        NodeIdentifierWithPredicates node3 = new NodeIdentifierWithPredicates( nodeName1,
+                ImmutableMap.<QName, Object>builder().put( key1, 10 ).put( key2, 20 ).build() );
+
+        NodeIdentifierWithPredicates node4 = new NodeIdentifierWithPredicates( nodeName1,
+                ImmutableMap.<QName, Object>builder().put( key1, 10 ).put( key2, 20 ).build() );
+
+        assertEquals( "hashCode", node3.hashCode(), node4.hashCode() );
+        assertEquals( "equals", true, node3.equals( node4 ) );
+
+        assertEquals( "equals", false, node3.equals( node1 ) );
+        assertEquals( "equals", false,
+                      node1.equals( new NodeIdentifierWithPredicates( nodeName1,
+                          ImmutableMap.<QName, Object>builder().put( key1, 10 ).put( key3, 20 ).build() ) ) );
+
+        node1 = new NodeIdentifierWithPredicates( nodeName1, key1, new byte[]{1,2} );
+        node2 = new NodeIdentifierWithPredicates( nodeName1, key1, new byte[]{1,2} );
+
+        assertEquals( "hashCode", node1.hashCode(), node2.hashCode() );
+        assertEquals( "equals", true, node1.equals( node2 ) );
+
+        assertEquals( "equals", false,
+                      node1.equals( new NodeIdentifierWithPredicates( nodeName1, key1, new byte[]{1,3} ) ) );
+        assertEquals( "equals", false,
+                      node1.equals( new NodeIdentifierWithPredicates( nodeName1, key1, new byte[]{1} ) ) );
+        assertEquals( "equals", false,
+                      node1.equals( new NodeIdentifierWithPredicates( nodeName1, key1, new byte[]{1,2,3} ) ) );
+    }
+
+    @Test
+    public void testNodeWithValue() {
+
+        NodeWithValue node1 = new NodeWithValue( nodeName1, "foo" );
+        assertEquals( "getNodeType", nodeName1, node1.getNodeType() );
+        assertEquals( "getValue", "foo", node1.getValue() );
+
+        NodeWithValue node2 = new NodeWithValue( nodeName1, "foo" );
+
+        assertEquals( "hashCode", node1.hashCode(), node2.hashCode() );
+        assertEquals( "equals", true, node1.equals( node2 ) );
+
+        assertEquals( "equals", false, node1.equals( new NodeWithValue( nodeName1, "bar" ) ) );
+        assertEquals( "equals", false, node1.equals( new NodeWithValue( nodeName2, "foo" ) ) );
+        assertEquals( "equals", false, node1.equals( new Object() ) );
+
+        assertNotNull( node1.toString() ); // for code coverage
+
+        NodeWithValue node3 = new NodeWithValue( nodeName1, new byte[]{1,2} );
+        NodeWithValue node4 = new NodeWithValue( nodeName1, new byte[]{1,2} );
+
+        assertEquals( "hashCode", node3.hashCode(), node4.hashCode() );
+        assertEquals( "equals", true, node3.equals( node4 ) );
+
+        assertEquals( "equals", false, node3.equals( new NodeWithValue( nodeName1, new byte[]{1,3} ) ) );
+        assertEquals( "equals", false, node3.equals( node1 ) );
+    }
+
+    @Test
+    public void testNodeIdentifier() {
+
+        NodeIdentifier node1 = new NodeIdentifier( nodeName1 );
+        assertEquals( "getNodeType", nodeName1, node1.getNodeType() );
+
+        NodeIdentifier node2 = new NodeIdentifier( nodeName1 );
+
+        assertEquals( "hashCode", node1.hashCode(), node2.hashCode() );
+        assertEquals( "equals", true, node1.equals( node2 ) );
+        assertEquals( "compareTo", 0, node1.compareTo( node2 ) );
+
+        assertEquals( "equals", false, node1.equals( new NodeIdentifier( nodeName3 ) ) );
+        assertEquals( "compareTo", true, node1.compareTo( new NodeIdentifier( nodeName3 ) ) != 0 );
+        assertEquals( "equals", false, node1.equals( new Object() ) );
+
+        assertNotNull( node1.toString() ); // for code coverage
+    }
+
+    @Test
+    public void testAugmentationIdentifier() {
+
+        AugmentationIdentifier node1 = new AugmentationIdentifier( Sets.newHashSet( nodeName1, nodeName2 ) );
+        assertEquals( "getPossibleChildNames", Sets.newHashSet( nodeName1, nodeName2 ), node1.getPossibleChildNames() );
+
+        AugmentationIdentifier node2 = new AugmentationIdentifier( Sets.newHashSet( nodeName2, nodeName1 ) );
+
+        assertEquals( "hashCode", node1.hashCode(), node2.hashCode() );
+        assertEquals( "equals", true, node1.equals( node2 ) );
+
+        assertEquals( "equals", false,
+                      node1.equals( new AugmentationIdentifier( Sets.newHashSet( nodeName1, nodeName3 ) ) ) );
+        assertEquals( "equals", false,
+                      node1.equals( new AugmentationIdentifier( Sets.newHashSet( nodeName1 ) ) ) );
+        assertEquals( "equals", false, node1.equals( new Object() ) );
+
+        assertNotNull( node1.toString() ); // for code coverage
+    }
+}
index 013bbcc357a2b9974c5915c0705c698172c88b9b..538195109bda19c52cc31fe90d9441269cdf1bae 100644 (file)
     </build>
 
     <dependencies>
+        <dependency>
+            <groupId>${project.groupId}</groupId>
+            <artifactId>util</artifactId>
+        </dependency>
         <dependency>
             <groupId>${project.groupId}</groupId>
             <artifactId>yang-common</artifactId>
index dfb02c5d5f5834b64ab5fd8086b3939e468a9456..00e06f80e6dff5a3f2113cd6517dc0128af4a0f3 100644 (file)
@@ -351,7 +351,7 @@ public abstract class TypeDefinitionAwareCodec<J, T extends TypeDefinition<T>> i
 
         @Override
         public String deserialize(String stringRepresentation) {
-            return stringRepresentation;
+            return stringRepresentation == null ? "" :stringRepresentation;
         }
 
         @Override
index 7b180f96651a8e81aacfc848f3d8364ea67b2da5..f8bf77967ff49a6ce1884a9362eaf084ad20c760 100644 (file)
@@ -176,7 +176,7 @@ public class XmlDocumentUtils {
         } else { // CompositeNode
             for (Node<?> child : ((CompositeNode) data).getValue()) {
                 DataSchemaNode childSchema = null;
-                if (schema != null) {
+                if (schema instanceof DataNodeContainer) {
                     childSchema = findFirstSchemaForNode(child, ((DataNodeContainer) schema).getChildNodes());
                     if (logger.isDebugEnabled()) {
                         if (childSchema == null) {
index fcec7afc214a5967d3c7099e76c3b7fee50cd8f3..a127bc5e0b467fe472c6ea93a4a8f2ec3585478a 100644 (file)
@@ -13,7 +13,7 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeAttrBuilder;
-import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedAttrNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedValueAttrNode;
 
 public class ImmutableLeafNodeBuilder<T> extends AbstractImmutableNormalizedNodeBuilder<InstanceIdentifier.NodeIdentifier, T, LeafNode<T>> {
 
@@ -26,7 +26,7 @@ public class ImmutableLeafNodeBuilder<T> extends AbstractImmutableNormalizedNode
         return new ImmutableLeafNode<>(getNodeIdentifier(), getValue(), getAttributes());
     }
 
-    private static final class ImmutableLeafNode<T> extends AbstractImmutableNormalizedAttrNode<InstanceIdentifier.NodeIdentifier, T> implements LeafNode<T> {
+    private static final class ImmutableLeafNode<T> extends AbstractImmutableNormalizedValueAttrNode<InstanceIdentifier.NodeIdentifier, T> implements LeafNode<T> {
 
         ImmutableLeafNode(final InstanceIdentifier.NodeIdentifier nodeIdentifier, final T value, final Map<QName, String> attributes) {
             super(nodeIdentifier, value, attributes);
index fd5cf52678ecd92f248c0d8493ca3a2579187e68..ba351f13481c7491c963f5063dc6ed17931d2b5c 100644 (file)
@@ -12,7 +12,7 @@ import java.util.Map;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
-import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedAttrNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.nodes.AbstractImmutableNormalizedValueAttrNode;
 
 import com.google.common.base.Preconditions;
 
@@ -27,7 +27,7 @@ public class ImmutableLeafSetEntryNodeBuilder<T> extends AbstractImmutableNormal
         return new ImmutableLeafSetEntryNode<>(getNodeIdentifier(), getValue(), getAttributes());
     }
 
-    private static final class ImmutableLeafSetEntryNode<T> extends AbstractImmutableNormalizedAttrNode<InstanceIdentifier.NodeWithValue, T> implements LeafSetEntryNode<T> {
+    private static final class ImmutableLeafSetEntryNode<T> extends AbstractImmutableNormalizedValueAttrNode<InstanceIdentifier.NodeWithValue, T> implements LeafSetEntryNode<T> {
 
         ImmutableLeafSetEntryNode(final InstanceIdentifier.NodeWithValue nodeIdentifier, final T value, final Map<QName, String> attributes) {
             super(nodeIdentifier, value, attributes);
index dfc6be4a18a65246d3c32b2a180536e4dd644b86..6d04d5989cd41cb2a965425a2a1ec6f01b5e7f55 100644 (file)
@@ -8,11 +8,12 @@
 package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
 
 import java.util.Collections;
-import java.util.LinkedHashMap;
+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;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
@@ -22,25 +23,23 @@ import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.ListNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
 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 Map<InstanceIdentifier.NodeWithValue, LeafSetEntryNode<T>> value;
+    private final Map<InstanceIdentifier.NodeWithValue, LeafSetEntryNode<T>> value;
     private InstanceIdentifier.NodeIdentifier nodeIdentifier;
-    private boolean dirty;
 
     protected ImmutableLeafSetNodeBuilder() {
-        value = new LinkedHashMap<>();
-        dirty = false;
+        value = new HashMap<>();
     }
 
     protected ImmutableLeafSetNodeBuilder(final ImmutableLeafSetNode<T> node) {
         nodeIdentifier = node.getIdentifier();
-        value = node.getChildren();
-        dirty = true;
+        value = MapAdaptor.getDefaultInstance().takeSnapshot(node.children);
     }
 
     public static <T> ListNodeBuilder<T, LeafSetEntryNode<T>> create() {
@@ -55,31 +54,21 @@ public class ImmutableLeafSetNodeBuilder<T> implements ListNodeBuilder<T, LeafSe
         return new ImmutableLeafSetNodeBuilder<T>((ImmutableLeafSetNode<T>) node);
     }
 
-    private void checkDirty() {
-        if (dirty) {
-            value = new LinkedHashMap<>(value);
-            dirty = false;
-        }
-    }
-
     @Override
     public ListNodeBuilder<T, LeafSetEntryNode<T>> withChild(final LeafSetEntryNode<T> child) {
-        checkDirty();
         this.value.put(child.getIdentifier(), child);
         return this;
     }
 
     @Override
     public ListNodeBuilder<T, LeafSetEntryNode<T>> withoutChild(final PathArgument key) {
-        checkDirty();
         this.value.remove(key);
         return this;
     }
 
     @Override
     public LeafSetNode<T> build() {
-        dirty = true;
-        return new ImmutableLeafSetNode<>(nodeIdentifier, value);
+        return new ImmutableLeafSetNode<>(nodeIdentifier, MapAdaptor.getDefaultInstance().optimize(value));
     }
 
     @Override
@@ -91,7 +80,6 @@ public class ImmutableLeafSetNodeBuilder<T> implements ListNodeBuilder<T, LeafSe
 
     @Override
     public ListNodeBuilder<T, LeafSetEntryNode<T>> withValue(final List<LeafSetEntryNode<T>> value) {
-        checkDirty();
         for (final LeafSetEntryNode<T> leafSetEntry : value) {
             withChild(leafSetEntry);
         }
@@ -114,7 +102,7 @@ public class ImmutableLeafSetNodeBuilder<T> implements ListNodeBuilder<T, LeafSe
     }
 
     protected final static class ImmutableLeafSetNode<T> extends
-            AbstractImmutableNormalizedNode<InstanceIdentifier.NodeIdentifier, Iterable<LeafSetEntryNode<T>>> implements
+            AbstractImmutableNormalizedValueNode<InstanceIdentifier.NodeIdentifier, Iterable<LeafSetEntryNode<T>>> implements
             Immutable, LeafSetNode<T> {
 
         private final Map<InstanceIdentifier.NodeWithValue, LeafSetEntryNode<T>> children;
@@ -135,10 +123,6 @@ public class ImmutableLeafSetNodeBuilder<T> implements ListNodeBuilder<T, LeafSe
             return children.hashCode();
         }
 
-        private Map<InstanceIdentifier.NodeWithValue, LeafSetEntryNode<T>> getChildren() {
-            return Collections.unmodifiableMap(children);
-        }
-
         @Override
         protected boolean valueEquals(final AbstractImmutableNormalizedNode<?, ?> other) {
             return children.equals(((ImmutableLeafSetNode<?>) other).children);
index c7c58e1899942c016bd4f4bc906ae886eaf08e07..4a52f95d3ec12ba201df1d115c323bd02f19097d 100644 (file)
@@ -7,11 +7,12 @@
  */
 package org.opendaylight.yangtools.yang.data.impl.schema.builder.impl;
 
-import java.util.LinkedHashMap;
+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.InstanceIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.NodeIdentifier;
 import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier.PathArgument;
@@ -27,19 +28,16 @@ import com.google.common.collect.Iterables;
 public class ImmutableMapNodeBuilder
         implements CollectionNodeBuilder<MapEntryNode, MapNode> {
 
-    private Map<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> value;
+    private final Map<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> value;
     private InstanceIdentifier.NodeIdentifier nodeIdentifier;
-    private boolean dirty = false;
 
     protected ImmutableMapNodeBuilder() {
-        this.value = new LinkedHashMap<>();
-        this.dirty = false;
+        this.value = new HashMap<>();
     }
 
     protected ImmutableMapNodeBuilder(final ImmutableMapNode node) {
         this.nodeIdentifier = node.getIdentifier();
-        this.value = node.children;
-        this.dirty = true;
+        this.value = MapAdaptor.getDefaultInstance().takeSnapshot(node.children);
     }
 
     public static CollectionNodeBuilder<MapEntryNode, MapNode> create() {
@@ -54,23 +52,14 @@ public class ImmutableMapNodeBuilder
         return new ImmutableMapNodeBuilder((ImmutableMapNode) node);
     }
 
-    private void checkDirty() {
-        if (dirty) {
-            value = new LinkedHashMap<>(value);
-            dirty = false;
-        }
-    }
-
     @Override
     public CollectionNodeBuilder<MapEntryNode, MapNode> withChild(final MapEntryNode child) {
-        checkDirty();
         this.value.put(child.getIdentifier(), child);
         return this;
     }
 
     @Override
     public CollectionNodeBuilder<MapEntryNode, MapNode> withoutChild(final InstanceIdentifier.PathArgument key) {
-        checkDirty();
         this.value.remove(key);
         return this;
     }
@@ -93,8 +82,7 @@ public class ImmutableMapNodeBuilder
 
     @Override
     public MapNode build() {
-        dirty = true;
-        return new ImmutableMapNode(nodeIdentifier, value);
+        return new ImmutableMapNode(nodeIdentifier, MapAdaptor.getDefaultInstance().optimize(value));
     }
 
     @Override
@@ -116,7 +104,7 @@ public class ImmutableMapNodeBuilder
 
         ImmutableMapNode(final InstanceIdentifier.NodeIdentifier nodeIdentifier,
                          final Map<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> children) {
-            super(nodeIdentifier, Iterables.unmodifiableIterable(children.values()));
+            super(nodeIdentifier);
             this.children = children;
         }
 
@@ -125,6 +113,11 @@ public class ImmutableMapNodeBuilder
             return Optional.fromNullable(children.get(child));
         }
 
+               @Override
+               public Iterable<MapEntryNode> getValue() {
+                       return Iterables.unmodifiableIterable(children.values());
+               }
+
         @Override
         protected int valueHashCode() {
             return children.hashCode();
index d66f0228953bf4f171cc2ea41401f5f216d7ac9d..c440bd7f8d747a7adacd89cb1c60e7f04608b529 100644 (file)
@@ -122,7 +122,7 @@ public class ImmutableOrderedLeafSetNodeBuilder<T> implements ListNodeBuilder<T,
 
         ImmutableOrderedLeafSetNode(final InstanceIdentifier.NodeIdentifier nodeIdentifier,
                 final Map<InstanceIdentifier.NodeWithValue, LeafSetEntryNode<T>> children) {
-            super(nodeIdentifier, Iterables.unmodifiableIterable(children.values()));
+            super(nodeIdentifier);
             this.children = children;
         }
 
@@ -155,6 +155,11 @@ public class ImmutableOrderedLeafSetNodeBuilder<T> implements ListNodeBuilder<T,
             // TODO Auto-generated method stub
             return 0;
         }
+
+               @Override
+               public Iterable<LeafSetEntryNode<T>> getValue() {
+                       return Iterables.unmodifiableIterable(children.values());
+               }
     }
 
     @Override
index 3f9e4d5f12ae029b6bd00199baa13c6e219af291..ca0ea95365da2341e3277c5b579e1114b0a86b70 100644 (file)
@@ -116,7 +116,7 @@ public class ImmutableOrderedMapNodeBuilder
 
         ImmutableOrderedMapNode(final InstanceIdentifier.NodeIdentifier nodeIdentifier,
                          final Map<InstanceIdentifier.NodeIdentifierWithPredicates, MapEntryNode> children) {
-            super(nodeIdentifier, Iterables.unmodifiableIterable(children.values()));
+            super(nodeIdentifier);
             this.children = children;
         }
 
@@ -144,5 +144,10 @@ public class ImmutableOrderedMapNodeBuilder
         public int getSize() {
             return children.size();
         }
+
+               @Override
+               public Iterable<MapEntryNode> getValue() {
+                       return Iterables.unmodifiableIterable(children.values());
+               }
     }
 }
index 498b65824599fcf0c48ea91d6f9544a357402c70..274b781d3e66fded64bdf5485dada1f47561c20f 100644 (file)
@@ -19,6 +19,7 @@ import org.opendaylight.yangtools.yang.data.api.schema.UnkeyedListNode;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.CollectionNodeBuilder;
 import org.opendaylight.yangtools.yang.data.impl.schema.builder.api.NormalizedNodeContainerBuilder;
 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;
@@ -109,7 +110,7 @@ public class ImmutableUnkeyedListNodeBuilder implements CollectionNodeBuilder<Un
     }
 
     protected static final class ImmutableUnkeyedListNode extends
-            AbstractImmutableNormalizedNode<InstanceIdentifier.NodeIdentifier, Iterable<UnkeyedListEntryNode>>
+            AbstractImmutableNormalizedValueNode<InstanceIdentifier.NodeIdentifier, Iterable<UnkeyedListEntryNode>>
             implements Immutable, UnkeyedListNode {
 
         private final ImmutableList<UnkeyedListEntryNode> children;
index 7c7d53d61ac210a77bc7a5dc7c7d3e29a5f3b334..438b05c7da3af2bab1424fba7e56b00c80a007e7 100644 (file)
@@ -26,7 +26,7 @@ public abstract class AbstractImmutableDataContainerNode<K extends PathArgument>
 
     public AbstractImmutableDataContainerNode(
             final Map<PathArgument, DataContainerChild<? extends PathArgument, ?>> children, final K nodeIdentifier) {
-        super(nodeIdentifier, Iterables.unmodifiableIterable(children.values()));
+        super(nodeIdentifier);
         this.children = children;
     }
 
@@ -35,6 +35,11 @@ public abstract class AbstractImmutableDataContainerNode<K extends PathArgument>
         return Optional.<DataContainerChild<? extends PathArgument, ?>> fromNullable(children.get(child));
     }
 
+    @Override
+    public final Iterable<DataContainerChild<? extends PathArgument, ?>> getValue() {
+        return Iterables.unmodifiableIterable(children.values());
+    }
+
     @Override
     protected int valueHashCode() {
         return children.hashCode();
index 708f9225c2f29c640db725b4550b2d5386d2a6cf..14b0f419297352315c71d5b2517395fee7e7cfb8 100644 (file)
@@ -21,11 +21,9 @@ public abstract class AbstractImmutableNormalizedNode<K extends InstanceIdentifi
         implements NormalizedNode<K, V>, Immutable {
 
     private final K nodeIdentifier;
-    private final V value;
 
-    protected AbstractImmutableNormalizedNode(final K nodeIdentifier, final V value) {
+    protected AbstractImmutableNormalizedNode(final K nodeIdentifier) {
         this.nodeIdentifier = Preconditions.checkNotNull(nodeIdentifier, "nodeIdentifier");
-        this.value = Preconditions.checkNotNull(value, "value");
     }
 
     @Override
@@ -48,11 +46,6 @@ public abstract class AbstractImmutableNormalizedNode<K extends InstanceIdentifi
         return getNodeType();
     }
 
-    @Override
-    public final V getValue() {
-        return value;
-    }
-
     @Override
     public final V setValue(final V value) {
         throw new UnsupportedOperationException("Immutable");
@@ -16,13 +16,13 @@ import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
 import com.google.common.base.Objects.ToStringHelper;
 import com.google.common.collect.ImmutableMap;
 
-public abstract class AbstractImmutableNormalizedAttrNode<K extends InstanceIdentifier.PathArgument,V>
-        extends AbstractImmutableNormalizedNode<K, V>
+public abstract class AbstractImmutableNormalizedValueAttrNode<K extends InstanceIdentifier.PathArgument,V>
+        extends AbstractImmutableNormalizedValueNode<K, V>
         implements AttributesContainer {
 
     private final Map<QName, String> attributes;
 
-    protected AbstractImmutableNormalizedAttrNode(final K nodeIdentifier, final V value, final Map<QName, String> attributes) {
+    protected AbstractImmutableNormalizedValueAttrNode(final K nodeIdentifier, final V value, final Map<QName, String> attributes) {
         super(nodeIdentifier, value);
         this.attributes = ImmutableMap.copyOf(attributes);
     }
diff --git a/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableNormalizedValueNode.java b/yang/yang-data-impl/src/main/java/org/opendaylight/yangtools/yang/data/impl/schema/nodes/AbstractImmutableNormalizedValueNode.java
new file mode 100644 (file)
index 0000000..16ca637
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.data.impl.schema.nodes;
+
+import org.opendaylight.yangtools.yang.data.api.InstanceIdentifier;
+
+import com.google.common.base.Preconditions;
+
+public abstract class AbstractImmutableNormalizedValueNode<K extends InstanceIdentifier.PathArgument,V>
+        extends AbstractImmutableNormalizedNode<K, V> {
+
+    private final V value;
+
+    protected AbstractImmutableNormalizedValueNode(final K nodeIdentifier, final V value) {
+       super(nodeIdentifier);
+        this.value = Preconditions.checkNotNull(value, "value");
+    }
+
+    @Override
+    public final V getValue() {
+        return value;
+    }
+}
index cae5136a40f75867d97cd56829818b7649028177..401c009fd4b4e64bf015cf91fb99e515b8c010c1 100644 (file)
@@ -12,6 +12,7 @@ import java.util.Set;
 import org.opendaylight.yangtools.yang.common.QName;
 
 /**
+ *
  * The ChoiceNode defines a set of alternatives. It consists of a number of
  * branches defined as ChoiceCaseNode objects.
  */
@@ -19,7 +20,7 @@ public interface ChoiceNode extends DataSchemaNode, AugmentationTarget {
 
     /**
      * Returns cases of choice.
-     * 
+     *
      * @return set of ChoiceCaseNode objects defined in this node which
      *         represents set of arguments of the YANG <code>case</code>
      *         substatement of the <code>choice</code> statement
@@ -27,9 +28,9 @@ public interface ChoiceNode extends DataSchemaNode, AugmentationTarget {
     Set<ChoiceCaseNode> getCases();
 
     /**
-     * 
+     *
      * Returns the concrete case according to specified Q name.
-     * 
+     *
      * @param name
      *            QName of seeked Choice Case Node
      * @return child case node of this Choice if child with given name is
@@ -39,7 +40,7 @@ public interface ChoiceNode extends DataSchemaNode, AugmentationTarget {
 
     /**
      * Returns the concrete case according to specified name.
-     * 
+     *
      * @param name
      *            name of seeked child as String
      * @return child case node (or local name of case node) of this Choice if
@@ -48,9 +49,9 @@ public interface ChoiceNode extends DataSchemaNode, AugmentationTarget {
     ChoiceCaseNode getCaseNodeByName(String name);
 
     /**
-     * 
+     *
      * Returns name of case which is in the choice specified as default
-     * 
+     *
      * @return string with the name of case which is specified in the argument
      *         of the YANG <code>default</code> substatement of
      *         <code>choice</code> statement.
index 6b3f4703bad31618a11eaad5573774adee47cc9b..ab8ae21cafd9010502fd3496ff6e5bb4b5763152 100644 (file)
@@ -8,10 +8,22 @@
 package org.opendaylight.yangtools.yang.model.api;
 
 /**
+ *
+ * Data Schema Node represents abstract supertype from which all data tree
+ * definitions are derived.
  *
  * Contains the method which are used for getting metadata from the schema nodes
  * which contains data.
  *
+ * @see ContainerSchemaNode
+ * @see ListSchemaNode
+ * @see LeafListSchemaNode
+ * @see ChoiceNode
+ * @see ChoiceCaseNode
+ * @see LeafSchemaNode
+ * @see AnyXmlSchemaNode
+ *
+ *
  */
 public interface DataSchemaNode extends SchemaNode {
 
index 29de860253a6f1ddf264d0eaf243fdb06ae7bda5..6cfa27e6d3096df806fbf056f1529cac63d28993 100644 (file)
@@ -7,7 +7,6 @@
  */
 package org.opendaylight.yangtools.yang.model.util;
 
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
@@ -18,6 +17,8 @@ import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
 
+import com.google.common.base.Optional;
+
 /**
  * The Abstract Integer class defines implementation of IntegerTypeDefinition
  * interface which represents SIGNED Integer values defined in Yang language. <br>
@@ -43,22 +44,23 @@ abstract class AbstractSignedInteger implements IntegerTypeDefinition {
     private final List<RangeConstraint> rangeStatements;
 
     /**
-     * @param name
-     * @param description
-     * @param minRange
-     * @param maxRange
-     * @param units
+     * Construct SignedInteger
+     *
+     * @param name Name of type
+     * @param description Description of type
+     * @param minRange Minimal range
+     * @param maxRange Maxium range
+     * @param units Units
      */
-    public AbstractSignedInteger(final QName name, final String description, final Number minRange,
+    protected AbstractSignedInteger(final QName name, final String description, final Number minRange,
             final Number maxRange, final String units) {
         this.name = name;
         this.path = SchemaPath.create(Collections.singletonList(name), true);
         this.description = description;
         this.units = units;
-        this.rangeStatements = new ArrayList<RangeConstraint>();
         final String rangeDescription = "Integer values between " + minRange + " and " + maxRange + ", inclusively.";
-        this.rangeStatements.add(BaseConstraints.rangeConstraint(minRange, maxRange, rangeDescription,
-                "https://tools.ietf.org/html/rfc6020#section-9.2.4"));
+        this.rangeStatements = Collections.singletonList(BaseConstraints.newRangeConstraint(minRange, maxRange, Optional.of(rangeDescription),
+                Optional.of("https://tools.ietf.org/html/rfc6020#section-9.2.4")));
     }
 
     @Override
index ae7a61016a6910926024fce88e8e8939acf65b4f..b33392a7a0fcf1632694da9dee3510c7c4310d90 100644 (file)
@@ -7,7 +7,6 @@
  */
 package org.opendaylight.yangtools.yang.model.util;
 
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
@@ -18,6 +17,8 @@ import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
 
+import com.google.common.base.Optional;
+
 /**
  * The Abstract Integer class defines implementation of IntegerTypeDefinition
  * interface which represents UNSIGNED Integer values defined in Yang language. <br>
@@ -44,21 +45,21 @@ abstract class AbstractUnsignedInteger implements UnsignedIntegerTypeDefinition
     private final List<RangeConstraint> rangeStatements;
 
     /**
+     * Construct Unsigned Integer
      *
-     * @param name
-     * @param description
-     * @param maxRange
-     * @param units
+     * @param name Name of type
+     * @param description Description of type
+     * @param maxRange Maximum value
+     * @param units Units
      */
     public AbstractUnsignedInteger(final QName name, final String description, final Number maxRange, final String units) {
         this.name = name;
         this.path = SchemaPath.create(Collections.singletonList(name), true);
         this.description = description;
         this.units = units;
-        this.rangeStatements = new ArrayList<RangeConstraint>();
         final String rangeDescription = "Integer values between " + MIN_VALUE + " and " + maxRange + ", inclusively.";
-        this.rangeStatements.add(BaseConstraints.rangeConstraint(MIN_VALUE, maxRange, rangeDescription,
-                "https://tools.ietf.org/html/rfc6020#section-9.2.4"));
+        this.rangeStatements = Collections.singletonList(BaseConstraints.newRangeConstraint(MIN_VALUE, maxRange, Optional.of(rangeDescription),
+                Optional.of("https://tools.ietf.org/html/rfc6020#section-9.2.4")));
     }
 
     @Override
index c6ba5d619c0605e0d8dbab39ccb4d81b9f3d4687..7dd5fb402934afbb3caad6913c409e587caf1a59 100644 (file)
@@ -11,423 +11,172 @@ import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
 
+import com.google.common.base.Optional;
+
+/**
+ * Utility class which provides factory methods to construct Constraints.
+ *
+ * Provides static factory methods which constructs instances of
+ * <ul>
+ * <li>{@link LengthConstraint} - {@link #lengthConstraint(Number, Number, String, String)}
+ * <li>{@link RangeConstraint} - {@link #rangeConstraint(Number, Number, String, String)}
+ * <li>{@link PatternConstraint} - {@link #patternConstraint(String, String, String)}
+ * </ul>
+ */
 public final class BaseConstraints {
 
     private BaseConstraints() {
     }
 
-    public static LengthConstraint lengthConstraint(final Number min, final Number max, final String description,
-            final String reference) {
+
+    /**
+     * Creates a {@link LengthConstraint}.
+     *
+     * Creates an instance of Length constraint based on supplied parameters
+     * with additional behaviour:
+     *
+     * <ul>
+     * <li>{@link LengthConstraint#getErrorAppTag()} returns <code>length-out-of-specified-bounds</code>
+     * <li>{@link LengthConstraint#getErrorMessage() returns <code>The argument is out of bounds &lt;<i>min</i>, <i>max</i> &gt;</code>
+     * </ul>
+     *
+     * @see LengthConstraint
+     *
+     * @param min  length-restricting lower bound value. The value MUST NOT be negative.
+     * @param max length-restricting upper bound value. The value MUST NOT be negative.
+     * @param description Description associated with constraint. {@link Optional#absent()} if description is undefined.
+     * @param reference Reference associated with constraint. {@link Optional#absent()} if reference is undefined.
+     * @return Instance of {@link LengthConstraint}
+     */
+    public static LengthConstraint newLengthConstraint(final Number min, final Number max, final Optional<String> description,
+            final Optional<String> reference) {
         return new LengthConstraintImpl(min, max, description, reference);
     }
 
-    public static RangeConstraint rangeConstraint(final Number min, final Number max, final String description,
-            final String reference) {
+    /**
+     * Creates a {@link RangeConstraint}.
+     *
+     * Creates an instance of Range constraint based on supplied parameters
+     * with additional behaviour:
+     *
+     * <ul>
+     * <li>{@link RangeConstraint#getErrorAppTag()} returns <code>range-out-of-specified-bounds</code>
+     * <li>{@link RangeConstraint#getErrorMessage() returns <code>The argument is out of bounds &lt;<i>min</i>, <i>max</i> &gt;</code>
+     * </ul>
+     *
+     *
+     * @see RangeConstraint
+     *
+     * @param min value-restricting lower bound value. The value MUST NOT Be null.
+     * @param max value-restricting upper bound value. The value MUST NOT Be null.
+     * @param description Description associated with constraint. {@link Optional#absent()} if description is undefined.
+     * @param reference Reference associated with constraint. {@link Optional#absent()} if reference is undefined.
+     * @return Instance of {@link RangeConstraint}
+     */
+    public static RangeConstraint newRangeConstraint(final Number min, final Number max, final Optional<String> description,
+            final Optional<String> reference) {
         return new RangeConstraintImpl(min, max, description, reference);
     }
 
-    public static PatternConstraint patternConstraint(final String pattern, final String description,
-            final String reference) {
+
+    /**
+     * Creates a {@link PatternConstraint}.
+     *
+     * Creates an instance of Pattern constraint based on supplied parameters
+     * with additional behaviour:
+     *
+     * <ul>
+     * <li>{@link PatternConstraint#getErrorAppTag()} returns <code>invalid-regular-expression</code>
+     * </ul>
+     *
+     * @see PatternConstraint
+     *
+     * @param pattern Regular expression, MUST NOT BE null.
+     * @param description Description associated with constraint.
+     * @param reference Reference associated with constraint.
+     * @returnInstance of {@link PatternConstraint}
+     */
+    public static PatternConstraint newPatternConstraint(final String pattern, final Optional<String> description,
+            final Optional<String> reference) {
         return new PatternConstraintImpl(pattern, description, reference);
     }
 
-    private static final class LengthConstraintImpl implements LengthConstraint {
-
-        private final Number min;
-        private final Number max;
-
-        private final String description;
-        private final String reference;
-
-        private final String errorAppTag;
-        private final String errorMessage;
 
-        public LengthConstraintImpl(Number min, Number max, final String description, final String reference) {
-            super();
-            this.min = min;
-            this.max = max;
-            this.description = description;
-            this.reference = reference;
-
-            this.errorAppTag = "length-out-of-specified-bounds";
-            this.errorMessage = "The argument is out of bounds <" + min + ", " + max + ">";
-        }
-
-        @Override
-        public String getDescription() {
-            return description;
-        }
-
-        @Override
-        public String getErrorAppTag() {
-            return errorAppTag;
-        }
-
-        @Override
-        public String getErrorMessage() {
-            return errorMessage;
-        }
-
-        @Override
-        public String getReference() {
-            return reference;
-        }
-
-        @Override
-        public Number getMin() {
-            return min;
-        }
-
-        @Override
-        public Number getMax() {
-            return max;
-        }
-
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = 1;
-            result = prime * result + ((description == null) ? 0 : description.hashCode());
-            result = prime * result + ((errorAppTag == null) ? 0 : errorAppTag.hashCode());
-            result = prime * result + ((errorMessage == null) ? 0 : errorMessage.hashCode());
-            result = prime * result + ((max == null) ? 0 : max.hashCode());
-            result = prime * result + ((min == null) ? 0 : min.hashCode());
-            result = prime * result + ((reference == null) ? 0 : reference.hashCode());
-            return result;
-        }
-
-        @Override
-        public boolean equals(final Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (obj == null) {
-                return false;
-            }
-            if (getClass() != obj.getClass()) {
-                return false;
-            }
-            final LengthConstraintImpl other = (LengthConstraintImpl) obj;
-            if (description == null) {
-                if (other.description != null) {
-                    return false;
-                }
-            } else if (!description.equals(other.description)) {
-                return false;
-            }
-            if (errorAppTag == null) {
-                if (other.errorAppTag != null) {
-                    return false;
-                }
-            } else if (!errorAppTag.equals(other.errorAppTag)) {
-                return false;
-            }
-            if (errorMessage == null) {
-                if (other.errorMessage != null) {
-                    return false;
-                }
-            } else if (!errorMessage.equals(other.errorMessage)) {
-                return false;
-            }
-            if (max != other.max) {
-                return false;
-            }
-            if (min != other.min) {
-                return false;
-            }
-            if (reference == null) {
-                if (other.reference != null) {
-                    return false;
-                }
-            } else if (!reference.equals(other.reference)) {
-                return false;
-            }
-            return true;
-        }
-
-        @Override
-        public String toString() {
-            StringBuilder builder = new StringBuilder();
-            builder.append("LengthConstraintImpl [min=");
-            builder.append(min);
-            builder.append(", max=");
-            builder.append(max);
-            builder.append(", description=");
-            builder.append(description);
-            builder.append(", errorAppTag=");
-            builder.append(errorAppTag);
-            builder.append(", reference=");
-            builder.append(reference);
-            builder.append(", errorMessage=");
-            builder.append(errorMessage);
-            builder.append("]");
-            return builder.toString();
-        }
+    /**
+     * Creates a {@link LengthConstraint}.
+     *
+     * Creates an instance of Length constraint based on supplied parameters
+     * with additional behaviour:
+     *
+     * <ul>
+     * <li>{@link LengthConstraint#getErrorAppTag()} returns <code>length-out-of-specified-bounds</code>
+     * <li>{@link LengthConstraint#getErrorMessage() returns <code>The argument is out of bounds &lt;<i>min</i>, <i>max</i> &gt;</code>
+     * </ul>
+     *
+     * @see LengthConstraint
+     *
+     * @param min  length-restricting lower bound value. The value MUST NOT be negative.
+     * @param max length-restricting upper bound value. The value MUST NOT be negative.
+     * @param description Description associated with constraint.
+     * @param reference Reference associated with constraint.
+     * @return Instance of {@link LengthConstraint}
+     * @deprecated Use {@link #newLengthConstraint(Number, Number, Optional, Optional)} instead.
+     */
+    @Deprecated
+    public static LengthConstraint lengthConstraint(final Number min, final Number max, final String description,
+            final String reference) {
+        return newLengthConstraint(min, max, Optional.fromNullable(description), Optional.fromNullable(reference));
     }
 
-    private static final class RangeConstraintImpl implements RangeConstraint {
-        private final Number min;
-        private final Number max;
-
-        private final String description;
-        private final String reference;
-
-        private final String errorAppTag;
-        private final String errorMessage;
-
-        public RangeConstraintImpl(Number min, Number max, String description, String reference) {
-            super();
-            this.min = min;
-            this.max = max;
-            this.description = description;
-            this.reference = reference;
-
-            this.errorAppTag = "range-out-of-specified-bounds";
-            this.errorMessage = "The argument is out of bounds <" + min + ", " + max + ">";
-        }
-
-        @Override
-        public String getDescription() {
-            return description;
-        }
-
-        @Override
-        public String getErrorAppTag() {
-            return errorAppTag;
-        }
-
-        @Override
-        public String getErrorMessage() {
-            return errorMessage;
-        }
-
-        @Override
-        public String getReference() {
-            return reference;
-        }
-
-        @Override
-        public Number getMin() {
-            return min;
-        }
-
-        @Override
-        public Number getMax() {
-            return max;
-        }
-
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = 1;
-            result = prime * result + ((description == null) ? 0 : description.hashCode());
-            result = prime * result + ((errorAppTag == null) ? 0 : errorAppTag.hashCode());
-            result = prime * result + ((errorMessage == null) ? 0 : errorMessage.hashCode());
-            result = prime * result + ((max == null) ? 0 : max.hashCode());
-            result = prime * result + ((min == null) ? 0 : min.hashCode());
-            result = prime * result + ((reference == null) ? 0 : reference.hashCode());
-            return result;
-        }
-
-        @Override
-        public boolean equals(final Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (obj == null) {
-                return false;
-            }
-            if (getClass() != obj.getClass()) {
-                return false;
-            }
-            final RangeConstraintImpl other = (RangeConstraintImpl) obj;
-            if (description == null) {
-                if (other.description != null) {
-                    return false;
-                }
-            } else if (!description.equals(other.description)) {
-                return false;
-            }
-            if (errorAppTag == null) {
-                if (other.errorAppTag != null) {
-                    return false;
-                }
-            } else if (!errorAppTag.equals(other.errorAppTag)) {
-                return false;
-            }
-            if (errorMessage == null) {
-                if (other.errorMessage != null) {
-                    return false;
-                }
-            } else if (!errorMessage.equals(other.errorMessage)) {
-                return false;
-            }
-            if (max == null) {
-                if (other.max != null) {
-                    return false;
-                }
-            } else if (!max.equals(other.max)) {
-                return false;
-            }
-            if (min == null) {
-                if (other.min != null) {
-                    return false;
-                }
-            } else if (!min.equals(other.min)) {
-                return false;
-            }
-            if (reference == null) {
-                if (other.reference != null) {
-                    return false;
-                }
-            } else if (!reference.equals(other.reference)) {
-                return false;
-            }
-            return true;
-        }
-
-        @Override
-        public String toString() {
-            final StringBuilder builder = new StringBuilder();
-            builder.append("RangeConstraintImpl [min=");
-            builder.append(min);
-            builder.append(", max=");
-            builder.append(max);
-            builder.append(", description=");
-            builder.append(description);
-            builder.append(", reference=");
-            builder.append(reference);
-            builder.append(", errorAppTag=");
-            builder.append(errorAppTag);
-            builder.append(", errorMessage=");
-            builder.append(errorMessage);
-            builder.append("]");
-            return builder.toString();
-        }
+    /**
+     * Creates a {@link RangeConstraint}.
+     *
+     * Creates an instance of Range constraint based on supplied parameters
+     * with additional behaviour:
+     *
+     * <ul>
+     * <li>{@link RangeConstraint#getErrorAppTag()} returns <code>range-out-of-specified-bounds</code>
+     * <li>{@link RangeConstraint#getErrorMessage() returns <code>The argument is out of bounds &lt;<i>min</i>, <i>max</i> &gt;</code>
+     * </ul>
+     *
+     *
+     * @see RangeConstraint
+     *
+     * @param min value-restricting lower bound value. The value MUST NOT Be null.
+     * @param max value-restricting upper bound value. The value MUST NOT Be null.
+     * @param description Description associated with constraint.
+     * @param reference Reference associated with constraint.
+     * @return Instance of {@link RangeConstraint}
+     * @deprecated Use {@link #newRangeConstraint(Number, Number, Optional, Optional)} instead.
+     */
+    @Deprecated
+    public static RangeConstraint rangeConstraint(final Number min, final Number max, final String description,
+            final String reference) {
+        return newRangeConstraint(min, max, Optional.fromNullable(description), Optional.fromNullable(reference));
     }
 
-    private static final class PatternConstraintImpl implements PatternConstraint {
-
-        private final String regex;
-        private final String description;
-        private final String reference;
-
-        private final String errorAppTag;
-        private final String errorMessage;
-
-        public PatternConstraintImpl(final String regex, final String description, final String reference) {
-            super();
-            this.regex = regex;
-            this.description = description;
-            this.reference = reference;
-
-            errorAppTag = "invalid-regular-expression";
-            // TODO: add erro message
-            errorMessage = "";
-        }
-
-        @Override
-        public String getDescription() {
-            return description;
-        }
-
-        @Override
-        public String getErrorAppTag() {
-            return errorAppTag;
-        }
-
-        @Override
-        public String getErrorMessage() {
-            return errorMessage;
-        }
-
-        @Override
-        public String getReference() {
-            return reference;
-        }
-
-        @Override
-        public String getRegularExpression() {
-            return regex;
-        }
-
-        @Override
-        public int hashCode() {
-            final int prime = 31;
-            int result = 1;
-            result = prime * result + ((description == null) ? 0 : description.hashCode());
-            result = prime * result + ((errorAppTag == null) ? 0 : errorAppTag.hashCode());
-            result = prime * result + ((errorMessage == null) ? 0 : errorMessage.hashCode());
-            result = prime * result + ((reference == null) ? 0 : reference.hashCode());
-            result = prime * result + ((regex == null) ? 0 : regex.hashCode());
-            return result;
-        }
-
-        @Override
-        public boolean equals(final Object obj) {
-            if (this == obj) {
-                return true;
-            }
-            if (obj == null) {
-                return false;
-            }
-            if (getClass() != obj.getClass()) {
-                return false;
-            }
-            final PatternConstraintImpl other = (PatternConstraintImpl) obj;
-            if (description == null) {
-                if (other.description != null) {
-                    return false;
-                }
-            } else if (!description.equals(other.description)) {
-                return false;
-            }
-            if (errorAppTag == null) {
-                if (other.errorAppTag != null) {
-                    return false;
-                }
-            } else if (!errorAppTag.equals(other.errorAppTag)) {
-                return false;
-            }
-            if (errorMessage == null) {
-                if (other.errorMessage != null) {
-                    return false;
-                }
-            } else if (!errorMessage.equals(other.errorMessage)) {
-                return false;
-            }
-            if (reference == null) {
-                if (other.reference != null) {
-                    return false;
-                }
-            } else if (!reference.equals(other.reference)) {
-                return false;
-            }
-            if (regex == null) {
-                if (other.regex != null) {
-                    return false;
-                }
-            } else if (!regex.equals(other.regex)) {
-                return false;
-            }
-            return true;
-        }
-
-        @Override
-        public String toString() {
-            StringBuilder builder = new StringBuilder();
-            builder.append("PatternConstraintImpl [regex=");
-            builder.append(regex);
-            builder.append(", description=");
-            builder.append(description);
-            builder.append(", reference=");
-            builder.append(reference);
-            builder.append(", errorAppTag=");
-            builder.append(errorAppTag);
-            builder.append(", errorMessage=");
-            builder.append(errorMessage);
-            builder.append("]");
-            return builder.toString();
-        }
+    /**
+     * Creates a {@link PatternConstraint}.
+     *
+     * Creates an instance of Range constraint based on supplied parameters
+     * with additional behaviour:
+     *
+     * <ul>
+     * <li>{@link PatternConstraint#getErrorAppTag()} returns <code>invalid-regular-expression</code>
+     * </ul>
+     *
+     *
+     * @see PatternConstraint
+     *
+     * @param pattern Regular expression, MUST NOT
+     * @param description Description associated with constraint.
+     * @param reference Reference associated with constraint.
+     * @return Instance of {@link PatternConstraint}
+     * @deprecated Use {@link #newPatternConstraint(String, Optional, Optional)} Instead.
+     */
+    @Deprecated
+    public static PatternConstraint patternConstraint(final String pattern, final String description,
+            final String reference) {
+        return newPatternConstraint(pattern, Optional.fromNullable(description), Optional.fromNullable(reference));
     }
 }
index 7403099c0706fa492a764ef0bf4da5fc22cafcac..53dc55b58555f473eb4c838a39336dfd56a82ec5 100644 (file)
@@ -12,22 +12,36 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Date;
 import java.util.List;
+import java.util.Set;
 
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Utility methods and constants to work with built-in YANG types
+ *
+ *
+ */
 public final class BaseTypes {
 
     private BaseTypes() {
     }
 
     public static final URI BASE_TYPES_NAMESPACE = URI.create("urn:ietf:params:xml:ns:yang:1");
+
     public static final QName BINARY_QNAME = constructQName("binary");
     public static final QName BITS_QNAME = constructQName("bits");
     public static final QName BOOLEAN_QNAME = constructQName("boolean");
     public static final QName DECIMAL64_QNAME = constructQName("decimal64");
     public static final QName EMPTY_QNAME = constructQName("empty");
     public static final QName ENUMERATION_QNAME = constructQName("enumeration");
+    public static final QName IDENTITYREF_QNAME = constructQName("identityref");
+    public static final QName INSTANCE_IDENTIFIER_QNAME = constructQName("instance-identifier");
     public static final QName INT8_QNAME = constructQName("int8");
     public static final QName INT16_QNAME = constructQName("int16");
     public static final QName INT32_QNAME = constructQName("int32");
@@ -38,6 +52,28 @@ public final class BaseTypes {
     public static final QName UINT16_QNAME = constructQName("uint16");
     public static final QName UINT32_QNAME = constructQName("uint32");
     public static final QName UINT64_QNAME = constructQName("uint64");
+    public static final QName UNION_QNAME = constructQName("union");
+
+    private static final Set<String> BUILD_IN_TYPES = ImmutableSet.<String> builder().add(BINARY_QNAME.getLocalName()) //
+            .add(BITS_QNAME.getLocalName()) //
+            .add(BOOLEAN_QNAME.getLocalName()) //
+            .add(DECIMAL64_QNAME.getLocalName()) //
+            .add(EMPTY_QNAME.getLocalName()) //
+            .add(ENUMERATION_QNAME.getLocalName()) //
+            .add(IDENTITYREF_QNAME.getLocalName()) //
+            .add(INSTANCE_IDENTIFIER_QNAME.getLocalName()) //
+            .add(INT8_QNAME.getLocalName()) //
+            .add(INT16_QNAME.getLocalName()) //
+            .add(INT32_QNAME.getLocalName()) //
+            .add(INT64_QNAME.getLocalName()) //
+            .add(LEAFREF_QNAME.getLocalName()) //
+            .add(STRING_QNAME.getLocalName()) //
+            .add(UINT8_QNAME.getLocalName()) //
+            .add(UINT16_QNAME.getLocalName()) //
+            .add(UINT32_QNAME.getLocalName()) //
+            .add(UINT64_QNAME.getLocalName()) //
+            .add(UNION_QNAME.getLocalName()) //
+            .build();
 
     /**
      * Construct QName for Built-in base Yang type. The namespace for built-in
@@ -52,12 +88,14 @@ public final class BaseTypes {
     }
 
     /**
-     * Creates Schema Path from Qname.
+     * Creates Schema Path from {@link QName}.
      *
      * @param typeName
      *            yang type QName
      * @return Schema Path from Qname.
+     * @deprecated Use {@link SchemaPath#create(boolean, QName...)} instead.
      */
+    @Deprecated
     public static SchemaPath schemaPath(final QName typeName) {
         return SchemaPath.create(Collections.singletonList(typeName), true);
     }
@@ -73,7 +111,11 @@ public final class BaseTypes {
      * @param revision
      *            Revision Date
      * @return Schema Path
+     *
+     * @deprecated Use {@link SchemaPath#create(boolean, Iterable)} with QNames
+     *             manually constructed.
      */
+    @Deprecated
     public static SchemaPath schemaPath(final List<String> actualPath, final URI namespace, final Date revision) {
         if (actualPath == null) {
             throw new IllegalArgumentException("The actual path List MUST be specified.");
@@ -87,4 +129,70 @@ public final class BaseTypes {
         }
         return SchemaPath.create(pathList, true);
     }
+
+    /**
+     * Returns true if supplied type is representation of built-in YANG type as
+     * per RFC 6020.
+     *
+     * See package documentation for description of base types.
+     *
+     * @param type
+     * @return true if type is built-in YANG Types.
+     */
+    public static boolean isYangBuildInType(final String type) {
+        return BUILD_IN_TYPES.contains(type);
+    }
+
+    /**
+     * Returns default instance of built-in for supplied type
+     *
+     * See package documentation for description of base build-in types
+     * with default instance.
+     *
+     * @param typeName
+     * @return Returns default instance or {@link Optional#absent()} if default
+     *         instance does not exists
+     *
+     */
+    public static Optional<TypeDefinition<?>> defaultBaseTypeFor(final String typeName) {
+        return Optional.<TypeDefinition<?>> fromNullable(defaultBaseTypeForImpl(typeName));
+    }
+
+    private static TypeDefinition<?> defaultBaseTypeForImpl(final String typeName) {
+        Preconditions.checkNotNull(typeName, "typeName must not be null.");
+
+        if (typeName.startsWith("int")) {
+            if ("int8".equals(typeName)) {
+                return Int8.getInstance();
+            } else if ("int16".equals(typeName)) {
+                return Int16.getInstance();
+            } else if ("int32".equals(typeName)) {
+                return Int32.getInstance();
+            } else if ("int64".equals(typeName)) {
+                return Int64.getInstance();
+            }
+        } else if (typeName.startsWith("uint")) {
+            if ("uint8".equals(typeName)) {
+                return Uint8.getInstance();
+            } else if ("uint16".equals(typeName)) {
+                return Uint16.getInstance();
+            } else if ("uint32".equals(typeName)) {
+                return Uint32.getInstance();
+            } else if ("uint64".equals(typeName)) {
+                return Uint64.getInstance();
+            }
+        } else if ("string".equals(typeName)) {
+            return StringType.getInstance();
+        } else if ("binary".equals(typeName)) {
+            return BinaryType.getInstance();
+        } else if ("boolean".equals(typeName)) {
+            return BooleanType.getInstance();
+        } else if ("empty".equals(typeName)) {
+            return EmptyType.getInstance();
+        } else if ("instance-identifier".equals(typeName)) {
+            return InstanceIdentifier.getInstance();
+        }
+        return null;
+    }
+
 }
index cda865d1a2fb3d7dade645513766d191793cdca9..9d93f745f3d8675bca3315c21dcdfd8afb7d7ee4 100644 (file)
@@ -17,6 +17,8 @@ import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
 
+import com.google.common.base.Optional;
+
 /**
  * The <code>default</code> implementation of Binary Type Definition interface.
  *
@@ -27,16 +29,17 @@ public final class BinaryType implements BinaryTypeDefinition {
     private static final String REFERENCE = "https://tools.ietf.org/html/rfc6020#section-9.8";
     private static final String UNITS = "";
 
+    private final static QName QNAME = BaseTypes.BINARY_QNAME;
+
     private static final BinaryType INSTANCE = new BinaryType();
 
-    private final QName name = BaseTypes.BINARY_QNAME;
-    private final SchemaPath path = SchemaPath.create(Collections.singletonList(name), true);
+    private final static SchemaPath PATH = SchemaPath.create(Collections.singletonList(QNAME), true);
     private final List<Byte> bytes = Collections.emptyList();
     private final List<LengthConstraint> lengthConstraints;
 
     private BinaryType() {
         this.lengthConstraints = Collections.singletonList(
-                BaseConstraints.lengthConstraint(0, Long.MAX_VALUE, "", ""));
+                BaseConstraints.newLengthConstraint(0, Long.MAX_VALUE, Optional.of(""), Optional.of("")));
     }
 
     public static BinaryType getInstance() {
@@ -83,7 +86,7 @@ public final class BinaryType implements BinaryTypeDefinition {
      */
     @Override
     public QName getQName() {
-        return name;
+        return QNAME;
     }
 
     /*
@@ -93,7 +96,7 @@ public final class BinaryType implements BinaryTypeDefinition {
      */
     @Override
     public SchemaPath getPath() {
-        return path;
+        return PATH;
     }
 
     /*
@@ -150,8 +153,8 @@ public final class BinaryType implements BinaryTypeDefinition {
         int result = 1;
         result = prime * result + ((bytes == null) ? 0 : bytes.hashCode());
         result = prime * result + ((lengthConstraints == null) ? 0 : lengthConstraints.hashCode());
-        result = prime * result + ((name == null) ? 0 : name.hashCode());
-        result = prime * result + ((path == null) ? 0 : path.hashCode());
+        result = prime * result + QNAME.hashCode();
+        result = prime * result + PATH.hashCode();
         return result;
     }
 
@@ -181,20 +184,6 @@ public final class BinaryType implements BinaryTypeDefinition {
         } else if (!lengthConstraints.equals(other.lengthConstraints)) {
             return false;
         }
-        if (name == null) {
-            if (other.name != null) {
-                return false;
-            }
-        } else if (!name.equals(other.name)) {
-            return false;
-        }
-        if (path == null) {
-            if (other.path != null) {
-                return false;
-            }
-        } else if (!path.equals(other.path)) {
-            return false;
-        }
         return true;
     }
 
@@ -202,9 +191,7 @@ public final class BinaryType implements BinaryTypeDefinition {
     public String toString() {
         StringBuilder builder = new StringBuilder();
         builder.append("BinaryType [name=");
-        builder.append(name);
-        builder.append(", path=");
-        builder.append(path);
+        builder.append(QNAME);
         builder.append(", description=");
         builder.append(DESCRIPTION);
         builder.append(", reference=");
index c53df1bc6aa71259f030a996bc4259f2d8378518..e89e6572f459730a09d1cb30e3956138ec962596 100644 (file)
@@ -16,13 +16,17 @@ import org.opendaylight.yangtools.yang.model.api.Status;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.type.BitsTypeDefinition;
 
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
 /**
  * The <code>default</code> implementation of Bits Type Definition interface.
  *
  * @see BitsTypeDefinition
  */
 public final class BitsType implements BitsTypeDefinition {
-    private final QName name = BaseTypes.constructQName("bits");
+    private final static QName NAME = BaseTypes.BITS_QNAME;
+
     private final SchemaPath path;
     private final String description = "The bits built-in type represents a bit set.  "
             + "That is, a bits value is a set of flags identified by small integer position "
@@ -37,11 +41,13 @@ public final class BitsType implements BitsTypeDefinition {
      * Instantiates Bits type as empty bits list.
      *
      * @param path
+     * @deprecated Use static factory method {@link #create(SchemaPath, List)} instead.
      */
+    @Deprecated
     public BitsType(final SchemaPath path) {
         super();
         this.bits = Collections.emptyList();
-        this.path = path;
+        this.path = Preconditions.checkNotNull(path,"path must not be null");
     }
 
     /**
@@ -49,11 +55,17 @@ public final class BitsType implements BitsTypeDefinition {
      *
      * @param path
      * @param bits
+     * @deprecated Use static factory method {@link #create(SchemaPath, List)} instead.
      */
+    @Deprecated
     public BitsType(final SchemaPath path, final List<Bit> bits) {
         super();
-        this.bits = Collections.unmodifiableList(bits);
-        this.path = path;
+        this.bits = ImmutableList.copyOf(bits);
+        this.path = Preconditions.checkNotNull(path,"path must not be null");
+    }
+
+    public static BitsType create(final SchemaPath path, final List<Bit> bits) {
+        return new BitsType(path,bits);
     }
 
     /*
@@ -96,7 +108,7 @@ public final class BitsType implements BitsTypeDefinition {
      */
     @Override
     public QName getQName() {
-        return name;
+        return NAME;
     }
 
     /*
@@ -156,13 +168,13 @@ public final class BitsType implements BitsTypeDefinition {
         int result = 1;
         result = prime * result + ((bits == null) ? 0 : bits.hashCode());
         result = prime * result + ((description == null) ? 0 : description.hashCode());
-        result = prime * result + ((name == null) ? 0 : name.hashCode());
-        result = prime * result + ((path == null) ? 0 : path.hashCode());
+        result = prime * result + NAME.hashCode();
+        result = prime * result + path.hashCode();
         return result;
     }
 
     @Override
-    public boolean equals(Object obj) {
+    public boolean equals(final Object obj) {
         if (this == obj) {
             return true;
         }
@@ -187,13 +199,7 @@ public final class BitsType implements BitsTypeDefinition {
         } else if (!description.equals(other.description)) {
             return false;
         }
-        if (name == null) {
-            if (other.name != null) {
-                return false;
-            }
-        } else if (!name.equals(other.name)) {
-            return false;
-        }
+
         if (path == null) {
             if (other.path != null) {
                 return false;
@@ -208,7 +214,7 @@ public final class BitsType implements BitsTypeDefinition {
     public String toString() {
         StringBuilder builder = new StringBuilder();
         builder.append("BitsType [name=");
-        builder.append(name);
+        builder.append(NAME);
         builder.append(", path=");
         builder.append(path);
         builder.append(", description=");
index be35bf0b159f90d2abfade8ecd0adda93bc38f61..ad3a0ef6d29410beb12b3e5aaa30595058a7caf2 100644 (file)
@@ -34,6 +34,10 @@ public final class BooleanType implements BooleanTypeDefinition {
     private BooleanType() {
     }
 
+    /**
+     * Returns default instance of boolean built-in type.
+     * @return default instance of boolean built-in type.
+     */
     public static BooleanType getInstance() {
         return INSTANCE;
     }
index ed1db9a31505fc3ca961704e002862268975ca9f..850b51de87f52d091536008723b4075c1ba4763e 100644 (file)
@@ -24,6 +24,15 @@ import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 
+/**
+ * DataNodeIterator is iterator, which walks down whole YANG DataNodeContainer
+ * and walks all instances of {@link DataSchemaNode} present in subtree.
+ *
+ * Iterator instance is eagerly created, walking happens on initialization.
+ *
+ * Iteration is not ordered.
+ *
+ */
 public class DataNodeIterator implements Iterator<DataSchemaNode> {
 
     private final DataNodeContainer container;
@@ -50,22 +59,47 @@ public class DataNodeIterator implements Iterator<DataSchemaNode> {
         traverse(this.container);
     }
 
+    /**
+     * Returns list all containers present in subtree.
+     *
+     * @return Returns list all containers present in subtree.
+     */
     public List<ContainerSchemaNode> allContainers() {
         return allContainers;
     }
 
+    /**
+     * Returns list all lists present in subtree.
+     *
+     * @return Returns list all containers present in subtree.
+     */
     public List<ListSchemaNode> allLists() {
         return allLists;
     }
 
+    /**
+     * Returns list all choices present in subtree.
+     *
+     * @return Returns list all containers present in subtree.
+     */
     public List<ChoiceNode> allChoices() {
         return allChoices;
     }
 
+    /**
+     * Returns list all groupings present in subtree.
+     *
+     * @return Returns list all containers present in subtree.
+     */
     public List<GroupingDefinition> allGroupings() {
         return allGroupings;
     }
 
+    /**
+     * Returns list all typedefs present in subtree.
+     *
+     * @return Returns list all containers present in subtree.
+     */
     public List<TypeDefinition<?>> allTypedefs() {
         return allTypedefs;
     }
@@ -109,7 +143,7 @@ public class DataNodeIterator implements Iterator<DataSchemaNode> {
 
     }
 
-    private void traverseModule(DataNodeContainer dataNode) {
+    private void traverseModule(final DataNodeContainer dataNode) {
         final Module module;
         if (dataNode instanceof Module) {
             module = (Module) dataNode;
@@ -136,7 +170,7 @@ public class DataNodeIterator implements Iterator<DataSchemaNode> {
         }
     }
 
-    private void traverseGroupings(DataNodeContainer dataNode) {
+    private void traverseGroupings(final DataNodeContainer dataNode) {
         final Set<GroupingDefinition> groupings = dataNode.getGroupings();
         if (groupings != null) {
             for (GroupingDefinition grouping : groupings) {
index 666747915f3444becdf2e372b9fc9c15b6da1ab3..d975178a664015d4495b625ce173839fbb2ae85d 100644 (file)
@@ -19,6 +19,8 @@ import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
 
+import com.google.common.base.Optional;
+
 /**
  * The <code>default</code> implementation of Decimal Type Definition interface.
  *
@@ -26,7 +28,7 @@ import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
  * @see DecimalTypeDefinition
  */
 public final class Decimal64 implements DecimalTypeDefinition {
-    private final QName name = BaseTypes.constructQName("decimal64");
+    private static final QName NAME = BaseTypes.DECIMAL64_QNAME;
     private final SchemaPath path;
     private static final String UNITS = "";
     private static final BigDecimal DEFAULT_VALUE = null;
@@ -60,7 +62,9 @@ public final class Decimal64 implements DecimalTypeDefinition {
      *
      * @see DecimalTypeDefinition
      * @exception IllegalArgumentException
+     * @deprecated Use static factory {@link #create(SchemaPath, Integer)}.
      */
+    @Deprecated
     public Decimal64(final SchemaPath path, final Integer fractionDigits) {
         if (!((fractionDigits.intValue() >= 1) && (fractionDigits.intValue() <= MAX_NUMBER_OF_FRACTION_DIGITS))) {
             throw new IllegalArgumentException(
@@ -71,6 +75,10 @@ public final class Decimal64 implements DecimalTypeDefinition {
         this.path = path;
     }
 
+    public static Decimal64 create(final SchemaPath path, final Integer fractionDigits) {
+        return new Decimal64(path, fractionDigits);
+    }
+
     /**
      * Returns unmodifiable List with default definition of Range Statements.
      *
@@ -81,8 +89,8 @@ public final class Decimal64 implements DecimalTypeDefinition {
         final BigDecimal min = new BigDecimal("-922337203685477580.8");
         final BigDecimal max = new BigDecimal("922337203685477580.7");
         final String rangeDescription = "Integer values between " + min + " and " + max + ", inclusively.";
-        rangeStmts.add(BaseConstraints.rangeConstraint(min, max, rangeDescription,
-                "https://tools.ietf.org/html/rfc6020#section-9.2.4"));
+        rangeStmts.add(BaseConstraints.newRangeConstraint(min, max, Optional.of(rangeDescription),
+                Optional.of("https://tools.ietf.org/html/rfc6020#section-9.2.4")));
         return Collections.unmodifiableList(rangeStmts);
     }
 
@@ -103,7 +111,7 @@ public final class Decimal64 implements DecimalTypeDefinition {
 
     @Override
     public QName getQName() {
-        return name;
+        return NAME;
     }
 
     @Override
@@ -145,13 +153,13 @@ public final class Decimal64 implements DecimalTypeDefinition {
     public int hashCode() {
         final int prime = 31;
         int result = 1;
-        result = prime * result + ((name == null) ? 0 : name.hashCode());
+        result = prime * result + ((NAME == null) ? 0 : NAME.hashCode());
         result = prime * result + ((path == null) ? 0 : path.hashCode());
         return result;
     }
 
     @Override
-    public boolean equals(Object obj) {
+    public boolean equals(final Object obj) {
         if (this == obj) {
             return true;
         }
@@ -162,13 +170,6 @@ public final class Decimal64 implements DecimalTypeDefinition {
             return false;
         }
         Decimal64 other = (Decimal64) obj;
-        if (name == null) {
-            if (other.name != null) {
-                return false;
-            }
-        } else if (!name.equals(other.name)) {
-            return false;
-        }
         if (path == null) {
             if (other.path != null) {
                 return false;
@@ -181,6 +182,6 @@ public final class Decimal64 implements DecimalTypeDefinition {
 
     @Override
     public String toString() {
-        return Decimal64.class.getSimpleName() + "[qname=" + name + ", fractionDigits=" + fractionDigits + "]";
+        return Decimal64.class.getSimpleName() + "[qname=" + NAME + ", fractionDigits=" + fractionDigits + "]";
     }
 }
index ed91d3358b4b42624edba5e15642d3251554bac6..7efebad4d43bdd4b0d2d5c8a84826de0ef09082e 100644 (file)
@@ -10,15 +10,16 @@ package org.opendaylight.yangtools.yang.model.util;
 import java.util.Collections;
 import java.util.List;
 
+import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.api.Status;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.type.EmptyTypeDefinition;
 
-public final class EmptyType implements EmptyTypeDefinition {
-    private static EmptyType instance;
-    private static final QName NAME = BaseTypes.constructQName("empty");
+public final class EmptyType implements EmptyTypeDefinition, Immutable {
+    private static final EmptyType INSTANCE = new EmptyType();
+    private static final QName NAME = BaseTypes.EMPTY_QNAME;
     private static final SchemaPath PATH = SchemaPath.create(Collections.singletonList(NAME), true);
     private static final String DESCRIPTION = "The empty built-in type represents a leaf that does not have any value, it conveys information by its presence or absence.";
     private static final String REFERENCE = "https://tools.ietf.org/html/rfc6020#page-131";
@@ -27,10 +28,7 @@ public final class EmptyType implements EmptyTypeDefinition {
     }
 
     public static EmptyType getInstance() {
-        if (instance == null) {
-            instance = new EmptyType();
-        }
-        return instance;
+        return INSTANCE;
     }
 
     @Override
index f359de0fddbfa9c7687197c89c62ea05fef152cb..1bd020019fa8fe63704dbd47572e9c478674bc7f 100644 (file)
@@ -16,6 +16,8 @@ import org.opendaylight.yangtools.yang.model.api.Status;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.type.EnumTypeDefinition;
 
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 
 /**
@@ -33,18 +35,55 @@ public final class EnumerationType implements EnumTypeDefinition {
     private final EnumPair defaultEnum;
     private final List<EnumPair> enums;
 
+
+    /**
+     * Constructs EnumerationType
+     *
+     * @param path
+     * @param enums
+     * @deprecated Use {@link #create(SchemaPath, List, Optional)} instead.
+     */
+    @Deprecated
     public EnumerationType(final SchemaPath path, final List<EnumPair> enums) {
-        super();
-        this.path = path;
-        this.enums = ImmutableList.copyOf(enums);
-        this.defaultEnum = null;
+        this(path,enums,Optional.<EnumPair>absent());
     }
 
+    /**
+     * Constructs EnumerationType
+     *
+     * @param path
+     * @param defaultEnum
+     * @param enums
+     * @deprecated Use {@link #create(SchemaPath, List, Optional)} instead.
+     */
+    @Deprecated
     public EnumerationType(final SchemaPath path, final EnumPair defaultEnum, final List<EnumPair> enums) {
-        super();
-        this.path = path;
-        this.defaultEnum = defaultEnum;
-        this.enums = ImmutableList.copyOf(enums);
+        this(path,enums,Optional.fromNullable(defaultEnum));
+    }
+
+    private EnumerationType(final SchemaPath path, final List<EnumPair> enums, final Optional<EnumPair> defaultEnum) {
+        this.path = Preconditions.checkNotNull(path,"path must not be null");
+        this.enums = ImmutableList.copyOf(Preconditions.checkNotNull(enums, "enums must not be null."));
+        if(defaultEnum.isPresent()) {
+            Preconditions.checkArgument(enums.contains(defaultEnum.get()),"defaultEnum must be contained in defined enumerations.");
+            this.defaultEnum = defaultEnum.get();
+        } else {
+            this.defaultEnum = null;
+        }
+    }
+
+    /**
+     *
+     * Constructs new enumeration
+     *
+     * @param path Schema Path to definition point of this enumeration
+     * @param enums List of defined enumeration values
+     * @param defaultValue {@link Optional#of(Object)} of default value, {@link Optional#absent()} if no default value is defined.
+     *        If defaultValue is set, it must be present in provided list of enumerations.
+     *
+     */
+    public static EnumerationType create(final SchemaPath path, final List<EnumPair> enums, final Optional<EnumPair> defaultValue) {
+        return new EnumerationType(path, enums, defaultValue);
     }
 
     /*
index 4c2c17b63ad2aae304dc0802d9f050f296bd18ee..3000c78e9fc98befdcf1b033cda1c3dbf09ea00f 100644 (file)
@@ -21,6 +21,17 @@ import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
 
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+/**
+ * Extended Type represents YANG type derived from other type.
+ *
+ * Extended type object is decorator on top of existing {@link TypeDefinition}
+ * which represents original type, and extended type
+ * may define additional constraints, modify description or reference
+ * of parent type or provide new type capture for specific use-cases.
+ *
+ */
 public class ExtendedType implements TypeDefinition<TypeDefinition<?>> {
 
     private final QName typeName;
@@ -35,10 +46,24 @@ public class ExtendedType implements TypeDefinition<TypeDefinition<?>> {
     private List<PatternConstraint> patterns = Collections.emptyList();
     private Integer fractionDigits = null;
 
-    private Status status;
-    private String units;
-    private Object defaultValue;
-    private boolean addedByUses;
+    private final Status status;
+    private final String units;
+    private final Object defaultValue;
+    private final boolean addedByUses;
+
+    /**
+    *
+    * Creates Builder for extended / derived type.
+    *
+    * @param typeName QName of derived type
+    * @param baseType Base type of derived type
+    * @param description Description of type
+    * @param reference Reference of Type
+    * @param path Schema path to type definition.
+    */
+    public static final Builder builder(final QName typeName,final TypeDefinition<?> baseType,final Optional<String> description,final Optional<String> reference,final SchemaPath path) {
+        return new Builder(typeName, baseType, description.or(""), reference.or(""), path);
+    }
 
     public static class Builder {
         private final QName typeName;
@@ -60,33 +85,55 @@ public class ExtendedType implements TypeDefinition<TypeDefinition<?>> {
         private List<PatternConstraint> patterns = Collections.emptyList();
         private Integer fractionDigits = null;
 
+        /**
+         *
+         * @param actualPath
+         * @param namespace
+         * @param revision
+         * @param typeName
+         * @param baseType
+         * @param description
+         * @param reference
+         *
+         * @deprecated Use {@link ExtendedType#builder(QName, TypeDefinition, Optional, Optional, SchemaPath)} instead.
+         */
+        @Deprecated
         public Builder(final List<String> actualPath, final URI namespace,
                 final Date revision, final QName typeName,
-                TypeDefinition<?> baseType, final String description,
+                final TypeDefinition<?> baseType, final String description,
                 final String reference) {
-            this.typeName = typeName;
-            this.baseType = baseType;
-            this.path = BaseTypes.schemaPath(actualPath, namespace, revision);
-            this.description = description;
-            this.reference = reference;
+            this(typeName,baseType,description,reference,BaseTypes.schemaPath(actualPath, namespace, revision));
         }
 
-        public Builder(final QName typeName, TypeDefinition<?> baseType,
+        /**
+         *
+         * Creates Builder for extended / derived type.
+         *
+         * @param typeName QName of derived type
+         * @param baseType Base type of derived type
+         * @param description Description of type
+         * @param reference Reference of Type
+         * @param path Schema path to type definition.
+         *
+         * @deprecated Use {@link ExtendedType#builder(QName, TypeDefinition, Optional, Optional, SchemaPath)} instead.
+         */
+        @Deprecated
+        public Builder(final QName typeName, final TypeDefinition<?> baseType,
                 final String description, final String reference,
-                SchemaPath path) {
-            this.typeName = typeName;
-            this.baseType = baseType;
-            this.path = path;
+                final SchemaPath path) {
+            this.typeName = Preconditions.checkNotNull(typeName, "type name must not be null.");
+            this.baseType = Preconditions.checkNotNull(baseType, "base type must not be null");
+            this.path = Preconditions.checkNotNull(path, "path must not be null.");
             this.description = description;
             this.reference = reference;
         }
 
-        public Builder status(Status status) {
+        public Builder status(final Status status) {
             this.status = status;
             return this;
         }
 
-        public Builder units(String units) {
+        public Builder units(final String units) {
             this.units = units;
             return this;
         }
@@ -138,7 +185,7 @@ public class ExtendedType implements TypeDefinition<TypeDefinition<?>> {
         }
     }
 
-    private ExtendedType(Builder builder) {
+    private ExtendedType(final Builder builder) {
         this.typeName = builder.typeName;
         this.baseType = builder.baseType;
         this.path = builder.path;
@@ -206,7 +253,7 @@ public class ExtendedType implements TypeDefinition<TypeDefinition<?>> {
     }
 
     @Override
-    public boolean equals(Object o) {
+    public boolean equals(final Object o) {
         if (this == o) {
             return true;
         }
index e34e0078588607c581c4f81e18d0ba37a9c170bf..16823e6708706682e24853627b07fc64581521f7 100644 (file)
@@ -17,6 +17,8 @@ import org.opendaylight.yangtools.yang.model.api.Status;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
 
+import com.google.common.base.Preconditions;
+
 /**
  * The <code>default</code> implementation of Identityref Type Definition
  * interface.
@@ -24,16 +26,39 @@ import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
  * @see IdentityrefTypeDefinition
  */
 public final class IdentityrefType implements IdentityrefTypeDefinition {
-    private final QName name = BaseTypes.constructQName("identityref");
+    private static final QName NAME = BaseTypes.IDENTITYREF_QNAME;
     private final SchemaPath path;
     private static final String DESCRIPTION = "The identityref type is used to reference an existing identity.";
     private static final String REFERENCE = "https://tools.ietf.org/html/rfc6020#section-9.10";
     private final IdentitySchemaNode identity;
     private static final String UNITS = "";
 
-    public IdentityrefType(IdentitySchemaNode identity, SchemaPath schemaPath) {
-        this.identity = identity;
-        this.path = schemaPath;
+    /**
+     * Constructs new {@link IdentityrefTypeDefinition} definition.
+     *
+     * @param identity
+     * @param schemaPath
+     */
+    @Deprecated
+    public IdentityrefType(final IdentitySchemaNode identity, final SchemaPath schemaPath) {
+        this(schemaPath,identity);
+    }
+
+    private IdentityrefType(final SchemaPath path, final IdentitySchemaNode baseIdentity) {
+        this.path = Preconditions.checkNotNull(path, "Path must be specified");
+        this.identity = Preconditions.checkNotNull(baseIdentity,"baseIdentity must be specified.");
+    }
+
+    /**
+     *
+     * Constructs new {@link IdentityrefTypeDefinition} definition.
+     *
+     * @param path Path to the definition.
+     * @param baseIdentity Base Identity, all derived identities are valid arguments for instance of this type.
+     * @return New identityref definition.
+     */
+    public static IdentityrefType create(final SchemaPath path, final IdentitySchemaNode baseIdentity) {
+        return new IdentityrefType(path, baseIdentity);
     }
 
     @Override
@@ -48,7 +73,7 @@ public final class IdentityrefType implements IdentityrefTypeDefinition {
 
     @Override
     public QName getQName() {
-        return name;
+        return NAME;
     }
 
     @Override
index 6330801f35cb7424965e3584a1cd3114afb4089c..b2d5887a7e6cbef4be618d392a2b2f8bfc9ef3b8 100644 (file)
@@ -10,6 +10,7 @@ package org.opendaylight.yangtools.yang.model.util;
 import java.util.Collections;
 import java.util.List;
 
+import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
@@ -21,33 +22,62 @@ import org.opendaylight.yangtools.yang.model.api.type.InstanceIdentifierTypeDefi
  * The <code>default</code> implementation of Instance Identifier Type
  * Definition interface.
  *
+ * Instance Identifier has only two possible variants - one with
+ * {@link #requireInstance()} which returns true, other one
+ * returns false.
+ *
  * @see InstanceIdentifierTypeDefinition
- * @deprecated Depracated, use {@link org.opendaylight.yangtools.yang.data.api.InstanceIdentifier} instead
+ *
  */
-@Deprecated
-public final class InstanceIdentifier implements InstanceIdentifierTypeDefinition {
-    private static final QName NAME = BaseTypes.constructQName("instance-identifier");
-    private static final SchemaPath PATH = new SchemaPath(Collections.singletonList(NAME), true);
+public final class InstanceIdentifier implements InstanceIdentifierTypeDefinition, Immutable {
+
+    private static final QName NAME = BaseTypes.INSTANCE_IDENTIFIER_QNAME;
+    private static final SchemaPath PATH = SchemaPath.create(Collections.singletonList(NAME), true);
     private static final String DESCRIPTION = "The instance-identifier built-in type is used to "
             + "uniquely identify a particular instance node in the data tree.";
     private static final String REFERENCE = "https://tools.ietf.org/html/rfc6020#section-9.13";
 
-    private final RevisionAwareXPath xpath;
     private static final String UNITS = "";
-    private boolean requireInstance = true;
+    private final Boolean requireInstance;
 
-    private static final int HASH_BOOLEAN_TRUE = 1231;
-    private static final int HASH_BOOLEAN_FALSE = 1237;
+    private static final InstanceIdentifier INSTANCE_WITH_REQUIRED_TRUE = new InstanceIdentifier(true);
+    private static final InstanceIdentifier INSTANCE_WITH_REQUIRED_FALSE = new InstanceIdentifier(false);
 
+    /**
+     * Constructs new instance identifier.
+     *
+     * @param xpath
+     * @deprecated Use {@link #getInstance()} for default one, since Instance Identifier does not have xpath.
+     */
+    @Deprecated
     public InstanceIdentifier(final RevisionAwareXPath xpath) {
-        this.xpath = xpath;
+        requireInstance = true;
     }
 
+    /**
+     * Constructs new instance identifier.
+     *
+     * @param xpath
+     * @param requireInstance if instance of data is required
+     * @deprecated Use {@link #create(boolean)}, since Instance Identifier does not have xpath.
+     */
+    @Deprecated
     public InstanceIdentifier(final RevisionAwareXPath xpath, final boolean requireInstance) {
-        this.xpath = xpath;
         this.requireInstance = requireInstance;
     }
 
+    private InstanceIdentifier(final boolean requiredInstance) {
+        this.requireInstance = requiredInstance;
+    }
+
+    public static InstanceIdentifier getInstance() {
+        return INSTANCE_WITH_REQUIRED_TRUE;
+    }
+
+    public static InstanceIdentifier create(final boolean requireInstance) {
+        return requireInstance ? INSTANCE_WITH_REQUIRED_TRUE : INSTANCE_WITH_REQUIRED_FALSE;
+    }
+
     /*
      * (non-Javadoc)
      *
@@ -78,7 +108,7 @@ public final class InstanceIdentifier implements InstanceIdentifierTypeDefinitio
      */
     @Override
     public Object getDefaultValue() {
-        return xpath;
+        return null;
     }
 
     /*
@@ -151,8 +181,9 @@ public final class InstanceIdentifier implements InstanceIdentifierTypeDefinitio
      * InstanceIdentifierTypeDefinition# getPathStatement()
      */
     @Override
+    @Deprecated
     public RevisionAwareXPath getPathStatement() {
-        return xpath;
+        return null;
     }
 
     /*
@@ -170,13 +201,12 @@ public final class InstanceIdentifier implements InstanceIdentifierTypeDefinitio
     public int hashCode() {
         final int prime = 31;
         int result = 1;
-        result = prime * result + (requireInstance ? HASH_BOOLEAN_TRUE : HASH_BOOLEAN_FALSE);
-        result = prime * result + ((xpath == null) ? 0 : xpath.hashCode());
+        result = prime * result + requireInstance.hashCode();
         return result;
     }
 
     @Override
-    public boolean equals(Object obj) {
+    public boolean equals(final Object obj) {
         if (this == obj) {
             return true;
         }
@@ -187,17 +217,9 @@ public final class InstanceIdentifier implements InstanceIdentifierTypeDefinitio
             return false;
         }
         InstanceIdentifier other = (InstanceIdentifier) obj;
-        if (requireInstance != other.requireInstance) {
-            return false;
-        }
-        if (xpath == null) {
-            if (other.xpath != null) {
-                return false;
-            }
-        } else if (!xpath.equals(other.xpath)) {
-            return false;
-        }
-        return true;
+        return requireInstance.equals(other.requireInstance);
     }
 
+
+
 }
index 63caa24500d6e285a685d80bc1a64ebcb992cfdb..f88e7984a16909b0682c60350662b6acf5aa664a 100644 (file)
@@ -7,7 +7,7 @@
  */
 package org.opendaylight.yangtools.yang.model.util;
 
-import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.concepts.Immutable;
 
 /**
  * Implementation of Yang int16 built-in type. <br>
@@ -16,20 +16,21 @@ import org.opendaylight.yangtools.yang.common.QName;
  *
  * @see AbstractSignedInteger
  */
-public final class Int16 extends AbstractSignedInteger {
-    private static Int16 instance;
-    private static final QName NAME = BaseTypes.constructQName("int16");
+public final class Int16 extends AbstractSignedInteger implements Immutable {
     private static final String DESCRIPTION = "int16  represents integer values between -32768 and 32767, inclusively.";
 
+    private static final Int16 INSTANCE = new Int16();
+
     private Int16() {
-        super(NAME, DESCRIPTION, Short.MIN_VALUE, Short.MAX_VALUE, "");
+        super(BaseTypes.INT16_QNAME, DESCRIPTION, Short.MIN_VALUE, Short.MAX_VALUE, "");
     }
 
+    /**
+     * Returns default instance of int16 type.
+     * @return default instance of int16 type.
+     */
     public static Int16 getInstance() {
-        if (instance == null) {
-            instance = new Int16();
-        }
-        return instance;
+        return INSTANCE;
     }
 
     @Override
@@ -39,7 +40,7 @@ public final class Int16 extends AbstractSignedInteger {
 
     @Override
     public String toString() {
-        return "type " + NAME;
+        return "type " + BaseTypes.INT16_QNAME;
     }
 
 }
index b043d40a7ed7b443557e6a34fc3ccd379db0d1bb..d42768bc71b14b2ffc88008673a049d8dc4e5a85 100644 (file)
@@ -7,7 +7,7 @@
  */
 package org.opendaylight.yangtools.yang.model.util;
 
-import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.concepts.Immutable;
 
 /**
  * Implementation of Yang int32 built-in type. <br>
@@ -18,20 +18,22 @@ import org.opendaylight.yangtools.yang.common.QName;
  * @see AbstractSignedInteger
  *
  */
-public final class Int32 extends AbstractSignedInteger {
-    private static Int32 instance;
-    private static final QName NAME = BaseTypes.constructQName("int32");
+public final class Int32 extends AbstractSignedInteger implements Immutable {
     private static final String DESCRIPTION = "int32  represents integer values between -2147483648 and 2147483647, inclusively.";
 
+
+    private static final Int32 INSTANCE = new Int32();
+
     private Int32() {
-        super(Int32.NAME, Int32.DESCRIPTION, Integer.MIN_VALUE, Integer.MAX_VALUE, "");
+        super(BaseTypes.INT32_QNAME, Int32.DESCRIPTION, Integer.MIN_VALUE, Integer.MAX_VALUE, "");
     }
 
+    /**
+     * Returns default instance of int32 type.
+     * @return default instance of int32 type.
+     */
     public static Int32 getInstance() {
-        if (instance == null) {
-            instance = new Int32();
-        }
-        return instance;
+        return INSTANCE;
     }
 
     @Override
@@ -41,6 +43,7 @@ public final class Int32 extends AbstractSignedInteger {
 
     @Override
     public String toString() {
-        return "type " + NAME;
+        return "type " + BaseTypes.INT32_QNAME;
     }
+
 }
index 892a1436ee37441dc6d180b0b51cefa5c8b9b2b3..ea6830fa13e90572a7eb2e6c66d89ebec0976bd4 100644 (file)
@@ -7,7 +7,7 @@
  */
 package org.opendaylight.yangtools.yang.model.util;
 
-import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.concepts.Immutable;
 
 /**
  * Implementation of Yang int64 built-in type. <br>
@@ -16,20 +16,22 @@ import org.opendaylight.yangtools.yang.common.QName;
  * type is {@link Long}.
  *
  */
-public final class Int64 extends AbstractSignedInteger {
-    private static Int64 instance;
-    private static final QName NAME = BaseTypes.constructQName("int64");
+public final class Int64 extends AbstractSignedInteger implements Immutable {
     private static final String DESCRIPTION = "int64  represents integer values between -9223372036854775808 and 9223372036854775807, inclusively.";
 
     private Int64() {
-        super(NAME, DESCRIPTION, Long.MIN_VALUE, Long.MAX_VALUE, "");
+        super(BaseTypes.INT64_QNAME, DESCRIPTION, Long.MIN_VALUE, Long.MAX_VALUE, "");
     }
 
+
+    private static final Int64 INSTANCE = new Int64();
+
+    /**
+     * Returns default instance of int64 type.
+     * @return default instance of int64 type.
+     */
     public static Int64 getInstance() {
-        if (instance == null) {
-            instance = new Int64();
-        }
-        return instance;
+        return INSTANCE;
     }
 
     @Override
@@ -39,7 +41,6 @@ public final class Int64 extends AbstractSignedInteger {
 
     @Override
     public String toString() {
-        return "type " + NAME;
+        return "type " + BaseTypes.INT64_QNAME;
     }
-
 }
index 5df2db696f39a1391fd71441016c93dde6d6df0e..61d7a469491e3ee910fe29ebb332e9ae085c989f 100644 (file)
@@ -7,7 +7,7 @@
  */
 package org.opendaylight.yangtools.yang.model.util;
 
-import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.concepts.Immutable;
 
 /**
  * Implementation of Yang int8 built-in type. <br>
@@ -16,20 +16,21 @@ import org.opendaylight.yangtools.yang.common.QName;
  *
  * @see AbstractSignedInteger
  */
-public final class Int8 extends AbstractSignedInteger {
-    private static Int8 instance;
-    private static final QName NAME = BaseTypes.constructQName("int8");
+public final class Int8 extends AbstractSignedInteger implements Immutable {
     private static final String DESCRIPTION = "represents integer values between -128 and 127, inclusively.";
 
     private Int8() {
-        super(NAME, DESCRIPTION, Byte.MIN_VALUE, Byte.MAX_VALUE, "");
+        super(BaseTypes.INT8_QNAME, DESCRIPTION, Byte.MIN_VALUE, Byte.MAX_VALUE, "");
     }
 
+    private static final Int8 INSTANCE = new Int8();
+
+    /**
+     * Returns default instance of int8 type.
+     * @return default instance of int8 type.
+     */
     public static Int8 getInstance() {
-        if (instance == null) {
-            instance = new Int8();
-        }
-        return instance;
+        return INSTANCE;
     }
 
     @Override
@@ -39,7 +40,7 @@ public final class Int8 extends AbstractSignedInteger {
 
     @Override
     public String toString() {
-        return "type " + NAME;
+        return "type " + BaseTypes.INT8_QNAME;
     }
 
 }
index 8ef325cfdf3bbc9aba90840b8b404d2c4bcdb0d9..65fd92458f72564de1f9fd084490854fc4c50498 100644 (file)
@@ -17,6 +17,8 @@ import org.opendaylight.yangtools.yang.model.api.Status;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.type.LeafrefTypeDefinition;
 
+import com.google.common.base.Preconditions;
+
 /**
  * The <code>default</code> implementation of Instance Leafref Type Definition
  * interface.
@@ -30,9 +32,21 @@ public final class Leafref implements LeafrefTypeDefinition {
     private static final String REF = "https://tools.ietf.org/html/rfc6020#section-9.9";
 
     private final RevisionAwareXPath xpath;
+    private final SchemaPath path;
 
+    @Deprecated
     public Leafref(final RevisionAwareXPath xpath) {
-        this.xpath = xpath;
+        this(PATH,xpath);
+
+    }
+
+    private Leafref(final SchemaPath path, final RevisionAwareXPath target) {
+        this.path = Preconditions.checkNotNull(path,"path must be specified");
+        this.xpath = Preconditions.checkNotNull(target,"target must not be null.");
+    }
+
+    public static Leafref create(final SchemaPath path,final RevisionAwareXPath target) {
+        return new Leafref(path,target);
     }
 
     @Override
@@ -57,7 +71,7 @@ public final class Leafref implements LeafrefTypeDefinition {
 
     @Override
     public SchemaPath getPath() {
-        return PATH;
+        return path;
     }
 
     @Override
@@ -94,7 +108,7 @@ public final class Leafref implements LeafrefTypeDefinition {
     }
 
     @Override
-    public boolean equals(Object obj) {
+    public boolean equals(final Object obj) {
         if (this == obj) {
             return true;
         }
diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/LengthConstraintImpl.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/LengthConstraintImpl.java
new file mode 100644 (file)
index 0000000..bbab950
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+ * 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.model.util;
+
+import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+/**
+ * {@link Immutable} implementation of {@link LengthConstraint}.
+ *
+ * Length constraint based on supplied parameters with additional behaviour:
+ *
+ * <ul>
+ * <li>{@link LengthConstraint#getErrorAppTag()} returns
+ * <code>length-out-of-specified-bounds</code>
+ * <li>{@link LengthConstraint#getErrorMessage() returns <code>The argument is
+ * out of bounds &lt;<i>min</i>, <i>max</i> &gt;</code>
+ * </ul
+ */
+final class LengthConstraintImpl implements LengthConstraint, Immutable {
+
+    private final Number min;
+    private final Number max;
+
+    private final String description;
+    private final String reference;
+
+    private final String errorAppTag;
+    private final String errorMessage;
+
+    LengthConstraintImpl(final Number min, final Number max, final Optional<String> description,
+            final Optional<String> reference) {
+        super();
+        this.min = Preconditions.checkNotNull(min, "min must not be null.");
+        this.max = Preconditions.checkNotNull(max, "max must not be null");
+        this.description = description.orNull();
+        this.reference = reference.orNull();
+
+        this.errorAppTag = "length-out-of-specified-bounds";
+        this.errorMessage = "The argument is out of bounds <" + min + ", " + max + ">";
+    }
+
+    @Override
+    public String getDescription() {
+        return description;
+    }
+
+    @Override
+    public String getErrorAppTag() {
+        return errorAppTag;
+    }
+
+    @Override
+    public String getErrorMessage() {
+        return errorMessage;
+    }
+
+    @Override
+    public String getReference() {
+        return reference;
+    }
+
+    @Override
+    public Number getMin() {
+        return min;
+    }
+
+    @Override
+    public Number getMax() {
+        return max;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((description == null) ? 0 : description.hashCode());
+        result = prime * result + errorAppTag.hashCode();
+        result = prime * result + errorMessage.hashCode();
+        result = prime * result + max.hashCode();
+        result = prime * result + min.hashCode();
+        result = prime * result + ((reference == null) ? 0 : reference.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final LengthConstraintImpl other = (LengthConstraintImpl) obj;
+        if (description == null) {
+            if (other.description != null) {
+                return false;
+            }
+        } else if (!description.equals(other.description)) {
+            return false;
+        }
+        if (errorAppTag == null) {
+            if (other.errorAppTag != null) {
+                return false;
+            }
+        } else if (!errorAppTag.equals(other.errorAppTag)) {
+            return false;
+        }
+        if (errorMessage == null) {
+            if (other.errorMessage != null) {
+                return false;
+            }
+        } else if (!errorMessage.equals(other.errorMessage)) {
+            return false;
+        }
+        if (max != other.max) {
+            return false;
+        }
+        if (min != other.min) {
+            return false;
+        }
+        if (reference == null) {
+            if (other.reference != null) {
+                return false;
+            }
+        } else if (!reference.equals(other.reference)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("LengthConstraintImpl [min=");
+        builder.append(min);
+        builder.append(", max=");
+        builder.append(max);
+        builder.append(", description=");
+        builder.append(description);
+        builder.append(", errorAppTag=");
+        builder.append(errorAppTag);
+        builder.append(", reference=");
+        builder.append(reference);
+        builder.append(", errorMessage=");
+        builder.append(errorMessage);
+        builder.append("]");
+        return builder.toString();
+    }
+}
\ No newline at end of file
diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/PatternConstraintImpl.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/PatternConstraintImpl.java
new file mode 100644 (file)
index 0000000..8ab67a7
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * 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.model.util;
+
+import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+/**
+ * {@link Immutable} implementation of {@link PatternConstraint}
+ *
+ * Creates an instance of Range constraint based on supplied parameters with
+ * additional behaviour:
+ *
+ * <ul>
+ * <li>{@link PatternConstraint#getErrorAppTag()} returns
+ * <code>invalid-regular-expression</code>
+ * </ul>
+ *
+ */
+final class PatternConstraintImpl implements PatternConstraint, Immutable {
+
+    private final String regex;
+    private final String description;
+    private final String reference;
+
+    private final String errorAppTag;
+    private final String errorMessage;
+
+    public PatternConstraintImpl(final String regex, final Optional<String> description,
+            final Optional<String> reference) {
+        super();
+        this.regex = Preconditions.checkNotNull(regex, "regex must not be null.");
+        this.description = description.orNull();
+        this.reference = reference.orNull();
+
+        // FIXME: Lookup better suitable error tag.
+        errorAppTag = "invalid-regular-expression";
+        // TODO: add erro message
+        errorMessage = "";
+    }
+
+    @Override
+    public String getDescription() {
+        return description;
+    }
+
+    @Override
+    public String getErrorAppTag() {
+        return errorAppTag;
+    }
+
+    @Override
+    public String getErrorMessage() {
+        return errorMessage;
+    }
+
+    @Override
+    public String getReference() {
+        return reference;
+    }
+
+    @Override
+    public String getRegularExpression() {
+        return regex;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((description == null) ? 0 : description.hashCode());
+        result = prime * result + ((errorAppTag == null) ? 0 : errorAppTag.hashCode());
+        result = prime * result + ((errorMessage == null) ? 0 : errorMessage.hashCode());
+        result = prime * result + ((reference == null) ? 0 : reference.hashCode());
+        result = prime * result + regex.hashCode();
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final PatternConstraintImpl other = (PatternConstraintImpl) obj;
+        if (description == null) {
+            if (other.description != null) {
+                return false;
+            }
+        } else if (!description.equals(other.description)) {
+            return false;
+        }
+        if (errorAppTag == null) {
+            if (other.errorAppTag != null) {
+                return false;
+            }
+        } else if (!errorAppTag.equals(other.errorAppTag)) {
+            return false;
+        }
+        if (errorMessage == null) {
+            if (other.errorMessage != null) {
+                return false;
+            }
+        } else if (!errorMessage.equals(other.errorMessage)) {
+            return false;
+        }
+        if (reference == null) {
+            if (other.reference != null) {
+                return false;
+            }
+        } else if (!reference.equals(other.reference)) {
+            return false;
+        }
+        if (regex == null) {
+            if (other.regex != null) {
+                return false;
+            }
+        } else if (!regex.equals(other.regex)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder builder = new StringBuilder();
+        builder.append("PatternConstraintImpl [regex=");
+        builder.append(regex);
+        builder.append(", description=");
+        builder.append(description);
+        builder.append(", reference=");
+        builder.append(reference);
+        builder.append(", errorAppTag=");
+        builder.append(errorAppTag);
+        builder.append(", errorMessage=");
+        builder.append(errorMessage);
+        builder.append("]");
+        return builder.toString();
+    }
+}
\ No newline at end of file
diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/RangeConstraintImpl.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/RangeConstraintImpl.java
new file mode 100644 (file)
index 0000000..70acbc8
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * 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.model.util;
+
+import org.opendaylight.yangtools.concepts.Immutable;
+import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
+import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+/**
+ * {@link Immutable} implementation of {@link LengthConstraint}.
+ *
+ * Range constraint based on supplied parameters with additional behaviour:
+ *
+ * <ul>
+ * <li>{@link RangeConstraint#getErrorAppTag()} returns
+ * <code>range-out-of-specified-bounds</code>
+ * <li>{@link RangeConstraint#getErrorMessage() returns <code>The argument is
+ * out of bounds &lt;<i>min</i>, <i>max</i> &gt;</code>
+ * </ul>
+ */
+final class RangeConstraintImpl implements RangeConstraint, Immutable {
+    private final Number min;
+    private final Number max;
+
+    private final String description;
+    private final String reference;
+
+    private final String errorAppTag;
+    private final String errorMessage;
+
+    RangeConstraintImpl(final Number min, final Number max, final Optional<String> description,
+            final Optional<String> reference) {
+        super();
+        this.min = Preconditions.checkNotNull(min, "min must not be null.");
+        this.max = Preconditions.checkNotNull(max, "max must not be null.");
+        this.description = description.orNull();
+        this.reference = reference.orNull();
+
+        this.errorAppTag = "range-out-of-specified-bounds";
+        this.errorMessage = "The argument is out of bounds <" + min + ", " + max + ">";
+    }
+
+    @Override
+    public String getDescription() {
+        return description;
+    }
+
+    @Override
+    public String getErrorAppTag() {
+        return errorAppTag;
+    }
+
+    @Override
+    public String getErrorMessage() {
+        return errorMessage;
+    }
+
+    @Override
+    public String getReference() {
+        return reference;
+    }
+
+    @Override
+    public Number getMin() {
+        return min;
+    }
+
+    @Override
+    public Number getMax() {
+        return max;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((description == null) ? 0 : description.hashCode());
+        result = prime * result + errorAppTag.hashCode();
+        result = prime * result + errorMessage.hashCode();
+        result = prime * result + max.hashCode();
+        result = prime * result + min.hashCode();
+        result = prime * result + ((reference == null) ? 0 : reference.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (getClass() != obj.getClass()) {
+            return false;
+        }
+        final RangeConstraintImpl other = (RangeConstraintImpl) obj;
+        if (description == null) {
+            if (other.description != null) {
+                return false;
+            }
+        } else if (!description.equals(other.description)) {
+            return false;
+        }
+        if (max == null) {
+            if (other.max != null) {
+                return false;
+            }
+        } else if (!max.equals(other.max)) {
+            return false;
+        }
+        if (min == null) {
+            if (other.min != null) {
+                return false;
+            }
+        } else if (!min.equals(other.min)) {
+            return false;
+        }
+        if (reference == null) {
+            if (other.reference != null) {
+                return false;
+            }
+        } else if (!reference.equals(other.reference)) {
+            return false;
+        }
+        return true;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder builder = new StringBuilder();
+        builder.append("RangeConstraintImpl [min=");
+        builder.append(min);
+        builder.append(", max=");
+        builder.append(max);
+        builder.append(", description=");
+        builder.append(description);
+        builder.append(", reference=");
+        builder.append(reference);
+        builder.append(", errorAppTag=");
+        builder.append(errorAppTag);
+        builder.append(", errorMessage=");
+        builder.append(errorMessage);
+        builder.append("]");
+        return builder.toString();
+    }
+}
\ No newline at end of file
index c5852696e4ec14b9c516d00aae66b1de5397a72b..3ef6d5a64e12eb5a4b08ebdf6ab94f5acbd11f52 100644 (file)
@@ -10,9 +10,9 @@ package org.opendaylight.yangtools.yang.model.util;
 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
 
 /**
- * The <code>default</code> implementation of Instance Rewision Aware XPath
+ * The <code>helper</code> implementation of Instance Rewision Aware XPath
  * interface.
- * 
+ *
  * @see RevisionAwareXPath
  */
 public class RevisionAwareXPathImpl implements RevisionAwareXPath {
@@ -23,7 +23,7 @@ public class RevisionAwareXPathImpl implements RevisionAwareXPath {
     private static final int HASH_BOOLEAN_TRUE = 1231;
     private static final int HASH_BOOLEAN_FALSE = 1237;
 
-    public RevisionAwareXPathImpl(String xpath, boolean absolute) {
+    public RevisionAwareXPathImpl(final String xpath, final boolean absolute) {
         this.xpath = xpath;
         this.absolute = absolute;
     }
@@ -43,7 +43,7 @@ public class RevisionAwareXPathImpl implements RevisionAwareXPath {
     }
 
     @Override
-    public boolean equals(Object obj) {
+    public boolean equals(final Object obj) {
         if (this == obj) {
             return true;
         }
index a6623b6d2d2fdc506556ef5f62a6ce9229d3c8bc..857e6a4d030037e89bc8dc7b01607149542a463c 100644 (file)
@@ -7,10 +7,10 @@
  */
 package org.opendaylight.yangtools.yang.model.util;
 
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
+import org.opendaylight.yangtools.concepts.Immutable;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
 import org.opendaylight.yangtools.yang.model.api.Status;
@@ -19,15 +19,16 @@ import org.opendaylight.yangtools.yang.model.api.type.LengthConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
 
+import com.google.common.base.Optional;
+
 /**
  * The <code>default</code> implementation of String Type Definition interface.
  *
  * @see StringTypeDefinition
  */
-public final class StringType implements StringTypeDefinition {
-    private static final StringType INSTANCE = new StringType();
-    private final QName name = BaseTypes.constructQName("string");
-    private final SchemaPath path = SchemaPath.create(Collections.singletonList(name), true);
+public final class StringType implements StringTypeDefinition, Immutable {
+    private static final QName NAME = BaseTypes.STRING_QNAME;
+    private static final SchemaPath PATH = SchemaPath.create(Collections.singletonList(NAME), true);
     private static final String DEFAULT_VALUE = "";
     private static final String DESCRIPTION = "";
     private static final String REFERENCE = "";
@@ -35,13 +36,13 @@ public final class StringType implements StringTypeDefinition {
     private final List<PatternConstraint> patterns;
     private static final String UNITS = "";
 
+    private static final StringType INSTANCE = new StringType();
+
     /**
      * Default Constructor.
      */
     private StringType() {
-        final List<LengthConstraint> constraints = new ArrayList<LengthConstraint>();
-        constraints.add(BaseConstraints.lengthConstraint(0, Integer.MAX_VALUE, "", ""));
-        lengthStatements = Collections.unmodifiableList(constraints);
+        lengthStatements = Collections.singletonList(BaseConstraints.newLengthConstraint(0, Integer.MAX_VALUE, Optional.of(""), Optional.of("")));
         patterns = Collections.emptyList();
     }
 
@@ -89,7 +90,7 @@ public final class StringType implements StringTypeDefinition {
      */
     @Override
     public QName getQName() {
-        return name;
+        return NAME;
     }
 
     /*
@@ -99,7 +100,7 @@ public final class StringType implements StringTypeDefinition {
      */
     @Override
     public SchemaPath getPath() {
-        return path;
+        return PATH;
     }
 
     /*
@@ -166,8 +167,8 @@ public final class StringType implements StringTypeDefinition {
         final int prime = 31;
         int result = 1;
         result = prime * result + ((lengthStatements == null) ? 0 : lengthStatements.hashCode());
-        result = prime * result + ((name == null) ? 0 : name.hashCode());
-        result = prime * result + ((path == null) ? 0 : path.hashCode());
+        result = prime * result + NAME.hashCode();
+        result = prime * result + PATH.hashCode();
         result = prime * result + ((patterns == null) ? 0 : patterns.hashCode());
         return result;
     }
@@ -191,20 +192,6 @@ public final class StringType implements StringTypeDefinition {
         } else if (!lengthStatements.equals(other.lengthStatements)) {
             return false;
         }
-        if (name == null) {
-            if (other.name != null) {
-                return false;
-            }
-        } else if (!name.equals(other.name)) {
-            return false;
-        }
-        if (path == null) {
-            if (other.path != null) {
-                return false;
-            }
-        } else if (!path.getPath().equals(other.path.getPath())) {
-            return false;
-        }
         if (patterns == null) {
             if (other.patterns != null) {
                 return false;
@@ -219,9 +206,9 @@ public final class StringType implements StringTypeDefinition {
     public String toString() {
         StringBuilder builder = new StringBuilder();
         builder.append("StringType [name=");
-        builder.append(name);
+        builder.append(NAME);
         builder.append(", path=");
-        builder.append(path);
+        builder.append(PATH);
         builder.append(", defaultValue=");
         builder.append(DEFAULT_VALUE);
         builder.append(", description=");
index 4c386c48d5b3988f083bb794f2840e745158746f..d557449220a153d725772905490748b080c8fe35 100644 (file)
@@ -7,7 +7,7 @@
  */
 package org.opendaylight.yangtools.yang.model.util;
 
-import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.concepts.Immutable;
 
 /**
  * Implementation of Yang uint16 built-in type. <br>
@@ -15,21 +15,18 @@ import org.opendaylight.yangtools.yang.common.QName;
  * counterpart of Yang uint16 built-in type is {@link Integer}.
  *
  */
-public final class Uint16 extends AbstractUnsignedInteger {
+public final class Uint16 extends AbstractUnsignedInteger implements Immutable {
     public static final int MAX_VALUE = 65535;
-    private static Uint16 instance;
-    private static final QName NAME = BaseTypes.constructQName("uint16");
     private static final String DESCRIPTION = "uint16 represents integer values between 0 and 65535, inclusively.";
 
+    private static Uint16 INSTANCE = new Uint16();
+
     private Uint16() {
-        super(NAME, DESCRIPTION, MAX_VALUE, "");
+        super(BaseTypes.UINT16_QNAME, DESCRIPTION, MAX_VALUE, "");
     }
 
     public static Uint16 getInstance() {
-        if (instance == null) {
-            instance = new Uint16();
-        }
-        return instance;
+        return INSTANCE;
     }
 
     @Override
@@ -39,7 +36,7 @@ public final class Uint16 extends AbstractUnsignedInteger {
 
     @Override
     public String toString() {
-        return "type " + NAME;
+        return "type " + BaseTypes.UINT16_QNAME;
     }
 
 }
index dd3183d51bf028fdc605e3381f28fe7920224122..aef0f8fac27ff60928a27d9b251b772c0fab3f54 100644 (file)
@@ -7,28 +7,26 @@
  */
 package org.opendaylight.yangtools.yang.model.util;
 
-import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.concepts.Immutable;
 
 /**
  * Implementation of Yang uint32 built-in type. <br>
  * uint32 represents integer values between 0 and 4294967295, inclusively.
  *
  */
-public final class Uint32 extends AbstractUnsignedInteger {
+public final class Uint32 extends AbstractUnsignedInteger implements Immutable {
     public static final long MAX_VALUE = 4294967295L;
-    private static Uint32 instance;
-    private static final QName NAME = BaseTypes.constructQName("uint32");
     private static final String DESCRIPTION = "uint32 represents integer values between 0 and 4294967295, inclusively.";
 
+    private static final Uint32 INSTANCE = new Uint32();
+
+
     private Uint32() {
-        super(NAME, DESCRIPTION, MAX_VALUE, "");
+        super(BaseTypes.UINT32_QNAME, DESCRIPTION, MAX_VALUE, "");
     }
 
     public static Uint32 getInstance() {
-        if (instance == null) {
-            instance = new Uint32();
-        }
-        return instance;
+        return INSTANCE;
     }
 
     @Override
@@ -38,7 +36,7 @@ public final class Uint32 extends AbstractUnsignedInteger {
 
     @Override
     public String toString() {
-        return "type " + NAME;
+        return "type " + BaseTypes.UINT32_QNAME;
     }
 
 }
index 555b76f5feb96ac74a99ee4d285a5edb707b9bae..3ec9d25369eb3c966fab370a661cc0a8aea750ab 100644 (file)
@@ -9,7 +9,7 @@ package org.opendaylight.yangtools.yang.model.util;
 
 import java.math.BigInteger;
 
-import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.concepts.Immutable;
 
 /**
  * Implementation of Yang uint64 built-in type. <br>
@@ -18,21 +18,18 @@ import org.opendaylight.yangtools.yang.common.QName;
  * {@link BigInteger}.
  *
  */
-public final class Uint64 extends AbstractUnsignedInteger {
+public final class Uint64 extends AbstractUnsignedInteger implements Immutable {
     public static final BigInteger MAX_VALUE = new BigInteger("18446744073709551615");
-    private static Uint64 instance;
-    private static final QName NAME = BaseTypes.constructQName("uint64");
     private static final String DESCRIPTION = "uint64 represents integer values between 0 and 18446744073709551615, inclusively.";
 
+    private static final Uint64 INSTANCE = new Uint64();
+
     private Uint64() {
-        super(NAME, DESCRIPTION, MAX_VALUE, "");
+        super(BaseTypes.UINT64_QNAME, DESCRIPTION, MAX_VALUE, "");
     }
 
     public static Uint64 getInstance() {
-        if (instance == null) {
-            instance = new Uint64();
-        }
-        return instance;
+        return INSTANCE;
     }
 
     @Override
@@ -42,7 +39,7 @@ public final class Uint64 extends AbstractUnsignedInteger {
 
     @Override
     public String toString() {
-        return "type " + NAME;
+        return "type " + BaseTypes.UINT64_QNAME;
     }
 
 }
index 2212585f0238e69746df6a75f79b2e86424077cd..f44ba754a7d62c8c94310382c1e0b2c569799f62 100644 (file)
@@ -7,7 +7,7 @@
  */
 package org.opendaylight.yangtools.yang.model.util;
 
-import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.concepts.Immutable;
 
 /**
  * Implementation of Yang uint8 built-in type. <br>
@@ -15,21 +15,18 @@ import org.opendaylight.yangtools.yang.common.QName;
  *
  * @see AbstractUnsignedInteger
  */
-public final class Uint8 extends AbstractUnsignedInteger {
+public final class Uint8 extends AbstractUnsignedInteger implements Immutable {
     public static final int MAX_VALUE = 255;
-    private static Uint8 instance;
-    private static final QName NAME = BaseTypes.constructQName("uint8");
     private static final String DESCRIPTION = "uint8  represents integer values between 0 and 255, inclusively.";
 
+    private static final Uint8 INSTANCE = new Uint8();
+
     private Uint8() {
-        super(NAME, DESCRIPTION, MAX_VALUE, "");
+        super(BaseTypes.UINT8_QNAME, DESCRIPTION, MAX_VALUE, "");
     }
 
     public static Uint8 getInstance() {
-        if (instance == null) {
-            instance = new Uint8();
-        }
-        return instance;
+        return INSTANCE;
     }
 
     @Override
@@ -39,7 +36,7 @@ public final class Uint8 extends AbstractUnsignedInteger {
 
     @Override
     public String toString() {
-        return "type " + NAME;
+        return "type " + BaseTypes.UINT8_QNAME;
     }
 
 }
index 99390b09803a438152bba18f0cee6ceaf8e196b5..3386bb720f5e238d8760f6b1cc7bc765070d3e7e 100644 (file)
@@ -17,18 +17,23 @@ import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
 
+import com.google.common.base.Preconditions;
+import com.google.common.collect.ImmutableList;
+
 public final class UnionType implements UnionTypeDefinition {
-    private final QName name = BaseTypes.constructQName("union");
-    private final SchemaPath path = BaseTypes.schemaPath(name);
+    private final SchemaPath path = SchemaPath.create(Collections.singletonList(BaseTypes.UNION_QNAME),true);
     private static final String DESCRIPTION = "The union built-in type represents a value that corresponds to one of its member types.";
     private static final String REFERENCE = "https://tools.ietf.org/html/rfc6020#section-9.12";
     private final List<TypeDefinition<?>> types;
 
-    public UnionType(List<TypeDefinition<?>> types) {
-        if (types == null) {
-            throw new IllegalArgumentException("When the type is 'union', the 'type' statement MUST be present.");
-        }
-        this.types = types;
+    @Deprecated
+    public UnionType(final List<TypeDefinition<?>> types) {
+        Preconditions.checkNotNull(types,"When the type is 'union', the 'type' statement MUST be present.");
+        this.types = ImmutableList.copyOf(types);
+    }
+
+    public static UnionType create(final List<TypeDefinition<?>> types) {
+        return new UnionType(types);
     }
 
     @Override
@@ -48,7 +53,7 @@ public final class UnionType implements UnionTypeDefinition {
 
     @Override
     public QName getQName() {
-        return name;
+        return BaseTypes.UNION_QNAME;
     }
 
     @Override
@@ -90,7 +95,7 @@ public final class UnionType implements UnionTypeDefinition {
     }
 
     @Override
-    public boolean equals(Object obj) {
+    public boolean equals(final Object obj) {
         if (this == obj) {
             return true;
         }
@@ -111,7 +116,7 @@ public final class UnionType implements UnionTypeDefinition {
     public String toString() {
         StringBuilder builder = new StringBuilder();
         builder.append("type ");
-        builder.append(name);
+        builder.append(BaseTypes.UNION_QNAME);
         builder.append(" (types=[");
         for (TypeDefinition<?> td : types) {
             builder.append(", " + td.getQName().getLocalName());
index 23bb8395ca059cf83eeb61e7863a3e4d977d43d2..2e23b81db600af9e5db25af9b484a543aee50527 100644 (file)
@@ -19,6 +19,16 @@ import org.opendaylight.yangtools.yang.model.api.type.PatternConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.RangeConstraint;
 import org.opendaylight.yangtools.yang.model.api.type.UnknownTypeDefinition;
 
+/**
+ * Utility implementation of unknown type definition.
+ *
+ * Unknown type definition is derived type, for
+ * which base built-in type is not yet known. This types
+ * are possible during parsing and resolving of YANG model
+ * without all requisites allready processed.
+ *
+ *
+ */
 public final class UnknownType implements UnknownTypeDefinition {
 
     private final QName name;
@@ -66,12 +76,12 @@ public final class UnknownType implements UnknownTypeDefinition {
             this.path = BaseTypes.schemaPath(name);
         }
 
-        public Builder description(String description) {
+        public Builder description(final String description) {
             this.description = description;
             return this;
         }
 
-        public Builder reference(String reference) {
+        public Builder reference(final String reference) {
             this.reference = reference;
             return this;
         }
@@ -106,12 +116,12 @@ public final class UnknownType implements UnknownTypeDefinition {
             return this;
         }
 
-        public Builder status(Status status) {
+        public Builder status(final Status status) {
             this.status = status;
             return this;
         }
 
-        public Builder units(String units) {
+        public Builder units(final String units) {
             this.units = units;
             return this;
         }
@@ -126,7 +136,7 @@ public final class UnknownType implements UnknownTypeDefinition {
         }
     }
 
-    private UnknownType(Builder builder) {
+    private UnknownType(final Builder builder) {
         this.name = builder.name;
         this.path = builder.path;
         this.description = builder.description;
@@ -296,7 +306,7 @@ public final class UnknownType implements UnknownTypeDefinition {
     }
 
     @Override
-    public boolean equals(Object obj) {
+    public boolean equals(final Object obj) {
         if (this == obj) {
             return true;
         }
index f156dafabcfe7ee550d6d8a3d59fb86e3f4cf30c..98c63d022ba6a8a3a734a7b03897e8526e174afc 100644 (file)
@@ -7,83 +7,40 @@
  */
 package org.opendaylight.yangtools.yang.model.util;
 
-import java.util.HashSet;
-import java.util.Set;
-
 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
 
+/**
+ * Utility class which provides various helper methods for working with YANG
+ * built-in types.
+ *
+ * @deprecated Use {@link BaseTypes} instead.
+ */
+@Deprecated
 public final class YangTypesConverter {
-    private static final Set<String> BASE_YANG_TYPES = new HashSet<String>();
-
     /**
      * It isn't desirable to create the instances of this class
      */
     private YangTypesConverter() {
     }
 
-    static {
-        BASE_YANG_TYPES.add("binary");
-        BASE_YANG_TYPES.add("bits");
-        BASE_YANG_TYPES.add("boolean");
-        BASE_YANG_TYPES.add("decimal64");
-        BASE_YANG_TYPES.add("empty");
-        BASE_YANG_TYPES.add("enumeration");
-        BASE_YANG_TYPES.add("identityref");
-        BASE_YANG_TYPES.add("instance-identifier");
-        BASE_YANG_TYPES.add("int8");
-        BASE_YANG_TYPES.add("int16");
-        BASE_YANG_TYPES.add("int32");
-        BASE_YANG_TYPES.add("int64");
-        BASE_YANG_TYPES.add("leafref");
-        BASE_YANG_TYPES.add("string");
-        BASE_YANG_TYPES.add("uint8");
-        BASE_YANG_TYPES.add("uint16");
-        BASE_YANG_TYPES.add("uint32");
-        BASE_YANG_TYPES.add("uint64");
-        BASE_YANG_TYPES.add("union");
-    }
-
-    public static boolean isBaseYangType(String type) {
-        return BASE_YANG_TYPES.contains(type);
+    @Deprecated
+    public static boolean isBaseYangType(final String type) {
+        return BaseTypes.isYangBuildInType(type);
     }
 
-    public static TypeDefinition<?> javaTypeForBaseYangType(String typeName) {
-        TypeDefinition<?> type = null;
-
-        if (typeName.startsWith("int")) {
-            if ("int8".equals(typeName)) {
-                type = Int8.getInstance();
-            } else if ("int16".equals(typeName)) {
-                type = Int16.getInstance();
-            } else if ("int32".equals(typeName)) {
-                type = Int32.getInstance();
-            } else if ("int64".equals(typeName)) {
-                type = Int64.getInstance();
-            }
-        } else if (typeName.startsWith("uint")) {
-            if ("uint8".equals(typeName)) {
-                type = Uint8.getInstance();
-            } else if ("uint16".equals(typeName)) {
-                type = Uint16.getInstance();
-            } else if ("uint32".equals(typeName)) {
-                type = Uint32.getInstance();
-            } else if ("uint64".equals(typeName)) {
-                type = Uint64.getInstance();
-            }
-        } else if ("string".equals(typeName)) {
-            type = StringType.getInstance();
-        } else if ("binary".equals(typeName)) {
-            type = BinaryType.getInstance();
-        } else if ("boolean".equals(typeName)) {
-            type = BooleanType.getInstance();
-        } else if ("empty".equals(typeName)) {
-            type = EmptyType.getInstance();
-        } else if ("instance-identifier".equals(typeName)) {
-            // FIXME
-            type = new InstanceIdentifier(null, true);
-        }
-
-        return type;
+    /**
+     *
+     * Returns default instance of built-in type for supplied string.
+     *
+     * @param typeName
+     * @return default instance of built-in type for supplied string or null, if
+     *         default instance does not exist.
+     *
+     * @deprecated Use {@link BaseTypes#defaultBaseTypeFor(String)} instead.
+     */
+    @Deprecated
+    public static TypeDefinition<?> javaTypeForBaseYangType(final String typeName) {
+        return BaseTypes.defaultBaseTypeFor(typeName).orNull();
     }
 
 }
diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/package-info.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/package-info.java
new file mode 100644 (file)
index 0000000..ec30f79
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * 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
+ */
+/**
+ * Utility classes and implementations for concepts defined in yang-model-api.
+ *
+ *
+ * <h2>Base Types</h2>
+ *
+ * YANG specification defines several base types, for which YANG model does not
+ * exists, but have same properties as derived types. This package provides
+ * implementation of {@link org.opendaylight.yangtools.yang.model.api.TypeDefinition}
+ * interface and it's subinterfaces which represent YANG base types and
+ * types derived from them.
+ * <p>
+ * YANG Specification implicitly defines two types of base types - ones with default version,
+ * and ones which needs to be derived.
+ *
+ * <h3>Base built-in types with default instance and semantics</h3>
+ *
+ *    <dl>
+ *       <dt>empty</dt>
+ *       <dd>A leaf that does not have any value - {@link org.opendaylight.yangtools.yang.model.util.EmptyType}</dd>
+ *       <dt>binary</dt>
+ *       <dd>Any binary data - {@link org.opendaylight.yangtools.yang.model.util.BinaryType}
+ *       <dt>boolean</dt>
+ *       <dd>"true" or "false" - {@link org.opendaylight.yangtools.yang.model.util.BinaryType}</dd>
+ *       <dt>int8</dt>
+ *       <dd>8-bit signed integer - {@link org.opendaylight.yangtools.yang.model.util.Int8}</dd>
+ *       <dt>int16</dt>
+ *       <dd>16-bit signed integer - {@link org.opendaylight.yangtools.yang.model.util.Int16}</dd>
+ *       <dt>int32</dt>
+ *       <dd>32-bit signed integer - {@link org.opendaylight.yangtools.yang.model.util.Int32}</dd>
+ *       <dt>int64</dt>
+ *       <dd>64-bit signed integer - {@link org.opendaylight.yangtools.yang.model.util.Int64}</dd>
+ *       <dt>uint8</dt>
+ *       <dd>8-bit unsigned integer -{@link org.opendaylight.yangtools.yang.model.util.Uint8}</dd>
+ *       <dt>uint16</dt>
+ *       <dd>16-bit unsigned integer - {@link org.opendaylight.yangtools.yang.model.util.Int16}</dd>
+ *       <dt>uint32</dt>
+ *       <dd>32-bit unsigned integer - {@link org.opendaylight.yangtools.yang.model.util.Int32}</dd>
+ *       <dt>uint64</dt>
+ *       <dd>64-bit unsigned integer -{@link org.opendaylight.yangtools.yang.model.util.Int64}</dd>
+ *       <dt>instance-identifier</dt>
+ *       <dd>References a data tree node - {@link org.opendaylight.yangtools.yang.model.util.InstanceIdentifier}</dd>
+ *       <dt>string</dt>
+ *       <dd>{@link org.opendaylight.yangtools.yang.model.util.StringType}</dd>
+ *     </dl>
+ *
+ * Common trait of base types with default instance is, that there is no requirement
+ * for user input in YANG schema to further modify this types.
+ * <p>
+ * The implementation classes for these base types contains static method <code>getInstance()</code>
+ * which provides reusable {@link org.opendaylight.yangtools.concepts.Immutable} instance of type.
+ *
+ * <h3>Base built-in types without default instance</h3>
+ *
+ *     <dl>
+ *       <dt>bits</dt>
+ *       <dd>A set of bits or flags - {@link org.opendaylight.yangtools.yang.model.util.BitsType}</dd>
+ *       <dt>decimal64</dt>
+ *       <dd>64-bit signed decimal number - {@link org.opendaylight.yangtools.yang.model.util.Decimal64}</dd>
+ *       <dt>enumeration</dt>
+ *       <dd>Enumerated strings - {@link org.opendaylight.yangtools.yang.model.util.EnumerationType}</dd>
+ *       <dt>union</dt>
+ *       <dd>Choice of member types - {@link org.opendaylight.yangtools.yang.model.util.UnionType}</dd>
+ *       <dt>identity-ref</dt>
+ *       <dd>A reference to an abstract identity - {@link org.opendaylight.yangtools.yang.model.util.IdentityrefType}</dd>
+ *       <dt>leafref</dt>
+ *       <dd>A reference to a leaf instance - {@link org.opendaylight.yangtools.yang.model.util.Leafref}</dd>
+ *     </dl>
+ *
+ * Common trait of these base types without default instance is, that they require
+ * user input in YANG schema to create instance of this types, and may have infinity number of
+ * possible permutations.
+ * <p>
+ * The implementations have static factory method <code>create(SchemaPath,...)</code>
+ * which provides {@link org.opendaylight.yangtools.concepts.Immutable} instance of type.
+ *
+ */
+package org.opendaylight.yangtools.yang.model.util;
\ No newline at end of file
index bbe870bd76951ba5a6e3a1b2f64801b10960a72f..6b1d6c61232e0221c718d15a9a16a95a0b03df54 100644 (file)
@@ -8,44 +8,68 @@
 package org.opendaylight.yangtools.yang.model.util.repo;
 
 import org.opendaylight.yangtools.concepts.Delegator;
+
+import com.google.common.annotations.Beta;
 import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 
-import static com.google.common.base.Preconditions.*;
 
+/**
+ *
+ * Abstract caching schema provider with support of multiple context
+ * per backing {@link SchemaSourceProvider}.
+ *
+ * @param <I> Input Schema Source Representation
+ * @param <O> Output Schema Source Representation
+ */
 public abstract class AbstractCachingSchemaSourceProvider<I, O> implements AdvancedSchemaSourceProvider<O>,
         Delegator<AdvancedSchemaSourceProvider<I>> {
 
-    public class CompatibilitySchemaSourceProviderInstance implements SchemaSourceProvider<O> {
-
-        @Override
-        public Optional<O> getSchemaSource(String moduleName, Optional<String> revision) {
-            // TODO Auto-generated method stub
-            return null;
-        }
-
-    }
-
     private final AdvancedSchemaSourceProvider<I> defaultDelegate;
 
-    protected AbstractCachingSchemaSourceProvider(AdvancedSchemaSourceProvider<I> delegate) {
+    /**
+     * Construct caching schema source provider with supplied delegate.
+     *
+     * Default delegate is is used to retrieve schema source when cache does not
+     * contain requested sources.
+     *
+     * @param delegate SchemaSourceProvided used to look up and retrieve schema source
+     * when cache does not contain requested sources.
+     */
+    protected AbstractCachingSchemaSourceProvider(final AdvancedSchemaSourceProvider<I> delegate) {
         this.defaultDelegate = delegate;
     }
 
     @Override
-    public Optional<O> getSchemaSource(String moduleName, Optional<String> revision) {
-        checkNotNull(moduleName, "Module name should not be null.");
-        checkNotNull(revision, "Revision should not be null");
+    public Optional<O> getSchemaSource(final String moduleName, final Optional<String> revision) {
+        Preconditions.checkNotNull(moduleName, "Module name should not be null.");
+        Preconditions.checkNotNull(revision, "Revision should not be null");
         return getSchemaSource(SourceIdentifier.create(moduleName, revision));
     }
-    
+
     @Override
-    public Optional<O> getSchemaSource(SourceIdentifier sourceIdentifier) {
+    public Optional<O> getSchemaSource(final SourceIdentifier sourceIdentifier) {
         return getSchemaSourceImpl(sourceIdentifier, defaultDelegate);
     }
 
-    protected final Optional<O> getSchemaSourceImpl(SourceIdentifier identifier,
-            AdvancedSchemaSourceProvider<I> delegate) {
-        checkNotNull(identifier, "Source identifier name should not be null.");
+    /**
+     * Actual implementation of schema source retrieval.
+     *
+     * <ul>
+     * <li>look up cached schema source via {@link #getCachedSchemaSource(SourceIdentifier)}
+     * <li>If source was found in cache, returns source to client code.
+     * <li>If source was not found in cache, Look up schema source in supplied <code>delegate</code>
+     * <li>Updates cache with schema from delegate by {@link #cacheSchemaSource(SourceIdentifier, Optional)}
+     * <li>Result is returned to client code.
+     * </ul>
+     *
+     * @param identifier Source identifier
+     * @param delegate Delegate to lookup if there is a miss.
+     * @return Optional of schema source, present if source was found. Absent otherwise.
+     */
+    protected final Optional<O> getSchemaSourceImpl(final SourceIdentifier identifier,
+            final AdvancedSchemaSourceProvider<I> delegate) {
+        Preconditions.checkNotNull(identifier, "Source identifier name should not be null.");
 
         Optional<O> cached = getCachedSchemaSource(identifier);
         if (cached.isPresent()) {
@@ -55,33 +79,81 @@ public abstract class AbstractCachingSchemaSourceProvider<I, O> implements Advan
         return cacheSchemaSource(identifier, live);
     }
 
-    abstract protected Optional<O> cacheSchemaSource(SourceIdentifier identifier, Optional<I> stream);
-
+    /**
+     * Caches supplied result and returns cached result which should be returned to client.
+     *
+     * <p>
+     * Implementations of cache are required to cache schema source if possible.
+     * They are not required to cache {@link Optional#absent()}.
+     *
+     * Implementations are required to transform source representation if <code>O</code> and <code>I</code>
+     * are different.
+     *
+     * This method SHOULD NOT fail and should recover from Runtime exceptions
+     * by not caching source and only transforming it.
+     *
+     * @param identifier Source Identifier for which schema SHOULD be cached
+     * @param input Optional of schema source, representing one returned from delegate.
+     * @return Optional of schema source, representing result returned from this cache.
+     */
+    abstract protected Optional<O> cacheSchemaSource(SourceIdentifier identifier, Optional<I> input);
+
+    /**
+     * Returns cached schema source of {@link Optional#absent()} if source is not present in cache.
+     *
+     * <p>
+     * Implementations of cache MUST return cached schema source, if it is present in cache,
+     * otherwise source will be requested from deleate and then cache will be updated
+     * via {@link #cacheSchemaSource(SourceIdentifier, Optional)}.
+     *
+     * @param identifier Source Identifier for which schema should be retrieved.
+     * @return Cached schema source.
+     */
     abstract protected Optional<O> getCachedSchemaSource(SourceIdentifier identifier);
 
+    @Override
     public AdvancedSchemaSourceProvider<I> getDelegate() {
         return defaultDelegate;
     }
 
-    public SchemaSourceProvider<O> createInstanceFor(SchemaSourceProvider<I> delegate) {
-        checkNotNull(delegate, "Delegate should not be null");
+    /**
+     * Creates an lightweight instance of source provider, which uses this cache for caching
+     * and supplied additional delegate for lookup of not cached sources.
+     * <p>
+     *
+     * @param delegate Backing {@link SchemaSourceProvider} which should be used for lookup
+     *   for sources not present in schema.
+     * @return new instance of {@link SchemaSourceProvider} which first lookup in cache
+     *   and then in delegate.
+     *
+     */
+    @Beta
+    public SchemaSourceProvider<O> createInstanceFor(final SchemaSourceProvider<I> delegate) {
         return new SchemaSourceProviderInstance(SchemaSourceProviders.toAdvancedSchemaSourceProvider(delegate));
-            
+
     }
 
+    /**
+     *
+     * Lightweight instance of source provider, which is associated with parent
+     * {@link AbstractCachingSchemaSourceProvider}, but uses
+     * different delegate for retrieving not cached sources.
+     *
+     */
+    @Beta
     private class SchemaSourceProviderInstance implements //
-    AdvancedSchemaSourceProvider<O>, 
+    AdvancedSchemaSourceProvider<O>,
     Delegator<AdvancedSchemaSourceProvider<I>> {
 
         private final AdvancedSchemaSourceProvider<I> delegate;
 
-        protected SchemaSourceProviderInstance(AdvancedSchemaSourceProvider<I> delegate) {
+        protected SchemaSourceProviderInstance(final AdvancedSchemaSourceProvider<I> delegate) {
             super();
-            this.delegate = delegate;
+            this.delegate = Preconditions.checkNotNull(delegate, "Delegate should not be null");;
         }
 
         @Override
-        public Optional<O> getSchemaSource(String moduleName, Optional<String> revision) {
+        public Optional<O> getSchemaSource(final String moduleName, final Optional<String> revision) {
             return getSchemaSource(SourceIdentifier.create(moduleName, revision));
         }
 
@@ -91,7 +163,7 @@ public abstract class AbstractCachingSchemaSourceProvider<I, O> implements Advan
         }
 
         @Override
-        public Optional<O> getSchemaSource(SourceIdentifier sourceIdentifier) {
+        public Optional<O> getSchemaSource(final SourceIdentifier sourceIdentifier) {
             return getSchemaSourceImpl(sourceIdentifier, getDelegate());
         }
     }
index 1c7ffa1da54889bb04077f73c52fc21bd118f7d0..0b82e089089b317403b1a0ecac5a8609f7adb91f 100644 (file)
@@ -9,7 +9,51 @@ package org.opendaylight.yangtools.yang.model.util.repo;
 
 import com.google.common.base.Optional;
 
-public interface AdvancedSchemaSourceProvider<F> extends SchemaSourceProvider<F> {
+/**
+ * Provider of representation of YANG schema sources.
+ *
+ * <p>
+ * {@link AdvancedSchemaSourceProvider} is extension of
+ * {@link SchemaSourceProvider} which did not have object concept of source
+ * identifier, and introduces {@link SourceIdentifier} (which contains schema
+ * name and revision) as identifier of sources.
+ *
+ * <p>
+ * <b>Schema Source representation</b>
+ * <p>
+ * Representation of schema source. Representation of schema source could exists
+ * in various formats (Java types), depending on stage of processing, but
+ * representation MUST BE still result of processing of only single unit of schema
+ * source (file, input stream). E.g.:
+ * <ul>
+ * <li>{@link java.lang.String} - textual representation of source code
+ * <li>{@link java.io.InputStream} - input stream containing source code
+ * <li>{@link com.google.common.io.ByteSource} - source for input streams
+ * containing source code
+ * <li>Parsed AST - abstract syntax tree, which is result of a parser, but still
+ * it is not linked against other schemas.
+ *
+ * <p>
+ * Conversion between representations should be done via implementations of
+ * {@link SchemaSourceTransformation}.
+ *
+ * @param <T>
+ *            Schema source representation type provided by this implementation
+ */
+public interface AdvancedSchemaSourceProvider<T> extends SchemaSourceProvider<T> {
 
-    Optional<F> getSchemaSource(SourceIdentifier sourceIdentifier);
+    /**
+     * Returns representation source for supplied YANG source identifier.
+     *
+     * Returned representation of schema source must be immutable, must not
+     * change during runtime if {@link SourceIdentifier} has specified both
+     * {@link SourceIdentifier#getName()} and
+     * {@link SourceIdentifier#getRevision()}
+     *
+     * @param sourceIdentifier
+     *            source identifier.
+     * @return source representation if supplied YANG module is available
+     *         {@link Optional#absent()} otherwise.
+     */
+    Optional<T> getSchemaSource(SourceIdentifier sourceIdentifier);
 }
index 153a110c473f76c9ce486c7b968b2af6e2b56799..71ab88bfc4c0049b46c44eb8242d7a5ce1e767c1 100644 (file)
@@ -32,21 +32,83 @@ import com.google.common.base.Function;
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 
-public class FilesystemSchemaCachingProvider<I> extends AbstractCachingSchemaSourceProvider<I, InputStream> {
+/**
+ * Filesystem-based schema caching source provider
+ *
+ * This schema source provider caches all YANG modules loaded from backing
+ * schema source providers (registered via
+ * {@link #createInstanceFor(SchemaSourceProvider)} to supplied folder.
+ *
+ * @param <I>
+ *            Input format in which schema source is represented.
+ *
+ */
+public final class FilesystemSchemaCachingProvider<I> extends AbstractCachingSchemaSourceProvider<I, InputStream> {
     private static final Logger LOG = LoggerFactory.getLogger(FilesystemSchemaCachingProvider.class);
 
     private final File storageDirectory;
-    private final Function<I, String> transformationFunction;
+    private final SchemaSourceTransformation<I, String> transformationFunction;
+
+    /**
+     *
+     * Construct filesystem caching schema source provider.
+     *
+     *
+     * @param delegate
+     *            Default delegate to lookup for missed entries in cache.
+     * @param directory
+     *            Directory where YANG files should be cached.
+     * @param transformationFunction
+     *            Transformation function which translates from input in format
+     *            <code>I</code> to InputStream.
+     * @throws IllegalArgumentException
+     *             If supplied directory does not exists or is not directory.
+     */
+    public FilesystemSchemaCachingProvider(final AdvancedSchemaSourceProvider<I> delegate, final File directory,
+            final SchemaSourceTransformation<I, String> transformationFunction) {
+        super(delegate);
+        Preconditions.checkNotNull(directory, "directory must not be null.");
+        Preconditions.checkArgument(directory.exists(), "directory must be directory.");
+        Preconditions.checkArgument(directory.isDirectory(), "directory must be directory.");
+        this.storageDirectory = directory;
+        this.transformationFunction = Preconditions.checkNotNull(transformationFunction,
+                "transformationFunction must not be null.");
+    }
 
+    /**
+     *
+     * Construct filesystem caching schema source provider.
+     *
+     *
+     * @param delegate
+     *            Default delegate to lookup for missed entries in cache.
+     * @param directory
+     *            Directory where YANG files should be cached.
+     * @param transformationFunction
+     *            Transformation function which translates from input in format
+     *            <code>I</code> to InputStream.
+     * @throws IllegalArgumentException
+     *             If supplied directory does not exists or is not directory.
+     * @deprecated Use
+     *             {@link #FilesystemSchemaCachingProvider(AdvancedSchemaSourceProvider, File, SchemaSourceTransformation)}
+     *             with
+     *             {@link SchemaSourceProviders#schemaSourceTransformationFrom(Function)}
+     *             instead.
+     */
+    @Deprecated
     public FilesystemSchemaCachingProvider(final AdvancedSchemaSourceProvider<I> delegate, final File directory,
             final Function<I, String> transformationFunction) {
         super(delegate);
+        Preconditions.checkNotNull(directory, "directory must not be null.");
+        Preconditions.checkArgument(directory.exists(), "directory must be directory.");
+        Preconditions.checkArgument(directory.isDirectory(), "directory must be directory.");
         this.storageDirectory = directory;
-        this.transformationFunction = transformationFunction;
+        this.transformationFunction = SchemaSourceProviders.schemaSourceTransformationFrom(transformationFunction);
     }
 
     @Override
-    protected synchronized Optional<InputStream> cacheSchemaSource(final SourceIdentifier identifier, final Optional<I> source) {
+    protected synchronized Optional<InputStream> cacheSchemaSource(final SourceIdentifier identifier,
+            final Optional<I> source) {
         File schemaFile = toFile(identifier);
         try {
             if (source.isPresent() && schemaFile.createNewFile()) {
@@ -55,25 +117,25 @@ public class FilesystemSchemaCachingProvider<I> extends AbstractCachingSchemaSou
                     writer.write(transformToString(source.get()));
                     writer.flush();
                 } catch (IOException e) {
-
+                    LOG.warn("Could not chache source for {}. Source: ",identifier,source.get(),e);
                 }
             }
         } catch (IOException e) {
-
+            LOG.warn("Could not create cache file for {}. File: ",identifier,schemaFile,e);
         }
         return transformToStream(source);
     }
 
     private Optional<InputStream> transformToStream(final Optional<I> source) {
         if (source.isPresent()) {
-            return Optional.<InputStream> of(
-                    new ByteArrayInputStream(transformToString(source.get()).getBytes(Charsets.UTF_8)));
+            return Optional.<InputStream> of(new ByteArrayInputStream(transformToString(source.get()).getBytes(
+                    Charsets.UTF_8)));
         }
         return Optional.absent();
     }
 
     private String transformToString(final I input) {
-        return transformationFunction.apply(input);
+        return transformationFunction.transform(input);
     }
 
     @Override
@@ -104,6 +166,7 @@ public class FilesystemSchemaCachingProvider<I> extends AbstractCachingSchemaSou
     private File findFileWithNewestRev(final SourceIdentifier identifier) {
         File[] files = storageDirectory.listFiles(new FilenameFilter() {
             final String regex = identifier.getName() + "(\\.yang|@\\d\\d\\d\\d-\\d\\d-\\d\\d.yang)";
+
             @Override
             public boolean accept(final File dir, final String name) {
                 if (name.matches(regex)) {
@@ -147,13 +210,6 @@ public class FilesystemSchemaCachingProvider<I> extends AbstractCachingSchemaSou
         return file;
     }
 
-    private static final Function<String, String> NOOP_TRANSFORMATION = new Function<String, String>() {
-        @Override
-        public String apply(final String input) {
-            return input;
-        }
-    };
-
     public static FilesystemSchemaCachingProvider<String> createFromStringSourceProvider(
             final SchemaSourceProvider<String> liveProvider, final File directory) {
         Preconditions.checkNotNull(liveProvider);
@@ -162,6 +218,6 @@ public class FilesystemSchemaCachingProvider<I> extends AbstractCachingSchemaSou
         return new FilesystemSchemaCachingProvider<String>(
                 SchemaSourceProviders.toAdvancedSchemaSourceProvider(liveProvider),//
                 directory, //
-                NOOP_TRANSFORMATION);
+                SchemaSourceProviders.<String>identityTransformation());
     }
 }
index b2fd12fbbe423c0e2ca9d27e091beb235c0f87c2..8804eaacd12231617461d4c9907d0787e4152f30 100644 (file)
@@ -8,9 +8,18 @@
 package org.opendaylight.yangtools.yang.model.util.repo;
 
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaContextHolder;
 
+
+/**
+ * Represent Schema Service.
+ *
+ *
+ * @deprecated Replaced by {@link SchemaContextHolder}, which provides
+ *    component-local view for actual {@link SchemaContext}.
+ */
+@Deprecated
 public interface SchemaService {
 
-    
     SchemaContext getSchemaContext();
 }
index 2e56634adf9b6134d7641ed52da34011e2010c23..82fea38e4a296c99aace36e74499f6c1b290a1b3 100644 (file)
@@ -9,8 +9,28 @@ package org.opendaylight.yangtools.yang.model.util.repo;
 
 import com.google.common.base.Optional;
 
+/**
+ * Provider of text stream representation of YANG Modules
+ *
+ * Provider is holder / user implemented service, which
+ * may be able to retrieve representation of YANG sources
+ * for other components.
+ *
+ * @param <F> Format in which YANG source is represented.
+ */
 public interface SchemaSourceProvider<F> {
 
+    /**
+     * Returns source for supplied YANG module identifier and revision.
+     *
+     * @param moduleName module name
+     * @param revision revision of module
+     * @return source representation if supplied YANG module is available
+     *  {@link Optional#absent()} otherwise.
+     *  @deprecated Use {@link AdvancedSchemaSourceProvider#getSchemaSource(SourceIdentifier)}
+     *     instead.
+     */
+    @Deprecated
     Optional<F> getSchemaSource(String moduleName, Optional<String> revision);
 
 }
index a0a2f512444f8610bb27924f4e16cdd7b9f337be..24a92ba872215c730733af4426fbba2156336e62 100644 (file)
@@ -13,9 +13,16 @@ import java.io.InputStream;
 import org.opendaylight.yangtools.concepts.Delegator;
 
 import com.google.common.base.Charsets;
+import com.google.common.base.Function;
 import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
 
-public class SchemaSourceProviders {
+/**
+ *
+ * Utility functions for {@link SchemaSourceProvider}
+ *
+ */
+public final class SchemaSourceProviders {
 
     @SuppressWarnings("rawtypes")
     private static final SchemaSourceProvider NOOP_PROVIDER = new AdvancedSchemaSourceProvider() {
@@ -32,51 +39,98 @@ public class SchemaSourceProviders {
 
     };
 
+    @SuppressWarnings("rawtypes")
+    private static final SchemaSourceTransformation IDENTITY_TRANFORMATION = new IdentityTransformation();
+
+    private static final StringToInputStreamTransformation STRING_TO_INPUTSTREAM_TRANSFORMATION = new StringToInputStreamTransformation();
+
+    private SchemaSourceProviders() {
+        throw new UnsupportedOperationException("Utility class.");
+    }
+
+    /**
+     * Returns a noop schema source provider.
+     *
+     * Noop schema provider returns {@link Optional#absent()} for each call to
+     * query schema source.
+     *
+     * @return
+     */
     @SuppressWarnings("unchecked")
     public static <T> SchemaSourceProvider<T> noopProvider() {
         return NOOP_PROVIDER;
     }
 
+    /**
+     *
+     * Returns delegating schema source provider which returns InputStream from
+     * supplied String based schema source provider.
+     *
+     * @param delegate
+     * @return
+     */
     public static SchemaSourceProvider<InputStream> inputStreamProviderfromStringProvider(
             final AdvancedSchemaSourceProvider<String> delegate) {
-        return new StringToInputStreamSchemaSourceProvider(delegate);
+        return TransformingSourceProvider.create(delegate, STRING_TO_INPUTSTREAM_TRANSFORMATION);
     }
 
-    public static <O> AdvancedSchemaSourceProvider<O> toAdvancedSchemaSourceProvider(final SchemaSourceProvider<O> schemaSourceProvider) {
+    /**
+     * Returns identity implementation of SchemaSourceTransformation
+     *
+     * Identity implementation of SchemaSourceTransformation is useful
+     * for usecases where Input and Output of SchemaSourceTransformation
+     * are identitcal, and you want to reuse input as an output.
+     *
+     * This implementation is really simple <code>return input;</code>.
+     *
+     * @return
+     */
+    @SuppressWarnings("unchecked")
+    public static <I> SchemaSourceTransformation<I, I> identityTransformation() {
+        return IDENTITY_TRANFORMATION;
+    }
+
+    public static <I, O> SchemaSourceTransformation<I, O> schemaSourceTransformationFrom(
+            final Function<I, O> transformation) {
+        return new FunctionBasedSchemaSourceTransformation<I, O>(transformation);
+    }
+
+    /**
+     *
+     * Casts {@link SchemaSourceProvider} to
+     * {@link AdvancedSchemaSourceProvider} or wraps it with utility
+     * implementation if supplied delegate does not implement
+     * {@link AdvancedSchemaSourceProvider}.
+     *
+     * @param schemaSourceProvider
+     */
+    public static <O> AdvancedSchemaSourceProvider<O> toAdvancedSchemaSourceProvider(
+            final SchemaSourceProvider<O> schemaSourceProvider) {
         if (schemaSourceProvider instanceof AdvancedSchemaSourceProvider<?>) {
             return (AdvancedSchemaSourceProvider<O>) schemaSourceProvider;
         }
         return new SchemaSourceCompatibilityWrapper<O>(schemaSourceProvider);
     }
 
-    private final static class StringToInputStreamSchemaSourceProvider implements //
-            AdvancedSchemaSourceProvider<InputStream>, Delegator<AdvancedSchemaSourceProvider<String>> {
+    private static final class FunctionBasedSchemaSourceTransformation<I, O> implements
+            SchemaSourceTransformation<I, O> {
 
-        private final AdvancedSchemaSourceProvider<String> delegate;
 
-        public StringToInputStreamSchemaSourceProvider(final AdvancedSchemaSourceProvider<String> delegate) {
-            this.delegate = delegate;
-        }
+        private final Function<I, O> delegate;
 
-        @Override
-        public AdvancedSchemaSourceProvider<String> getDelegate() {
-            return delegate;
+        protected FunctionBasedSchemaSourceTransformation(final Function<I, O> delegate) {
+            super();
+            this.delegate = Preconditions.checkNotNull(delegate, "delegate MUST NOT be null.");
         }
 
         @Override
-        public Optional<InputStream> getSchemaSource(final SourceIdentifier sourceIdentifier) {
-            Optional<String> potentialSource = getDelegate().getSchemaSource(sourceIdentifier);
-            if (potentialSource.isPresent()) {
-                final String stringSource = potentialSource.get();
-                return Optional.<InputStream> of(
-                        new ByteArrayInputStream(stringSource.getBytes(Charsets.UTF_8)));
-            }
-            return Optional.absent();
+        public O transform(final I input) {
+            return delegate.apply(input);
         }
 
         @Override
-        public Optional<InputStream> getSchemaSource(final String moduleName, final Optional<String> revision) {
-            return getSchemaSource(SourceIdentifier.create(moduleName, revision));
+        public String toString() {
+            return "FunctionBasedSchemaSourceTransformation [delegate=" + delegate + "]";
         }
     }
 
@@ -95,6 +149,16 @@ public class SchemaSourceProviders {
             return delegate;
         }
 
+
+        /*
+         * Deprecation warnings are suppresed, since this implementation
+         * needs to invoke deprecated method in order to provide
+         * implementation of non-deprecated APIs using legacy ones.
+         *
+         * (non-Javadoc)
+         * @see org.opendaylight.yangtools.yang.model.util.repo.AdvancedSchemaSourceProvider#getSchemaSource(org.opendaylight.yangtools.yang.model.util.repo.SourceIdentifier)
+         */
+        @SuppressWarnings("deprecation")
         @Override
         public Optional<O> getSchemaSource(final SourceIdentifier sourceIdentifier) {
 
@@ -103,10 +167,37 @@ public class SchemaSourceProviders {
             return delegate.getSchemaSource(moduleName, revision);
         }
 
+        /*
+         * Deprecation warnings are suppresed, since this implementation
+         * needs to invoke deprecated method in order to provide
+         * implementation of non-deprecated APIs using legacy ones.
+         *
+         * (non-Javadoc)
+         * @see org.opendaylight.yangtools.yang.model.util.repo.AdvancedSchemaSourceProvider#getSchemaSource(org.opendaylight.yangtools.yang.model.util.repo.SourceIdentifier)
+         */
         @Override
+        @SuppressWarnings("deprecation")
         public Optional<O> getSchemaSource(final String moduleName, final Optional<String> revision) {
             return delegate.getSchemaSource(moduleName, revision);
         }
     }
 
+    @SuppressWarnings("rawtypes")
+    private static class  IdentityTransformation implements SchemaSourceTransformation {
+
+        @Override
+        public Object transform(final Object input) {
+            return input;
+        }
+    }
+
+    private static class StringToInputStreamTransformation implements SchemaSourceTransformation<String, InputStream> {
+
+        @Override
+        public InputStream transform(final String input) {
+            return new ByteArrayInputStream(input.getBytes(Charsets.UTF_8));
+        }
+
+    }
+
 }
diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/repo/SchemaSourceTransformation.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/repo/SchemaSourceTransformation.java
new file mode 100644 (file)
index 0000000..6836618
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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/eplv10.html
+ */
+package org.opendaylight.yangtools.yang.model.util.repo;
+
+import com.google.common.annotations.Beta;
+
+/**
+ *
+ * Schema Source Transformation which transforms from one schema source
+ * representation to another.
+ *
+ * <p>
+ * <b>Representation of Schema Source</b>
+ * <p>
+ * Schema source may be represented by
+ * various Java Types, which depends on provider and/or consumer.
+ * <p>
+ * E.g example of possible representations:
+ * <ul>
+ * <li>{@link String}
+ * <li>{@link java.io.InputStream}
+ * <li>{@link com.google.common.io.ByteSource}
+ * </ul>
+ *
+ * FIXME: <b>Beta:</b> Consider allowing transformations, which may
+ * fail to produce Output, this will require introduction of
+ * checked exception.
+ *
+ * @param <I> Input schema source representation
+ * @param <O> Output schema source representation
+ */
+@Beta
+public interface SchemaSourceTransformation<I, O> {
+
+    /**
+     *
+     * Transforms supplied schema source in format <code>I</code> to schema
+     * source in format <code>O</code>.
+     *
+     * <ul>
+     * <li>Its execution does not cause any observable side effects.
+     * <li>If the contents of a,b are semantically same (e.g. contents of InputStream),
+     * output representations MUST BE also semantically equals.
+     * </ul>
+     *
+     * Implementations of transformation SHOULD NOT fail to
+     * transform valid non-null input to output representation.
+     *
+     *
+     * FIXME: <b>Beta:</b> Consider lowering condition for safe transformation
+     * and introduce checked exception for cases when transformation may fail.
+     *
+     * @param input Not null input which should be transformed
+     * @return Representation of input in <code>O</code> format.
+     * @throws NullPointerException if input is null.
+     *
+     */
+    @Beta
+    O transform(I input);
+}
index 5e06a57efa9b9a5d0a865c319345853c3dca2ce4..3c7812b0d81d5cbc58fe3087ba7d7a8cce9c7b4c 100644 (file)
@@ -7,19 +7,70 @@
  */
 package org.opendaylight.yangtools.yang.model.util.repo;
 
+import org.opendaylight.yangtools.concepts.Immutable;
+
 import com.google.common.base.Optional;
 
-public final class SourceIdentifier {
+/**
+ *
+ * YANG Schema source identifier
+ *
+ * Simple transfer object represents identifier of source for YANG schema (module or submodule),
+ * which consists of
+ * <ul>
+ * <li>YANG schema name ({@link #getName()}
+ * <li>Module revision (optional) ({link {@link #getRevision()})
+ * </ul>
+ *
+ * Source identifier is designated to be carry only necessary information
+ * to look-up YANG model source and to be used by {@link AdvancedSchemaSourceProvider}
+ * and similar.
+ *
+ * <b>Note:</b>On source retrieval layer it is impossible to distinguish
+ * between YANG module and/or submodule unless source is present.
+ *
+ * <p>
+ * (For further reference see: http://tools.ietf.org/html/rfc6020#section-5.2 and
+ * http://tools.ietf.org/html/rfc6022#section-3.1 ).
+ *
+ *
+ */
+public final class SourceIdentifier implements Immutable {
 
     private final String name;
     private final String revision;
 
+    /**
+     *
+     * Creates new YANG Schema source identifier.
+     *
+     * @param name Name of schema
+     * @param formattedRevision Revision of source in format YYYY-mm-dd
+     */
     public SourceIdentifier(final String name, final Optional<String> formattedRevision) {
         super();
         this.name = name;
         this.revision = formattedRevision.orNull();
     }
 
+    /**
+     * Returns model name
+     *
+     * @return model name
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Returns revision of source or null if revision was not supplied.
+     *
+     * @return revision of source or null if revision was not supplied.
+     */
+    public String getRevision() {
+        return revision;
+    }
+
     @Override
     public int hashCode() {
         final int prime = 31;
@@ -58,18 +109,23 @@ public final class SourceIdentifier {
         return true;
     }
 
-    public String getName() {
-        return name;
-    }
-
-    public String getRevision() {
-        return revision;
-    }
-
     public static SourceIdentifier create(final String moduleName, final Optional<String> revision) {
         return new SourceIdentifier(moduleName, revision);
     }
 
+    /**
+     * Returns filename for this YANG module as specified in RFC 6020.
+     *
+     * Returns filename in format
+     * <code>name ['@' revision] '.yang'</code>
+     * <p>
+     * Where revision is  date in format YYYY-mm-dd.
+     * <p>
+     * See
+     * http://tools.ietf.org/html/rfc6020#section-5.2
+     *
+     * @return Filename for this source identifier.
+     */
     public String toYangFilename() {
         return toYangFileName(name, Optional.fromNullable(revision));
     }
@@ -79,6 +135,20 @@ public final class SourceIdentifier {
         return "SourceIdentifier [name=" + name + "@" + revision + "]";
     }
 
+    /**
+     * Returns filename for this YANG module as specified in RFC 6020.
+     *
+     * Returns filename in format
+     * <code>moduleName ['@' revision] '.yang'</code>
+     *
+     * Where Where revision-date is in format YYYY-mm-dd.
+     *
+     * <p>
+     * See
+     * http://tools.ietf.org/html/rfc6020#section-5.2
+     *
+     * @return Filename for this source identifier.
+     */
     public static final String toYangFileName(final String moduleName, final Optional<String> revision) {
         StringBuilder filename = new StringBuilder(moduleName);
         if (revision.isPresent()) {
diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/repo/TransformingSourceProvider.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/repo/TransformingSourceProvider.java
new file mode 100644 (file)
index 0000000..502bc9d
--- /dev/null
@@ -0,0 +1,69 @@
+package org.opendaylight.yangtools.yang.model.util.repo;
+
+import org.opendaylight.yangtools.concepts.Delegator;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+/**
+ *
+ * Utility Source Provider implementation which uses delegate to retrieve
+ * sources and transformation function to convert sources to different
+ * representation.
+ *
+ *
+ * @param <I>
+ *            Representation of schema sources used by delegate
+ * @param <O>
+ *            Representation of schema sources exposed by this provider
+ */
+public final class TransformingSourceProvider<I, O> implements //
+        AdvancedSchemaSourceProvider<O>, Delegator<AdvancedSchemaSourceProvider<I>> {
+
+    private final AdvancedSchemaSourceProvider<I> delegate;
+    private final SchemaSourceTransformation<I, O> transformation;
+
+    /**
+     * Creates instance of transforming schema source provider which uses
+     * supplied delegate to retrieve sources and transformation to change
+     * sources to different representation.
+     *
+     * @param delegate
+     *            Delegate which provides sources.
+     * @param transformation
+     *            Transformation function which converts sources
+     * @return Instance of TransformingSourceProvider
+     * @throws NullPointerException
+     *             if any of arguments is null.
+     */
+    public static final <I, O> TransformingSourceProvider<I, O> create(final AdvancedSchemaSourceProvider<I> delegate,
+            final SchemaSourceTransformation<I, O> transformation) {
+        return new TransformingSourceProvider<>(delegate, transformation);
+    }
+
+    private TransformingSourceProvider(final AdvancedSchemaSourceProvider<I> delegate,
+            final SchemaSourceTransformation<I, O> transformation) {
+        this.delegate = Preconditions.checkNotNull(delegate, "delegate must not be null");
+        this.transformation = Preconditions.checkNotNull(transformation, "transformation must not be null");
+    }
+
+    @Override
+    public AdvancedSchemaSourceProvider<I> getDelegate() {
+        return delegate;
+    }
+
+    @Override
+    public Optional<O> getSchemaSource(final SourceIdentifier sourceIdentifier) {
+        Optional<I> potentialSource = getDelegate().getSchemaSource(sourceIdentifier);
+        if (potentialSource.isPresent()) {
+            I inputSource = potentialSource.get();
+            return Optional.<O> of(transformation.transform(inputSource));
+        }
+        return Optional.absent();
+    }
+
+    @Override
+    public Optional<O> getSchemaSource(final String moduleName, final Optional<String> revision) {
+        return getSchemaSource(SourceIdentifier.create(moduleName, revision));
+    }
+}
\ No newline at end of file
diff --git a/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/repo/package-info.java b/yang/yang-model-util/src/main/java/org/opendaylight/yangtools/yang/model/util/repo/package-info.java
new file mode 100644 (file)
index 0000000..6e31ba1
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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/eplv10.html
+ */
+/**
+ * This package introduces concepts, generic interfaces and implementations for
+ * creating and working with YANG Schema source repositories and working with them.
+ *
+ * <h2>Concepts</h2>
+ * <dl>
+ * <dt>Schema Source</dt>
+ * <dd>Source of YANG Schema, which is not processed, not resolved against other schemas
+ *    and from contents of <i>Schema Source</i> in combination with other Schema sources
+ *    it is possible to create resolved YANG Schema context.
+ * </dd>
+ * <dt>{@link org.opendaylight.yangtools.yang.model.util.repo.SourceIdentifier}</dt>
+ * <dd>Identifier of Schema Source. Identifier is not tied with source or representation.</dd>
+ * <dt>Schema Source Representation</dt>
+ * <dd>Representation of schema source. Representation of schema source could exists in various
+ * formats (Java types), depending on stage of processing, but representation MUST BE
+ * still result of processing only single unit of schema source (e.g. file, input stream). E.g.:
+ * <ul>
+ * <li>{@link java.lang.String} - textual representation of source code
+ * <li>{@link InputStream} - input stream containing source code
+ * <li>{@link com.google.common.io.ByteSource} - source for input streams containing source code
+ * <li>Parsed AST - abstract syntax tree, which is result of a parser, but still it is not linked
+ * against other schemas.
+ * </ul>
+ * </dd>
+ * <dt>{@link org.opendaylight.yangtools.yang.model.util.repo.AdvancedSchemaSourceProvider}</dt>
+ * <dd>
+ *    Service which provides query API to obtain <i>Schema Source Representation</i> associated
+ *    with {@link org.opendaylight.yangtools.yang.model.util.repo.SourceIdentifier}.
+ * </dd>
+ * <dt>{@link org.opendaylight.yangtools.yang.model.util.repo.SchemaSourceTransformation}</dt>
+ * <dd>
+ * Function (service) which provides transformation from one <i>Schema Source Representation</i>
+ * type to another.
+ * </dd>
+ * </dl>
+ *
+ *
+ */
+package org.opendaylight.yangtools.yang.model.util.repo;
\ No newline at end of file
index 1a463447a9c9eac5ee0a57293ac760f50623240d..d0af63da9b88f8babcf20de1755cb0cefb7178db 100644 (file)
@@ -1,6 +1,5 @@
 /*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
+ * 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
@@ -96,11 +95,11 @@ import org.opendaylight.yangtools.yang.validator.YangModelBasicValidator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.collect.HashBiMap;
 import com.google.common.io.ByteSource;
 
-
 public final class YangParserImpl implements YangContextParser {
     private static final Logger LOG = LoggerFactory.getLogger(YangParserImpl.class);
 
@@ -117,7 +116,8 @@ public final class YangParserImpl implements YangContextParser {
     }
 
     @Override
-    public SchemaContext parseFile(final File yangFile, final File directory) throws IOException, YangSyntaxErrorException {
+    public SchemaContext parseFile(final File yangFile, final File directory) throws IOException,
+    YangSyntaxErrorException {
         Preconditions.checkState(yangFile.exists(), yangFile + " does not exists");
         Preconditions.checkState(directory.exists(), directory + " does not exists");
         Preconditions.checkState(directory.isDirectory(), directory + " is not a directory");
@@ -181,7 +181,8 @@ public final class YangParserImpl implements YangContextParser {
     }
 
     @Override
-    public SchemaContext parseFiles(final Collection<File> yangFiles, final SchemaContext context) throws IOException, YangSyntaxErrorException {
+    public SchemaContext parseFiles(final Collection<File> yangFiles, final SchemaContext context) throws IOException,
+    YangSyntaxErrorException {
         if (yangFiles == null) {
             return resolveSchemaContext(Collections.<Module> emptySet());
         }
@@ -203,7 +204,8 @@ public final class YangParserImpl implements YangContextParser {
     }
 
     @Override
-    public SchemaContext parseSources(final Collection<ByteSource> sources) throws IOException, YangSyntaxErrorException {
+    public SchemaContext parseSources(final Collection<ByteSource> sources) throws IOException,
+    YangSyntaxErrorException {
         Collection<Module> unsorted = parseYangModelSources(sources).values();
         Set<Module> sorted = new LinkedHashSet<>(
                 ModuleDependencySort.sort(unsorted.toArray(new Module[unsorted.size()])));
@@ -222,7 +224,8 @@ public final class YangParserImpl implements YangContextParser {
     }
 
     @Override
-    public SchemaContext parseSources(final Collection<ByteSource> sources, final SchemaContext context) throws IOException, YangSyntaxErrorException {
+    public SchemaContext parseSources(final Collection<ByteSource> sources, final SchemaContext context)
+            throws IOException, YangSyntaxErrorException {
         if (sources == null) {
             return resolveSchemaContext(Collections.<Module> emptySet());
         }
@@ -303,16 +306,18 @@ public final class YangParserImpl implements YangContextParser {
 
     @Override
     public SchemaContext resolveSchemaContext(final Set<Module> modules) {
-        // after merging parse method with this one, add support for getting submodule sources.
+        // after merging parse method with this one, add support for getting
+        // submodule sources.
         Map<ModuleIdentifier, String> identifiersToSources = new HashMap<>();
-        for(Module module: modules) {
+        for (Module module : modules) {
             ModuleImpl moduleImpl = (ModuleImpl) module;
             identifiersToSources.put(module, moduleImpl.getSource());
         }
         return new SchemaContextImpl(modules, identifiersToSources);
     }
 
-    private Map<ByteSource, Module> parseYangModelSources(final Collection<ByteSource> sources) throws IOException, YangSyntaxErrorException {
+    private Map<ByteSource, Module> parseYangModelSources(final Collection<ByteSource> sources) throws IOException,
+    YangSyntaxErrorException {
         if (sources == null || sources.isEmpty()) {
             return Collections.emptyMap();
         }
@@ -344,13 +349,15 @@ public final class YangParserImpl implements YangContextParser {
      *         parsed from stream
      * @throws YangSyntaxErrorException
      */
-    private Map<ByteSource, ModuleBuilder> resolveSources(final Collection<ByteSource> streams) throws IOException, YangSyntaxErrorException {
+    private Map<ByteSource, ModuleBuilder> resolveSources(final Collection<ByteSource> streams) throws IOException,
+    YangSyntaxErrorException {
         Map<ByteSource, ModuleBuilder> builders = parseSourcesToBuilders(streams);
         Map<ByteSource, ModuleBuilder> result = resolveSubmodules(builders);
         return result;
     }
 
-    private Map<ByteSource, ModuleBuilder> parseSourcesToBuilders(final Collection<ByteSource> sources) throws IOException, YangSyntaxErrorException {
+    private Map<ByteSource, ModuleBuilder> parseSourcesToBuilders(final Collection<ByteSource> sources)
+            throws IOException, YangSyntaxErrorException {
         final ParseTreeWalker walker = new ParseTreeWalker();
         final Map<ByteSource, ParseTree> sourceToTree = parseYangSources(sources);
         final Map<ByteSource, ModuleBuilder> sourceToBuilder = new LinkedHashMap<>();
@@ -468,7 +475,8 @@ public final class YangParserImpl implements YangContextParser {
     }
 
     private Map<String, TreeMap<Date, ModuleBuilder>> resolveModuleBuilders(
-            final Collection<ByteSource> yangFileStreams, final SchemaContext context) throws IOException, YangSyntaxErrorException {
+            final Collection<ByteSource> yangFileStreams, final SchemaContext context) throws IOException,
+            YangSyntaxErrorException {
         Map<ByteSource, ModuleBuilder> parsedBuilders = resolveSources(yangFileStreams);
         ModuleBuilder[] builders = new ModuleBuilder[parsedBuilders.size()];
         parsedBuilders.values().toArray(builders);
@@ -522,7 +530,8 @@ public final class YangParserImpl implements YangContextParser {
      * @param filtered
      *            collection to fill up
      */
-    private void filterImports(final ModuleBuilder main, final Collection<ModuleBuilder> other, final Collection<ModuleBuilder> filtered) {
+    private void filterImports(final ModuleBuilder main, final Collection<ModuleBuilder> other,
+            final Collection<ModuleBuilder> filtered) {
         Set<ModuleImport> imports = main.getModuleImports();
 
         // if this is submodule, add parent to filtered and pick its imports
@@ -559,7 +568,8 @@ public final class YangParserImpl implements YangContextParser {
         }
     }
 
-    private Map<ByteSource, ParseTree> parseYangSources(final Collection<ByteSource> sources) throws IOException, YangSyntaxErrorException {
+    private Map<ByteSource, ParseTree> parseYangSources(final Collection<ByteSource> sources) throws IOException,
+    YangSyntaxErrorException {
         final Map<ByteSource, ParseTree> trees = new HashMap<>();
         for (ByteSource source : sources) {
             trees.put(source, parseYangSource(source));
@@ -568,7 +578,7 @@ public final class YangParserImpl implements YangContextParser {
     }
 
     private YangContext parseYangSource(final ByteSource source) throws IOException, YangSyntaxErrorException {
-       try (InputStream stream = source.openStream()) {
+        try (InputStream stream = source.openStream()) {
             final ANTLRInputStream input = new ANTLRInputStream(stream);
             final YangLexer lexer = new YangLexer(input);
             final CommonTokenStream tokens = new CommonTokenStream(lexer);
@@ -582,7 +592,7 @@ public final class YangParserImpl implements YangContextParser {
             errorListener.validate();
 
             return result;
-       }
+        }
     }
 
     public static YangContext parseStreamWithoutErrorListeners(final InputStream yangStream) {
@@ -892,7 +902,7 @@ public final class YangParserImpl implements YangContextParser {
             }
         }
         if (node instanceof ChoiceBuilder) {
-            for (ChoiceCaseBuilder child : ((ChoiceBuilder)node).getCases()) {
+            for (ChoiceCaseBuilder child : ((ChoiceBuilder) node).getCases()) {
                 correctPathForAugmentNodes(child, node.getPath());
             }
         }
@@ -988,22 +998,39 @@ public final class YangParserImpl implements YangContextParser {
 
         UsesNodeBuilder usesNode = (UsesNodeBuilder) augment.getParent();
         DataNodeContainerBuilder parentNode = usesNode.getParent();
-        SchemaNodeBuilder targetNode;
-        if (parentNode instanceof ModuleBuilder) {
-            targetNode = findSchemaNodeInModule(augment.getTargetPath().getPath(), (ModuleBuilder) parentNode);
+        Optional<SchemaNodeBuilder> potentialTargetNode;
+        SchemaPath resolvedTargetPath = augment.getTargetNodeSchemaPath();
+        if (parentNode instanceof ModuleBuilder && resolvedTargetPath.isAbsolute()) {
+            // Uses is directly used in module body, we lookup
+            // We lookup in data namespace to find correct augmentation target
+            potentialTargetNode = findSchemaNodeInModule(resolvedTargetPath, (ModuleBuilder) parentNode);
         } else {
-            targetNode = findSchemaNode(augment.getTargetPath().getPath(), (SchemaNodeBuilder) parentNode);
-        }
-
-        if (targetNode instanceof AugmentationTargetBuilder) {
-            fillAugmentTarget(augment, targetNode);
-            ((AugmentationTargetBuilder) targetNode).addAugmentation(augment);
-            augment.setResolved(true);
-            return true;
+            // Uses is used in local context (be it data namespace or grouping namespace,
+            // since all nodes via uses are imported to localName, it is safe to
+            // to proceed only with local names.
+            //
+            // Conflicting elements in other namespaces are still not present
+            // since resolveUsesAugment occurs before augmenting from external modules.
+            potentialTargetNode = Optional.<SchemaNodeBuilder> fromNullable(findSchemaNode(augment.getTargetPath()
+                    .getPath(), (SchemaNodeBuilder) parentNode));
+        }
+
+        if (potentialTargetNode.isPresent()) {
+            SchemaNodeBuilder targetNode = potentialTargetNode.get();
+            if (targetNode instanceof AugmentationTargetBuilder) {
+                fillAugmentTarget(augment, targetNode);
+                ((AugmentationTargetBuilder) targetNode).addAugmentation(augment);
+                augment.setResolved(true);
+                return true;
+            } else {
+                throw new YangParseException(module.getName(), augment.getLine(), String.format(
+                        "Failed to resolve augment in uses. Invalid augment target: %s", potentialTargetNode));
+            }
         } else {
-            throw new YangParseException(module.getName(), augment.getLine(),
-                    "Failed to resolve augment in uses. Invalid augment target: " + targetNode);
+            throw new YangParseException(module.getName(), augment.getLine(), String.format(
+                    "Failed to resolve augment in uses. Invalid augment target path: %s", augment.getTargetPath()));
         }
+
     }
 
     /**
@@ -1119,9 +1146,11 @@ public final class YangParserImpl implements YangContextParser {
                     final String baseIdentityName = identity.getBaseIdentityName();
                     final int line = identity.getLine();
                     if (baseIdentityName != null) {
-                        IdentitySchemaNodeBuilder baseIdentity = findBaseIdentity(modules, module, baseIdentityName, line);
+                        IdentitySchemaNodeBuilder baseIdentity = findBaseIdentity(modules, module, baseIdentityName,
+                                line);
                         if (baseIdentity == null) {
-                            throw new YangParseException(module.getName(), identity.getLine(), "Failed to find base identity");
+                            throw new YangParseException(module.getName(), identity.getLine(),
+                                    "Failed to find base identity");
                         } else {
                             identity.setBaseIdentity(baseIdentity);
                         }
@@ -1222,7 +1251,8 @@ public final class YangParserImpl implements YangContextParser {
      * @param context
      *            SchemaContext containing already resolved modules
      */
-    private void resolveUsesForGroupings(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final SchemaContext context) {
+    private void resolveUsesForGroupings(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
+            final SchemaContext context) {
         final Set<GroupingBuilder> allGroupings = new HashSet<>();
         for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
             for (Map.Entry<Date, ModuleBuilder> inner : entry.getValue().entrySet()) {
@@ -1248,7 +1278,8 @@ public final class YangParserImpl implements YangContextParser {
      * @param context
      *            SchemaContext containing already resolved modules
      */
-    private void resolveUsesForNodes(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final SchemaContext context) {
+    private void resolveUsesForNodes(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
+            final SchemaContext context) {
         for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
             for (Map.Entry<Date, ModuleBuilder> inner : entry.getValue().entrySet()) {
                 ModuleBuilder module = inner.getValue();
@@ -1272,8 +1303,8 @@ public final class YangParserImpl implements YangContextParser {
      * @param context
      *            SchemaContext containing already resolved modules
      */
-    private void resolveUses(final UsesNodeBuilder usesNode,
-            final Map<String, TreeMap<Date, ModuleBuilder>> modules, final SchemaContext context) {
+    private void resolveUses(final UsesNodeBuilder usesNode, final Map<String, TreeMap<Date, ModuleBuilder>> modules,
+            final SchemaContext context) {
         if (!usesNode.isResolved()) {
             DataNodeContainerBuilder parent = usesNode.getParent();
             ModuleBuilder module = ParserUtils.getParentModule(parent);
@@ -1299,8 +1330,7 @@ public final class YangParserImpl implements YangContextParser {
     }
 
     /**
-     * Copy target grouping child nodes to current location with
-     * new namespace.
+     * Copy target grouping child nodes to current location with new namespace.
      *
      * @param usesNode
      *            uses node to resolve
@@ -1322,35 +1352,34 @@ public final class YangParserImpl implements YangContextParser {
             rev = module.getRevision();
             pref = module.getPrefix();
             if (parent instanceof AugmentationSchemaBuilder) {
-                parentPath = ((AugmentationSchemaBuilder)parent).getTargetNodeSchemaPath();
+                parentPath = ((AugmentationSchemaBuilder) parent).getTargetNodeSchemaPath();
             } else {
-                parentPath = ((ModuleBuilder)parent).getPath();
+                parentPath = ((ModuleBuilder) parent).getPath();
             }
         } else {
             ns = ((DataSchemaNodeBuilder) parent).getQName().getNamespace();
             rev = ((DataSchemaNodeBuilder) parent).getQName().getRevision();
             pref = ((DataSchemaNodeBuilder) parent).getQName().getPrefix();
-            parentPath = ((DataSchemaNodeBuilder)parent).getPath();
+            parentPath = ((DataSchemaNodeBuilder) parent).getPath();
         }
 
         GroupingDefinition gd = usesNode.getGroupingDefinition();
 
-        Set<DataSchemaNodeBuilder> childNodes = wrapChildNodes(module.getModuleName(), line,
-                gd.getChildNodes(), parentPath, ns, rev, pref);
+        Set<DataSchemaNodeBuilder> childNodes = wrapChildNodes(module.getModuleName(), line, gd.getChildNodes(),
+                parentPath, ns, rev, pref);
         parent.getChildNodeBuilders().addAll(childNodes);
         for (DataSchemaNodeBuilder childNode : childNodes) {
             setNodeAddedByUses(childNode);
         }
 
-        Set<TypeDefinitionBuilder> typedefs = wrapTypedefs(module.getModuleName(), line, gd, parentPath, ns,
-                rev, pref);
+        Set<TypeDefinitionBuilder> typedefs = wrapTypedefs(module.getModuleName(), line, gd, parentPath, ns, rev, pref);
         parent.getTypeDefinitionBuilders().addAll(typedefs);
         for (TypeDefinitionBuilder typedef : typedefs) {
             setNodeAddedByUses(typedef);
         }
 
-        Set<GroupingBuilder> groupings = wrapGroupings(module.getModuleName(), line, usesNode
-                .getGroupingDefinition().getGroupings(), parentPath, ns, rev, pref);
+        Set<GroupingBuilder> groupings = wrapGroupings(module.getModuleName(), line, usesNode.getGroupingDefinition()
+                .getGroupings(), parentPath, ns, rev, pref);
         parent.getGroupingBuilders().addAll(groupings);
         for (GroupingBuilder gb : groupings) {
             setNodeAddedByUses(gb);
index 82d7014cfbf2fced74340464f753055b27d72341..9e123e343e63ac64c0abd671355cb6b5048386e7 100644 (file)
@@ -71,6 +71,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Function;
+import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
 import com.google.common.base.Splitter;
 import com.google.common.collect.Collections2;
@@ -81,6 +82,8 @@ public final class ParserUtils {
     private static final Logger LOG = LoggerFactory.getLogger(ParserUtils.class);
     private static final Splitter SLASH_SPLITTER = Splitter.on('/');
     private static final Splitter COLON_SPLITTER = Splitter.on(':');
+    private static final String INPUT = "input";
+    private static final String OUTPUT = "output";
 
     private ParserUtils() {
     }
@@ -102,7 +105,8 @@ public final class ParserUtils {
         };
     }
 
-    public static Collection<ByteSource> filesToByteSources(final Collection<File> streams) throws FileNotFoundException {
+    public static Collection<ByteSource> filesToByteSources(final Collection<File> streams)
+            throws FileNotFoundException {
         return Collections2.transform(streams, new Function<File, ByteSource>() {
             @Override
             public ByteSource apply(final File input) {
@@ -137,7 +141,12 @@ public final class ParserUtils {
                     try {
                         stream.close();
                     } catch (IOException e) {
-                        LOG.warn("Failed to close stream {}", stream);
+                        /*
+                         * Failed stream close does not prevent us from
+                         * continuing to work correctly, we just report that and
+                         * continue.
+                         */
+                        LOG.warn("Failed to close stream {}. Leaving stream unclosed.", stream, e);
                     }
                 }
             }
@@ -238,8 +247,8 @@ public final class ParserUtils {
      *            current line in yang model
      * @return module based on given prefix if found in context, null otherwise
      */
-    public static Module findModuleFromContext(final SchemaContext context, final ModuleBuilder currentModule, final String prefix,
-            final int line) {
+    public static Module findModuleFromContext(final SchemaContext context, final ModuleBuilder currentModule,
+            final String prefix, final int line) {
         if (context == null) {
             throw new YangParseException(currentModule.getName(), line, "Cannot find module with prefix '" + prefix
                     + "'.");
@@ -470,36 +479,197 @@ public final class ParserUtils {
         return node;
     }
 
-    public static SchemaNodeBuilder findSchemaNodeInModule(final List<QName> pathToNode, final ModuleBuilder module) {
-        List<QName> path = new ArrayList<>(pathToNode);
-        QName first = path.remove(0);
+    /**
+     *
+     * Find a builder for node in data namespace of YANG module.
+     *
+     * Search is performed on full QName equals, this means builders and schema
+     * path MUST be resolved against imports and their namespaces.
+     *
+     * Search is done in data namespace, this means notification, rpc
+     * definitions and top level data definitions are considered as top-level
+     * items, from which it is possible to traverse.
+     *
+     *
+     * @param schemaPath
+     *            Schema Path to node
+     * @param module
+     *            ModuleBuilder to start lookup in
+     * @return Node Builder if found, {@link Optional#absent()} otherwise.
+     */
+    public static Optional<SchemaNodeBuilder> findSchemaNodeInModule(final SchemaPath schemaPath,
+            final ModuleBuilder module) {
+        Iterator<QName> path = schemaPath.getPathFromRoot().iterator();
+        Preconditions.checkArgument(path.hasNext(), "Schema Path must contain at least one element.");
+        QName first = path.next();
+        Optional<SchemaNodeBuilder> currentNode = getDataNamespaceChild(module, first);
 
-        SchemaNodeBuilder node = module.getDataChildByName(first.getLocalName());
-        if (node == null) {
-            Set<NotificationBuilder> notifications = module.getAddedNotifications();
-            for (NotificationBuilder notification : notifications) {
-                if (notification.getQName().getLocalName().equals(first.getLocalName())) {
-                    node = notification;
-                }
+        while (currentNode.isPresent() && path.hasNext()) {
+            currentNode = findDataChild(currentNode.get(), path.next());
+        }
+        return currentNode;
+    }
+
+    private static Optional<SchemaNodeBuilder> findDataChild(SchemaNodeBuilder parent, QName child) {
+        if (parent instanceof DataNodeContainerBuilder) {
+            return castOptional(SchemaNodeBuilder.class,
+                    findDataChildInDataNodeContainer((DataNodeContainerBuilder) parent, child));
+        } else if (parent instanceof ChoiceBuilder) {
+            return castOptional(SchemaNodeBuilder.class, findCaseInChoice((ChoiceBuilder) parent, child));
+        } else if (parent instanceof RpcDefinitionBuilder) {
+            return castOptional(SchemaNodeBuilder.class, findContainerInRpc((RpcDefinitionBuilder) parent, child));
+
+        } else {
+            LOG.trace("Child {} not found in node {}", child, parent);
+            return Optional.absent();
+        }
+    }
+
+    /**
+     * Casts optional from one argument to other.
+     *
+     * @param cls
+     *            Class to be checked
+     * @param optional
+     *            Original value
+     * @return
+     */
+    private static <T> Optional<T> castOptional(Class<T> cls, Optional<?> optional) {
+        if (optional.isPresent()) {
+            Object value = optional.get();
+            if (cls.isInstance(value)) {
+                @SuppressWarnings("unchecked")
+                // Actually checked by outer if
+                T casted = (T) value;
+                return Optional.of(casted);
             }
         }
-        if (node == null) {
-            Set<RpcDefinitionBuilder> rpcs = module.getAddedRpcs();
-            for (RpcDefinitionBuilder rpc : rpcs) {
-                if (rpc.getQName().getLocalName().equals(first.getLocalName())) {
-                    node = rpc;
-                }
+        return Optional.absent();
+    }
+
+    /**
+     *
+     * Gets input / output container from {@link RpcDefinitionBuilder} if QName
+     * is input/output.
+     *
+     *
+     * @param parent
+     *            RPC Definition builder
+     * @param child
+     *            Child QName
+     * @return Optional of input/output if defined and QName is input/output.
+     *         Otherwise {@link Optional#absent()}.
+     */
+    private static Optional<ContainerSchemaNodeBuilder> findContainerInRpc(RpcDefinitionBuilder parent, QName child) {
+        if (INPUT.equals(child.getLocalName())) {
+            return Optional.of(parent.getInput());
+        } else if (OUTPUT.equals(child.getLocalName())) {
+            return Optional.of(parent.getOutput());
+        }
+        LOG.trace("Child {} not found in node {}", child, parent);
+        return Optional.absent();
+    }
+
+    /**
+     * Finds case by QName in {@link ChoiceBuilder}
+     *
+     *
+     * @param parent
+     *            DataNodeContainer in which lookup should be performed
+     * @param child
+     *            QName of child
+     * @return Optional of child if found.
+     */
+
+    private static Optional<ChoiceCaseBuilder> findCaseInChoice(ChoiceBuilder parent, QName child) {
+        for (ChoiceCaseBuilder caze : parent.getCases()) {
+            if (caze.getQName().equals(child)) {
+                return Optional.of(caze);
             }
         }
-        if (node == null) {
-            return null;
+        LOG.trace("Child {} not found in node {}", child, parent);
+        return Optional.absent();
+    }
+
+    /**
+     * Finds direct child by QName in {@link DataNodeContainerBuilder}
+     *
+     *
+     * @param parent
+     *            DataNodeContainer in which lookup should be performed
+     * @param child
+     *            QName of child
+     * @return Optional of child if found.
+     */
+    private static Optional<DataSchemaNodeBuilder> findDataChildInDataNodeContainer(DataNodeContainerBuilder parent,
+            QName child) {
+        for (DataSchemaNodeBuilder childNode : parent.getChildNodeBuilders()) {
+            if (childNode.getQName().equals(child)) {
+                return Optional.of(childNode);
+            }
+        }
+        LOG.trace("Child {} not found in node {}", child, parent);
+        return Optional.absent();
+    }
+
+    /**
+     *
+     * Find a child builder for node in data namespace of YANG module.
+     *
+     * Search is performed on full QName equals, this means builders and schema
+     * path MUST be resolved against imports and their namespaces.
+     *
+     * Search is done in data namespace, this means notification, rpc
+     * definitions and top level data definitions are considered as top-level
+     * items, from which it is possible to traverse.
+     *
+     *
+     * @param child
+     *            Child QName.
+     * @param module
+     *            ModuleBuilder to start lookup in
+     * @return Node Builder if found, {@link Optional#absent()} otherwise.
+     */
+    private static Optional<SchemaNodeBuilder> getDataNamespaceChild(ModuleBuilder module, QName child) {
+        /*
+         * First we do lookup in data tree, if node is found we return it.
+         */
+        final Optional<SchemaNodeBuilder> dataTreeNode = getDataChildByQName(module, child);
+        if (dataTreeNode.isPresent()) {
+            return dataTreeNode;
+        }
+
+        /*
+         * We lookup in notifications
+         */
+        Set<NotificationBuilder> notifications = module.getAddedNotifications();
+        for (NotificationBuilder notification : notifications) {
+            if (notification.getQName().equals(child)) {
+                return Optional.<SchemaNodeBuilder> of(notification);
+            }
         }
 
-        if (!path.isEmpty()) {
-            node = findSchemaNode(path, node);
+        /*
+         * We lookup in RPCs
+         */
+        Set<RpcDefinitionBuilder> rpcs = module.getAddedRpcs();
+        for (RpcDefinitionBuilder rpc : rpcs) {
+            if (rpc.getQName().equals(child)) {
+                return Optional.<SchemaNodeBuilder> of(rpc);
+            }
         }
+        LOG.trace("Child {} not found in data namespace of module {}", child, module);
+        return Optional.absent();
+    }
 
-        return node;
+    private static Optional<SchemaNodeBuilder> getDataChildByQName(DataNodeContainerBuilder builder, QName child) {
+        for (DataSchemaNodeBuilder childNode : builder.getChildNodeBuilders()) {
+            if (childNode.getQName().equals(child)) {
+                return Optional.<SchemaNodeBuilder> of(childNode);
+            }
+        }
+        LOG.trace("Child {} not found in node {}", child, builder);
+        return Optional.absent();
     }
 
     /**
@@ -512,14 +682,17 @@ public final class ParserUtils {
      *            path to augment target
      * @return true if augmentation process succeed, false otherwise
      */
-    public static boolean processAugmentation(final AugmentationSchemaBuilder augment, final ModuleBuilder firstNodeParent) {
-        List<QName> path = augment.getTargetPath().getPath();
-        Builder targetNode = findSchemaNodeInModule(path, firstNodeParent);
-        if (targetNode == null) {
+    public static boolean processAugmentation(final AugmentationSchemaBuilder augment,
+            final ModuleBuilder firstNodeParent) {
+        Optional<SchemaNodeBuilder> potentialTargetNode = findSchemaNodeInModule(augment.getTargetNodeSchemaPath(),
+                firstNodeParent);
+        if (!potentialTargetNode.isPresent()) {
             return false;
         }
-
+        SchemaNodeBuilder targetNode = potentialTargetNode.get();
         fillAugmentTarget(augment, targetNode);
+        Preconditions.checkState(targetNode instanceof AugmentationTargetBuilder,
+                "Node refered by augmentation must be valid augmentation target");
         ((AugmentationTargetBuilder) targetNode).addAugmentation(augment);
         augment.setResolved(true);
         return true;
@@ -549,7 +722,8 @@ public final class ParserUtils {
         }
     }
 
-    public static IdentitySchemaNodeBuilder findIdentity(final Set<IdentitySchemaNodeBuilder> identities, final String name) {
+    public static IdentitySchemaNodeBuilder findIdentity(final Set<IdentitySchemaNodeBuilder> identities,
+            final String name) {
         for (IdentitySchemaNodeBuilder identity : identities) {
             if (identity.getQName().getLocalName().equals(name)) {
                 return identity;
@@ -580,8 +754,9 @@ public final class ParserUtils {
         return parentModule;
     }
 
-    public static Set<DataSchemaNodeBuilder> wrapChildNodes(final String moduleName, final int line, final Set<DataSchemaNode> nodes,
-            final SchemaPath parentPath, final URI ns, final Date rev, final String pref) {
+    public static Set<DataSchemaNodeBuilder> wrapChildNodes(final String moduleName, final int line,
+            final Set<DataSchemaNode> nodes, final SchemaPath parentPath, final URI ns, final Date rev,
+            final String pref) {
         Set<DataSchemaNodeBuilder> result = new HashSet<>();
 
         for (DataSchemaNode node : nodes) {
@@ -592,8 +767,8 @@ public final class ParserUtils {
         return result;
     }
 
-    public static DataSchemaNodeBuilder wrapChildNode(final String moduleName, final int line, final DataSchemaNode node,
-            final SchemaPath parentPath, final QName qname) {
+    public static DataSchemaNodeBuilder wrapChildNode(final String moduleName, final int line,
+            final DataSchemaNode node, final SchemaPath parentPath, final QName qname) {
 
         final SchemaPath schemaPath = parentPath.createChild(qname);
 
@@ -617,8 +792,9 @@ public final class ParserUtils {
         }
     }
 
-    public static Set<GroupingBuilder> wrapGroupings(final String moduleName, final int line, final Set<GroupingDefinition> nodes,
-            final SchemaPath parentPath, final URI ns, final Date rev, final String pref) {
+    public static Set<GroupingBuilder> wrapGroupings(final String moduleName, final int line,
+            final Set<GroupingDefinition> nodes, final SchemaPath parentPath, final URI ns, final Date rev,
+            final String pref) {
         Set<GroupingBuilder> result = new HashSet<>();
         for (GroupingDefinition node : nodes) {
             QName qname = new QName(ns, rev, pref, node.getQName().getLocalName());
@@ -628,8 +804,9 @@ public final class ParserUtils {
         return result;
     }
 
-    public static Set<TypeDefinitionBuilder> wrapTypedefs(final String moduleName, final int line, final DataNodeContainer dataNode,
-            final SchemaPath parentPath, final URI ns, final Date rev, final String pref) {
+    public static Set<TypeDefinitionBuilder> wrapTypedefs(final String moduleName, final int line,
+            final DataNodeContainer dataNode, final SchemaPath parentPath, final URI ns, final Date rev,
+            final String pref) {
         Set<TypeDefinition<?>> nodes = dataNode.getTypeDefinitions();
         Set<TypeDefinitionBuilder> result = new HashSet<>();
         for (TypeDefinition<?> node : nodes) {
@@ -643,7 +820,8 @@ public final class ParserUtils {
     }
 
     public static List<UnknownSchemaNodeBuilder> wrapUnknownNodes(final String moduleName, final int line,
-            final List<UnknownSchemaNode> nodes, final SchemaPath parentPath, final URI ns, final Date rev, final String pref) {
+            final List<UnknownSchemaNode> nodes, final SchemaPath parentPath, final URI ns, final Date rev,
+            final String pref) {
         List<UnknownSchemaNodeBuilder> result = new ArrayList<>();
         for (UnknownSchemaNode node : nodes) {
             QName qname = new QName(ns, rev, pref, node.getQName().getLocalName());
index 52c7cfcb3469a969ad35cffccbcf5e848165b19c..92e6f31e64e835ee34af115caaa02fed728cb601 100644 (file)
@@ -11,8 +11,12 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
-import java.io.*;
-import java.util.*;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
 
 import org.junit.Test;
 import org.opendaylight.yangtools.yang.model.parser.api.YangModelParser;
@@ -174,8 +178,9 @@ public class YangParserNegativeTest {
                 fail("YangParseException should by thrown");
             }
         } catch (YangParseException e) {
-            String expected = "Error in module 'augment1' at line 10: Failed to perform augmentation: Error in module 'augment0' at line 8: Can not add 'leaf id' to 'container bar' in module 'augment0': node with same name already declared at line 9";
-            assertEquals(expected, e.getMessage());
+            assertTrue(e.getMessage().contains("Error in module 'augment1'"));
+            assertTrue(e.getMessage().contains("Failed to perform augmentation:"));
+
         }
     }
 
@@ -189,8 +194,8 @@ public class YangParserNegativeTest {
                 fail("YangParseException should by thrown");
             }
         } catch (YangParseException e) {
-            String expected = "Error in module 'augment0' at line 17: Can not add 'anyxml delta' to node 'choice-ext' in module 'augment0': case with same name already declared at line 18";
-            assertEquals(expected, e.getMessage());
+            assertTrue(e.getMessage().contains("Error in module "));
+            assertTrue(e.getMessage().contains("case with same name already declared "));
         }
     }
 
index ff8519ccdbacd6e26a652f70c86a73bc12815925..27b0f3f8c58f0ba4c0b8639c4665ecd0bfb53366 100644 (file)
@@ -3,6 +3,8 @@ module augment0 {
     namespace "urn:simple.augment0.demo";
     prefix "a0";
 
+    revision "2014-06-02";
+
     container foo {
         description "foo container";
         container bar {
index d08ea8f062f9b9b0092d495272cde33bf73958b4..8ccafd560815a754d75c4052f81ab7afe70d8b4f 100644 (file)
@@ -1,12 +1,21 @@
 module augment1 {
     yang-version 1;
-    namespace "urn:simple.augment0.demo";
+    namespace "urn:simple.augment1.demo";
     prefix "a1";
 
+
     import augment0 {
         prefix "a0";
     }
 
+    revision "2014-06-02";
+
+    augment "/a0:foo/a0:bar" {
+        leaf id {
+            type string;
+        }
+    }
+
     augment "/a0:foo/a0:bar" {
         leaf id {
             type string;
index 4d87619ae25fea2b573e3ba054d7f070aef8de2c..632a6c5d926410c8049d81ac7372635ac910e6b3 100644 (file)
@@ -7,6 +7,12 @@ module augment2 {
         prefix "a0";
     }
 
+    revision "2014-06-02";
+
+    augment "/a0:foo/a0:bar/a0:choice-ext" {
+        anyxml delta;
+    }
+
     augment "/a0:foo/a0:bar/a0:choice-ext" {
         anyxml delta;
     }