Fixed SchemaPath resolution for base YANG types.
[controller.git] / opendaylight / sal / yang-prototype / code-generator / yang-model-parser-impl / src / main / java / org / opendaylight / controller / yang / model / parser / util / YangModelBuilderUtil.java
index cbeed0959ede0ed471ae6ced0f9d83e1c4813cdf..fff33b63bd513baa2b4e435b6266e497ce5ea874 100644 (file)
@@ -17,15 +17,20 @@ import java.util.Stack;
 import org.antlr.v4.runtime.tree.ParseTree;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Argument_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Base_stmtContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Bit_stmtContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Bits_specificationContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Config_argContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Config_stmtContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Decimal64_specificationContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Default_stmtContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Description_stmtContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Enum_specificationContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Enum_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Error_app_tag_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Error_message_stmtContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Fraction_digits_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Identityref_specificationContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Leafref_specificationContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Length_stmtContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Mandatory_argContext;
@@ -39,8 +44,17 @@ import org.opendaylight.controller.antlrv4.code.gen.YangParser.Ordered_by_stmtCo
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Path_stmtContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Pattern_stmtContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Position_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Presence_stmtContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Range_stmtContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Reference_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Refine_anyxml_stmtsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Refine_choice_stmtsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Refine_container_stmtsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Refine_leaf_list_stmtsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Refine_leaf_stmtsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Refine_list_stmtsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Refine_pomContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Refine_stmtContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Require_instance_argContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Require_instance_stmtContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_argContext;
@@ -49,10 +63,12 @@ import org.opendaylight.controller.antlrv4.code.gen.YangParser.StringContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.String_restrictionsContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Type_body_stmtsContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Units_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Value_stmtContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.When_stmtContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yin_element_argContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yin_element_stmtContext;
 import org.opendaylight.controller.yang.common.QName;
+import org.opendaylight.controller.yang.model.api.MustDefinition;
 import org.opendaylight.controller.yang.model.api.RevisionAwareXPath;
 import org.opendaylight.controller.yang.model.api.SchemaPath;
 import org.opendaylight.controller.yang.model.api.Status;
@@ -61,6 +77,7 @@ import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
 import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition;
 import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition.Bit;
 import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition;
+import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition.EnumPair;
 import org.opendaylight.controller.yang.model.api.type.LengthConstraint;
 import org.opendaylight.controller.yang.model.api.type.PatternConstraint;
 import org.opendaylight.controller.yang.model.api.type.RangeConstraint;
@@ -69,13 +86,21 @@ import org.opendaylight.controller.yang.model.parser.builder.impl.ConstraintsBui
 import org.opendaylight.controller.yang.model.util.BaseConstraints;
 import org.opendaylight.controller.yang.model.util.BinaryType;
 import org.opendaylight.controller.yang.model.util.BitsType;
+import org.opendaylight.controller.yang.model.util.Decimal64;
 import org.opendaylight.controller.yang.model.util.EnumerationType;
 import org.opendaylight.controller.yang.model.util.InstanceIdentifier;
+import org.opendaylight.controller.yang.model.util.Int16;
+import org.opendaylight.controller.yang.model.util.Int32;
+import org.opendaylight.controller.yang.model.util.Int64;
+import org.opendaylight.controller.yang.model.util.Int8;
 import org.opendaylight.controller.yang.model.util.Leafref;
 import org.opendaylight.controller.yang.model.util.RevisionAwareXPathImpl;
 import org.opendaylight.controller.yang.model.util.StringType;
+import org.opendaylight.controller.yang.model.util.Uint16;
+import org.opendaylight.controller.yang.model.util.Uint32;
+import org.opendaylight.controller.yang.model.util.Uint64;
+import org.opendaylight.controller.yang.model.util.Uint8;
 import org.opendaylight.controller.yang.model.util.UnknownType;
-import org.opendaylight.controller.yang.model.util.YangTypesConverter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -84,6 +109,9 @@ public final class YangModelBuilderUtil {
     private static final Logger logger = LoggerFactory
             .getLogger(YangModelBuilderUtil.class);
 
+    private YangModelBuilderUtil() {
+    }
+
     /**
      * Parse given tree and get first string value.
      *
@@ -114,18 +142,18 @@ public final class YangModelBuilderUtil {
      * @param builder
      *            builder to fill in with parsed statements
      */
-    public static void parseSchemaNodeArgs(ParseTree ctx,
-            SchemaNodeBuilder builder) {
+    public static void parseSchemaNodeArgs(final ParseTree ctx,
+            final SchemaNodeBuilder builder) {
         for (int i = 0; i < ctx.getChildCount(); i++) {
-            ParseTree child = ctx.getChild(i);
+            final ParseTree child = ctx.getChild(i);
             if (child instanceof Description_stmtContext) {
-                String desc = stringFromNode(child);
+                final String desc = stringFromNode(child);
                 builder.setDescription(desc);
             } else if (child instanceof Reference_stmtContext) {
-                String ref = stringFromNode(child);
+                final String ref = stringFromNode(child);
                 builder.setReference(ref);
             } else if (child instanceof Status_stmtContext) {
-                Status status = parseStatus((Status_stmtContext) child);
+                final Status status = parseStatus((Status_stmtContext) child);
                 builder.setStatus(status);
             }
         }
@@ -138,7 +166,7 @@ public final class YangModelBuilderUtil {
      *            status context
      * @return value parsed from context
      */
-    public static Status parseStatus(Status_stmtContext ctx) {
+    public static Status parseStatus(final Status_stmtContext ctx) {
         Status result = null;
         for (int i = 0; i < ctx.getChildCount(); i++) {
             ParseTree statusArg = ctx.getChild(i);
@@ -166,7 +194,7 @@ public final class YangModelBuilderUtil {
      * @return value of units statement as string or null if there is no units
      *         statement
      */
-    public static String parseUnits(ParseTree ctx) {
+    public static String parseUnits(final ParseTree ctx) {
         String units = null;
         for (int i = 0; i < ctx.getChildCount(); i++) {
             ParseTree child = ctx.getChild(i);
@@ -189,11 +217,12 @@ public final class YangModelBuilderUtil {
      * @param prefix
      * @return SchemaPath object.
      */
-    public static SchemaPath createActualSchemaPath(List<String> actualPath,
-            URI namespace, Date revision, String prefix) {
+    public static SchemaPath createActualSchemaPath(
+            final List<String> actualPath, final URI namespace,
+            final Date revision, final String prefix) {
         final List<QName> path = new ArrayList<QName>();
         QName qname;
-        // start from index 1 - module name ommited
+        // start from index 1 - module name omited
         for (int i = 1; i < actualPath.size(); i++) {
             qname = new QName(namespace, revision, prefix, actualPath.get(i));
             path.add(qname);
@@ -208,9 +237,9 @@ public final class YangModelBuilderUtil {
      *            string representation of path
      * @return SchemaPath object
      */
-    public static SchemaPath parseAugmentPath(String augmentPath) {
-        boolean absolute = augmentPath.startsWith("/");
-        String[] splittedPath = augmentPath.split("/");
+    public static SchemaPath parseAugmentPath(final String augmentPath) {
+        final boolean absolute = augmentPath.startsWith("/");
+        final String[] splittedPath = augmentPath.split("/");
         List<QName> path = new ArrayList<QName>();
         QName name;
         for (String pathElement : splittedPath) {
@@ -242,8 +271,8 @@ public final class YangModelBuilderUtil {
      *            current prefix
      * @return YANG list key as java.util.List of QName objects
      */
-    public static List<QName> createListKey(String keyDefinition,
-            URI namespace, Date revision, String prefix) {
+    public static List<QName> createListKey(final String keyDefinition,
+            final URI namespace, final Date revision, final String prefix) {
         List<QName> key = new ArrayList<QName>();
         String[] splittedKey = keyDefinition.split(" ");
 
@@ -257,23 +286,37 @@ public final class YangModelBuilderUtil {
         return key;
     }
 
+    /**
+     * Parse given type body of enumeration statement.
+     *
+     * @param ctx
+     *            type body context to parse
+     * @param path
+     *            actual position in YANG model
+     * @param namespace
+     * @param revision
+     * @param prefix
+     * @return List of EnumPair object parsed from given context
+     */
     private static List<EnumTypeDefinition.EnumPair> getEnumConstants(
-            Type_body_stmtsContext ctx, List<String> path, URI namespace,
-            Date revision, String prefix) {
+            final Type_body_stmtsContext ctx, final List<String> path,
+            final URI namespace, final Date revision, final String prefix) {
         List<EnumTypeDefinition.EnumPair> enumConstants = new ArrayList<EnumTypeDefinition.EnumPair>();
 
-        out: for (int j = 0; j < ctx.getChildCount(); j++) {
+        for (int j = 0; j < ctx.getChildCount(); j++) {
             ParseTree enumSpecChild = ctx.getChild(j);
             if (enumSpecChild instanceof Enum_specificationContext) {
+                int highestValue = -1;
                 for (int k = 0; k < enumSpecChild.getChildCount(); k++) {
                     ParseTree enumChild = enumSpecChild.getChild(k);
                     if (enumChild instanceof Enum_stmtContext) {
-                        enumConstants.add(createEnumPair(
-                                (Enum_stmtContext) enumChild, k, path,
-                                namespace, revision, prefix));
-                        if (k == enumSpecChild.getChildCount() - 1) {
-                            break out;
+                        EnumPair enumPair = createEnumPair(
+                                (Enum_stmtContext) enumChild, highestValue,
+                                path, namespace, revision, prefix);
+                        if (enumPair.getValue() > highestValue) {
+                            highestValue = enumPair.getValue();
                         }
+                        enumConstants.add(enumPair);
                     }
                 }
             }
@@ -281,20 +324,41 @@ public final class YangModelBuilderUtil {
         return enumConstants;
     }
 
+    /**
+     * Parse enum statement context
+     *
+     * @param ctx
+     *            enum statement context
+     * @param highestValue
+     *            current highest value in enumeration
+     * @param path
+     *            actual position in YANG model
+     * @param namespace
+     * @param revision
+     * @param prefix
+     * @return EnumPair object parsed from given context
+     */
     private static EnumTypeDefinition.EnumPair createEnumPair(
-            Enum_stmtContext ctx, final int value, List<String> path,
-            final URI namespace, final Date revision, final String prefix) {
+            final Enum_stmtContext ctx, final int highestValue,
+            final List<String> path, final URI namespace, final Date revision,
+            final String prefix) {
         final String name = stringFromNode(ctx);
         final QName qname = new QName(namespace, revision, prefix, name);
+        Integer value = null;
+
         String description = null;
         String reference = null;
         Status status = null;
+
         List<String> enumPairPath = new ArrayList<String>(path);
         enumPairPath.add(name);
 
         for (int i = 0; i < ctx.getChildCount(); i++) {
             ParseTree child = ctx.getChild(i);
-            if (child instanceof Description_stmtContext) {
+            if (child instanceof Value_stmtContext) {
+                String valueStr = stringFromNode(child);
+                value = Integer.valueOf(valueStr);
+            } else if (child instanceof Description_stmtContext) {
                 description = stringFromNode(child);
             } else if (child instanceof Reference_stmtContext) {
                 reference = stringFromNode(child);
@@ -303,6 +367,17 @@ public final class YangModelBuilderUtil {
             }
         }
 
+        if (value == null) {
+            value = highestValue + 1;
+        }
+        if (value < -2147483648 || value > 2147483647) {
+            throw new YangParseException(
+                    "Error on enum '"
+                            + name
+                            + "': the enum value MUST be in the range from -2147483648 to 2147483647, but was: "
+                            + value);
+        }
+
         EnumPairImpl result = new EnumPairImpl();
         result.qname = qname;
         result.path = createActualSchemaPath(enumPairPath, namespace, revision,
@@ -315,6 +390,9 @@ public final class YangModelBuilderUtil {
         return result;
     }
 
+    /**
+     * Internal implementation of EnumPair.
+     */
     private static class EnumPairImpl implements EnumTypeDefinition.EnumPair {
         private QName qname;
         private SchemaPath path;
@@ -436,20 +514,26 @@ public final class YangModelBuilderUtil {
             return EnumTypeDefinition.EnumPair.class.getSimpleName() + "[name="
                     + name + ", value=" + value + "]";
         }
-    };
+    }
 
+    /**
+     * Get and parse range from given type body context.
+     *
+     * @param ctx
+     *            type body context to parse
+     * @return List of RangeConstraint created from this context
+     */
     private static List<RangeConstraint> getRangeConstraints(
-            Type_body_stmtsContext ctx) {
-        final List<RangeConstraint> rangeConstraints = new ArrayList<RangeConstraint>();
-        for (int j = 0; j < ctx.getChildCount(); j++) {
+            final Type_body_stmtsContext ctx) {
+        List<RangeConstraint> rangeConstraints = Collections.emptyList();
+        outer: for (int j = 0; j < ctx.getChildCount(); j++) {
             ParseTree numRestrChild = ctx.getChild(j);
             if (numRestrChild instanceof Numerical_restrictionsContext) {
                 for (int k = 0; k < numRestrChild.getChildCount(); k++) {
                     ParseTree rangeChild = numRestrChild.getChild(k);
                     if (rangeChild instanceof Range_stmtContext) {
-                        rangeConstraints
-                                .addAll(parseRangeConstraints((Range_stmtContext) rangeChild));
-                        break;
+                        rangeConstraints = parseRangeConstraints((Range_stmtContext) rangeChild);
+                        break outer;
                     }
                 }
             }
@@ -457,8 +541,15 @@ public final class YangModelBuilderUtil {
         return rangeConstraints;
     }
 
+    /**
+     * Parse given range context.
+     *
+     * @param ctx
+     *            range context to parse
+     * @return List of RangeConstraints parsed from this context
+     */
     private static List<RangeConstraint> parseRangeConstraints(
-            Range_stmtContext ctx) {
+            final Range_stmtContext ctx) {
         List<RangeConstraint> rangeConstraints = new ArrayList<RangeConstraint>();
         String description = null;
         String reference = null;
@@ -480,10 +571,10 @@ public final class YangModelBuilderUtil {
             Number min;
             Number max;
             if (splittedRangeDef.length == 1) {
-                min = max = parseRangeValue(splittedRangeDef[0]);
+                min = max = parseNumberConstraintValue(splittedRangeDef[0]);
             } else {
-                min = parseRangeValue(splittedRangeDef[0]);
-                max = parseRangeValue(splittedRangeDef[1]);
+                min = parseNumberConstraintValue(splittedRangeDef[0]);
+                max = parseNumberConstraintValue(splittedRangeDef[1]);
             }
             RangeConstraint range = BaseConstraints.rangeConstraint(min, max,
                     description, reference);
@@ -493,17 +584,24 @@ public final class YangModelBuilderUtil {
         return rangeConstraints;
     }
 
+    /**
+     * Get and parse length from given type body context.
+     *
+     * @param ctx
+     *            type body context to parse
+     * @return List of LengthConstraint created from this context
+     */
     private static List<LengthConstraint> getLengthConstraints(
-            Type_body_stmtsContext ctx) {
-        List<LengthConstraint> lengthConstraints = new ArrayList<LengthConstraint>();
-        for (int j = 0; j < ctx.getChildCount(); j++) {
+            final Type_body_stmtsContext ctx) {
+        List<LengthConstraint> lengthConstraints = Collections.emptyList();
+        outer: for (int j = 0; j < ctx.getChildCount(); j++) {
             ParseTree stringRestrChild = ctx.getChild(j);
             if (stringRestrChild instanceof String_restrictionsContext) {
                 for (int k = 0; k < stringRestrChild.getChildCount(); k++) {
                     ParseTree lengthChild = stringRestrChild.getChild(k);
                     if (lengthChild instanceof Length_stmtContext) {
-                        lengthConstraints
-                                .addAll(parseLengthConstraints((Length_stmtContext) lengthChild));
+                        lengthConstraints = parseLengthConstraints((Length_stmtContext) lengthChild);
+                        break outer;
                     }
                 }
             }
@@ -511,8 +609,15 @@ public final class YangModelBuilderUtil {
         return lengthConstraints;
     }
 
+    /**
+     * Parse given length context.
+     *
+     * @param ctx
+     *            length context to parse
+     * @return List of LengthConstraints parsed from this context
+     */
     private static List<LengthConstraint> parseLengthConstraints(
-            Length_stmtContext ctx) {
+            final Length_stmtContext ctx) {
         List<LengthConstraint> lengthConstraints = new ArrayList<LengthConstraint>();
         String description = null;
         String reference = null;
@@ -534,10 +639,10 @@ public final class YangModelBuilderUtil {
             Number min;
             Number max;
             if (splittedRangeDef.length == 1) {
-                min = max = parseRangeValue(splittedRangeDef[0]);
+                min = max = parseNumberConstraintValue(splittedRangeDef[0]);
             } else {
-                min = parseRangeValue(splittedRangeDef[0]);
-                max = parseRangeValue(splittedRangeDef[1]);
+                min = parseNumberConstraintValue(splittedRangeDef[0]);
+                max = parseNumberConstraintValue(splittedRangeDef[1]);
             }
             LengthConstraint range = BaseConstraints.lengthConstraint(min, max,
                     description, reference);
@@ -547,7 +652,13 @@ public final class YangModelBuilderUtil {
         return lengthConstraints;
     }
 
-    private static Number parseRangeValue(String value) {
+    /**
+     * @param value
+     *            value to parse
+     * @return wrapper object of primitive java type or UnknownBoundaryNumber if
+     *         type is one of special YANG values 'min' or 'max'
+     */
+    private static Number parseNumberConstraintValue(final String value) {
         Number result = null;
         if ("min".equals(value) || "max".equals(value)) {
             result = new UnknownBoundaryNumber(value);
@@ -563,10 +674,10 @@ public final class YangModelBuilderUtil {
     }
 
     private static List<PatternConstraint> getPatternConstraint(
-            Type_body_stmtsContext ctx) {
+            final Type_body_stmtsContext ctx) {
         List<PatternConstraint> patterns = new ArrayList<PatternConstraint>();
 
-        out: for (int j = 0; j < ctx.getChildCount(); j++) {
+        outer: for (int j = 0; j < ctx.getChildCount(); j++) {
             ParseTree stringRestrChild = ctx.getChild(j);
             if (stringRestrChild instanceof String_restrictionsContext) {
                 for (int k = 0; k < stringRestrChild.getChildCount(); k++) {
@@ -574,7 +685,7 @@ public final class YangModelBuilderUtil {
                     if (lengthChild instanceof Pattern_stmtContext) {
                         patterns.add(parsePatternConstraint((Pattern_stmtContext) lengthChild));
                         if (k == lengthChild.getChildCount() - 1) {
-                            break out;
+                            break outer;
                         }
                     }
                 }
@@ -591,7 +702,7 @@ public final class YangModelBuilderUtil {
      * @return PatternConstraint object
      */
     private static PatternConstraint parsePatternConstraint(
-            Pattern_stmtContext ctx) {
+            final Pattern_stmtContext ctx) {
         String description = null;
         String reference = null;
         for (int i = 0; i < ctx.getChildCount(); i++) {
@@ -631,6 +742,14 @@ public final class YangModelBuilderUtil {
         return result.toString();
     }
 
+    /**
+     * Get fraction digits value from context.
+     *
+     * @param ctx
+     *            type body context to parse
+     * @return 'fraction-digits' value if present in given context, null
+     *         otherwise
+     */
     private static Integer getFractionDigits(Type_body_stmtsContext ctx) {
         Integer result = null;
         for (int j = 0; j < ctx.getChildCount(); j++) {
@@ -661,10 +780,23 @@ public final class YangModelBuilderUtil {
         return result;
     }
 
+    /**
+     * Internal helper method for parsing bit statements from given type body
+     * context.
+     *
+     * @param ctx
+     *            type body context to parse
+     * @param actualPath
+     *            current position in YANG model
+     * @param namespace
+     * @param revision
+     * @param prefix
+     * @return List of Bit objects created from this context
+     */
     private static List<BitsTypeDefinition.Bit> getBits(
             Type_body_stmtsContext ctx, List<String> actualPath, URI namespace,
             Date revision, String prefix) {
-        List<BitsTypeDefinition.Bit> bits = new ArrayList<BitsTypeDefinition.Bit>();
+        final List<BitsTypeDefinition.Bit> bits = new ArrayList<BitsTypeDefinition.Bit>();
         for (int j = 0; j < ctx.getChildCount(); j++) {
             ParseTree bitsSpecChild = ctx.getChild(j);
             if (bitsSpecChild instanceof Bits_specificationContext) {
@@ -686,6 +818,20 @@ public final class YangModelBuilderUtil {
         return bits;
     }
 
+    /**
+     * Internal helper method for parsing bit context.
+     *
+     * @param ctx
+     *            bit statement context to parse
+     * @param highestPosition
+     *            current highest position in bits type
+     * @param actualPath
+     *            current position in YANG model
+     * @param namespace
+     * @param revision
+     * @param prefix
+     * @return Bit object parsed from this context
+     */
     private static BitsTypeDefinition.Bit parseBit(final Bit_stmtContext ctx,
             long highestPosition, List<String> actualPath, final URI namespace,
             final Date revision, final String prefix) {
@@ -728,122 +874,9 @@ public final class YangModelBuilderUtil {
                             + "': the position value MUST be in the range 0 to 4294967295");
         }
 
-        final List<UnknownSchemaNode> extensionNodes = Collections.emptyList();
-        return createBit(qname, schemaPath, description, reference, status,
-                extensionNodes, position);
-    }
-
-    private static BitsTypeDefinition.Bit createBit(final QName qname,
-            final SchemaPath schemaPath, final String description,
-            final String reference, final Status status,
-            final List<UnknownSchemaNode> unknownNodes, final Long position) {
-        return new BitsTypeDefinition.Bit() {
-
-            @Override
-            public QName getQName() {
-                return qname;
-            }
-
-            @Override
-            public SchemaPath getPath() {
-                return schemaPath;
-            }
-
-            @Override
-            public String getDescription() {
-                return description;
-            }
-
-            @Override
-            public String getReference() {
-                return reference;
-            }
-
-            @Override
-            public Status getStatus() {
-                return status;
-            }
-
-            @Override
-            public List<UnknownSchemaNode> getUnknownSchemaNodes() {
-                return unknownNodes;
-            }
-
-            @Override
-            public Long getPosition() {
-                return position;
-            }
-
-            @Override
-            public String getName() {
-                return qname.getLocalName();
-            }
-
-            @Override
-            public int hashCode() {
-                final int prime = 31;
-                int result = 1;
-                result = prime * result
-                        + ((qname == null) ? 0 : qname.hashCode());
-                result = prime * result
-                        + ((schemaPath == null) ? 0 : schemaPath.hashCode());
-                result = prime * result
-                        + ((position == null) ? 0 : position.hashCode());
-                result = prime
-                        * result
-                        + ((unknownNodes == null) ? 0 : unknownNodes.hashCode());
-                return result;
-            }
-
-            @Override
-            public boolean equals(Object obj) {
-                if (this == obj) {
-                    return true;
-                }
-                if (obj == null) {
-                    return false;
-                }
-                if (getClass() != obj.getClass()) {
-                    return false;
-                }
-                Bit other = (Bit) obj;
-                if (qname == null) {
-                    if (other.getQName() != null) {
-                        return false;
-                    }
-                } else if (!qname.equals(other.getQName())) {
-                    return false;
-                }
-                if (schemaPath == null) {
-                    if (other.getPath() != null) {
-                        return false;
-                    }
-                } else if (!schemaPath.equals(other.getPath())) {
-                    return false;
-                }
-                if (unknownNodes == null) {
-                    if (other.getUnknownSchemaNodes() != null) {
-                        return false;
-                    }
-                } else if (!unknownNodes.equals(other.getUnknownSchemaNodes())) {
-                    return false;
-                }
-                if (position == null) {
-                    if (other.getPosition() != null) {
-                        return false;
-                    }
-                } else if (!position.equals(other.getPosition())) {
-                    return false;
-                }
-                return true;
-            }
-
-            @Override
-            public String toString() {
-                return Bit.class.getSimpleName() + "[name="
-                        + qname.getLocalName() + ", position=" + position + "]";
-            }
-        };
+        final List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
+        return new BitImpl(position, qname, schemaPath, description, reference,
+                status, unknownNodes);
     }
 
     /**
@@ -941,9 +974,10 @@ public final class YangModelBuilderUtil {
      *            current prefix
      * @return TypeDefinition object based on parsed values.
      */
-    public static TypeDefinition<?> parseTypeBody(String typeName,
-            Type_body_stmtsContext typeBody, List<String> actualPath,
-            URI namespace, Date revision, String prefix) {
+    public static TypeDefinition<?> parseTypeBody(final String typeName,
+            final Type_body_stmtsContext typeBody,
+            final List<String> actualPath, final URI namespace,
+            final Date revision, final String prefix) {
         TypeDefinition<?> type = null;
 
         List<RangeConstraint> rangeStatements = getRangeConstraints(typeBody);
@@ -954,37 +988,69 @@ public final class YangModelBuilderUtil {
                 typeBody, actualPath, namespace, revision, prefix);
 
         if ("decimal64".equals(typeName)) {
-            type = YangTypesConverter.javaTypeForBaseYangDecimal64Type(
-                    rangeStatements, fractionDigits);
+            type = new Decimal64(actualPath, namespace, revision, fractionDigits);
         } else if (typeName.startsWith("int")) {
-            type = YangTypesConverter.javaTypeForBaseYangSignedIntegerType(
-                    typeName, rangeStatements);
+            if (typeName.equals("int8")) {
+                type = new Int8(actualPath, namespace, revision, rangeStatements, null, null);
+            } else if (typeName.equals("int16")) {
+                type = new Int16(actualPath, namespace, revision, rangeStatements, null, null);
+            } else if (typeName.equals("int32")) {
+                type = new Int32(actualPath, namespace, revision, rangeStatements, null, null);
+            } else if (typeName.equals("int64")) {
+                type = new Int64(actualPath, namespace, revision, rangeStatements, null, null);
+            }
         } else if (typeName.startsWith("uint")) {
-            type = YangTypesConverter.javaTypeForBaseYangUnsignedIntegerType(
-                    typeName, rangeStatements);
+            if (typeName.equals("uint8")) {
+                type = new Uint8(actualPath, namespace, revision, rangeStatements, null, null);
+            } else if (typeName.equals("uint16")) {
+                type = new Uint16(actualPath, namespace, revision, rangeStatements, null, null);
+            } else if (typeName.equals("uint32")) {
+                type = new Uint32(actualPath, namespace, revision, rangeStatements, null, null);
+            } else if (typeName.equals("uint64")) {
+                type = new Uint64(actualPath, namespace, revision, rangeStatements, null, null);
+            }
         } else if ("enumeration".equals(typeName)) {
-            type = new EnumerationType(enumConstants);
+            type = new EnumerationType(actualPath, namespace, revision,
+                    enumConstants);
         } else if ("string".equals(typeName)) {
-            type = new StringType(lengthStatements, patternStatements);
+            type = new StringType(actualPath, namespace, revision, lengthStatements, patternStatements);
         } else if ("bits".equals(typeName)) {
-            type = new BitsType(getBits(typeBody, actualPath, namespace,
+            type = new BitsType(actualPath, namespace, revision, getBits(typeBody, actualPath, namespace,
                     revision, prefix));
         } else if ("leafref".equals(typeName)) {
             final String path = parseLeafrefPath(typeBody);
             final boolean absolute = path.startsWith("/");
             RevisionAwareXPath xpath = new RevisionAwareXPathImpl(path,
                     absolute);
-            type = new Leafref(xpath);
+            type = new Leafref(actualPath, namespace, revision, xpath);
         } else if ("binary".equals(typeName)) {
             List<Byte> bytes = Collections.emptyList();
-            type = new BinaryType(bytes, lengthStatements, null);
+            type = new BinaryType(actualPath, namespace, revision, bytes, lengthStatements, null);
         } else if ("instance-identifier".equals(typeName)) {
             boolean requireInstance = isRequireInstance(typeBody);
-            type = new InstanceIdentifier(null, requireInstance);
+            type = new InstanceIdentifier(actualPath, namespace, revision, null, requireInstance);
         }
         return type;
     }
 
+    public static String getIdentityrefBase(Type_body_stmtsContext ctx) {
+        String result = null;
+        outer:
+        for (int i = 0; i < ctx.getChildCount(); i++) {
+            ParseTree child = ctx.getChild(i);
+            if (child instanceof Identityref_specificationContext) {
+                for (int j = 0; j < child.getChildCount(); j++) {
+                    ParseTree baseArg = child.getChild(j);
+                    if (baseArg instanceof Base_stmtContext) {
+                        result = stringFromNode(baseArg);
+                        break outer;
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
     private static boolean isRequireInstance(Type_body_stmtsContext ctx) {
         for (int i = 0; i < ctx.getChildCount(); i++) {
             ParseTree child = ctx.getChild(i);
@@ -1020,76 +1086,83 @@ public final class YangModelBuilderUtil {
      *
      * @param ctx
      *            Must_stmtContext
-     * @return an array of strings with following fields: [0] must text [1]
-     *         description [2] reference
+     * @return MustDefinition object based on parsed context
      */
-    public static String[] parseMust(YangParser.Must_stmtContext ctx) {
-        String[] params = new String[3];
-
+    public static MustDefinition parseMust(final YangParser.Must_stmtContext ctx) {
         StringBuilder mustText = new StringBuilder();
         String description = null;
         String reference = null;
+        String errorAppTag = null;
+        String errorMessage = null;
         for (int i = 0; i < ctx.getChildCount(); ++i) {
             ParseTree child = ctx.getChild(i);
             if (child instanceof StringContext) {
                 final StringContext context = (StringContext) child;
-                for (int j = 0; j < context.getChildCount(); j++) {
-                    String mustPart = context.getChild(j).getText();
-                    if (j == 0) {
-                        mustText.append(mustPart.substring(0,
-                                mustPart.length() - 1));
-                        continue;
-                    }
-                    if (j % 2 == 0) {
-                        mustText.append(mustPart.substring(1));
+                if (context.getChildCount() == 1) {
+                    String mustPart = context.getChild(0).getText();
+                    // trim start and end quotation
+                    mustText.append(mustPart.substring(1, mustPart.length() - 1));
+                } else {
+                    for (int j = 0; j < context.getChildCount(); j++) {
+                        String mustPart = context.getChild(j).getText();
+                        if (j == 0) {
+                            mustText.append(mustPart.substring(0,
+                                    mustPart.length() - 1));
+                            continue;
+                        }
+                        if (j % 2 == 0) {
+                            mustText.append(mustPart.substring(1));
+                        }
                     }
                 }
             } else if (child instanceof Description_stmtContext) {
                 description = stringFromNode(child);
             } else if (child instanceof Reference_stmtContext) {
                 reference = stringFromNode(child);
+            } else if (child instanceof Error_app_tag_stmtContext) {
+                errorAppTag = stringFromNode(child);
+            } else if (child instanceof Error_message_stmtContext) {
+                errorMessage = stringFromNode(child);
             }
         }
-        params[0] = mustText.toString();
-        params[1] = description;
-        params[2] = reference;
 
-        return params;
+        MustDefinition must = new MustDefinitionImpl(mustText.toString(),
+                description, reference, errorAppTag, errorMessage);
+        return must;
     }
 
     /**
      * Parse given tree and set constraints to given builder.
      *
      * @param ctx
-     *            Context to search.
-     * @param constraintsBuilder
-     *            ConstraintsBuilder to fill.
+     *            context to search
+     * @param constraints
+     *            ConstraintsBuilder to fill
      */
-    public static void parseConstraints(ParseTree ctx,
-            ConstraintsBuilder constraintsBuilder) {
+    public static void parseConstraints(final ParseTree ctx,
+            final ConstraintsBuilder constraints) {
         for (int i = 0; i < ctx.getChildCount(); ++i) {
             final ParseTree childNode = ctx.getChild(i);
             if (childNode instanceof Max_elements_stmtContext) {
                 Integer max = Integer.valueOf(stringFromNode(childNode));
-                constraintsBuilder.setMinElements(max);
+                constraints.setMinElements(max);
             } else if (childNode instanceof Min_elements_stmtContext) {
                 Integer min = Integer.valueOf(stringFromNode(childNode));
-                constraintsBuilder.setMinElements(min);
+                constraints.setMinElements(min);
             } else if (childNode instanceof Must_stmtContext) {
-                String[] mustParams = parseMust((Must_stmtContext) childNode);
-                constraintsBuilder.addMustDefinition(mustParams[0],
-                        mustParams[1], mustParams[2]);
+                MustDefinition must = parseMust((Must_stmtContext) childNode);
+                constraints.addMustDefinition(must);
             } else if (childNode instanceof Mandatory_stmtContext) {
                 for (int j = 0; j < childNode.getChildCount(); j++) {
                     ParseTree mandatoryTree = ctx.getChild(j);
                     if (mandatoryTree instanceof Mandatory_argContext) {
                         Boolean mandatory = Boolean
                                 .valueOf(stringFromNode(mandatoryTree));
-                        constraintsBuilder.setMandatory(mandatory);
+                        constraints.setMandatory(mandatory);
                     }
                 }
             } else if (childNode instanceof When_stmtContext) {
-                constraintsBuilder.addWhenCondition(stringFromNode(childNode));
+                constraints.addWhenCondition(stringFromNode(childNode));
             }
         }
     }
@@ -1121,4 +1194,199 @@ public final class YangModelBuilderUtil {
         return yinValue;
     }
 
+//    public static List<RefineHolder> parseRefines(Uses_stmtContext ctx) {
+//        List<RefineHolder> refines = new ArrayList<RefineHolder>();
+//
+//        for (int i = 0; i < ctx.getChildCount(); i++) {
+//            ParseTree child = ctx.getChild(i);
+//            if (child instanceof Refine_stmtContext) {
+//                final String refineTarget = stringFromNode(child);
+//                final RefineHolder refine = new RefineHolder(refineTarget);
+//                for (int j = 0; j < child.getChildCount(); j++) {
+//                    ParseTree refinePom = child.getChild(j);
+//                    if (refinePom instanceof Refine_pomContext) {
+//                        for (int k = 0; k < refinePom.getChildCount(); k++) {
+//                            ParseTree refineStmt = refinePom.getChild(k);
+//                            if (refineStmt instanceof Refine_leaf_stmtsContext) {
+//                                parseRefine(refine,
+//                                        (Refine_leaf_stmtsContext) refineStmt);
+//                            } else if (refineStmt instanceof Refine_container_stmtsContext) {
+//                                parseRefine(
+//                                        refine,
+//                                        (Refine_container_stmtsContext) refineStmt);
+//                            } else if (refineStmt instanceof Refine_list_stmtsContext) {
+//                                parseRefine(refine,
+//                                        (Refine_list_stmtsContext) refineStmt);
+//                            } else if (refineStmt instanceof Refine_leaf_list_stmtsContext) {
+//                                parseRefine(
+//                                        refine,
+//                                        (Refine_leaf_list_stmtsContext) refineStmt);
+//                            } else if (refineStmt instanceof Refine_choice_stmtsContext) {
+//                                parseRefine(refine,
+//                                        (Refine_choice_stmtsContext) refineStmt);
+//                            } else if (refineStmt instanceof Refine_anyxml_stmtsContext) {
+//                                parseRefine(refine,
+//                                        (Refine_anyxml_stmtsContext) refineStmt);
+//                            }
+//                        }
+//                    }
+//                }
+//                refines.add(refine);
+//            }
+//        }
+//        return refines;
+//    }
+
+    public static RefineHolder parseRefine(Refine_stmtContext child) {
+        final String refineTarget = stringFromNode(child);
+        final RefineHolder refine = new RefineHolder(refineTarget);
+        for (int j = 0; j < child.getChildCount(); j++) {
+            ParseTree refinePom = child.getChild(j);
+            if (refinePom instanceof Refine_pomContext) {
+                for (int k = 0; k < refinePom.getChildCount(); k++) {
+                    ParseTree refineStmt = refinePom.getChild(k);
+                    if (refineStmt instanceof Refine_leaf_stmtsContext) {
+                        parseRefine(refine,
+                                (Refine_leaf_stmtsContext) refineStmt);
+                    } else if (refineStmt instanceof Refine_container_stmtsContext) {
+                        parseRefine(
+                                refine,
+                                (Refine_container_stmtsContext) refineStmt);
+                    } else if (refineStmt instanceof Refine_list_stmtsContext) {
+                        parseRefine(refine,
+                                (Refine_list_stmtsContext) refineStmt);
+                    } else if (refineStmt instanceof Refine_leaf_list_stmtsContext) {
+                        parseRefine(
+                                refine,
+                                (Refine_leaf_list_stmtsContext) refineStmt);
+                    } else if (refineStmt instanceof Refine_choice_stmtsContext) {
+                        parseRefine(refine,
+                                (Refine_choice_stmtsContext) refineStmt);
+                    } else if (refineStmt instanceof Refine_anyxml_stmtsContext) {
+                        parseRefine(refine,
+                                (Refine_anyxml_stmtsContext) refineStmt);
+                    }
+                }
+            }
+        }
+        return refine;
+    }
+
+    private static RefineHolder parseRefine(RefineHolder refine,
+            Refine_leaf_stmtsContext refineStmt) {
+        for (int i = 0; i < refineStmt.getChildCount(); i++) {
+            ParseTree refineArg = refineStmt.getChild(i);
+            if (refineArg instanceof Default_stmtContext) {
+                String defaultStr = stringFromNode(refineArg);
+                refine.setDefaultStr(defaultStr);
+            } else if (refineArg instanceof Mandatory_stmtContext) {
+                for (int j = 0; j < refineArg.getChildCount(); j++) {
+                    ParseTree mandatoryTree = refineArg.getChild(j);
+                    if (mandatoryTree instanceof Mandatory_argContext) {
+                        Boolean mandatory = Boolean
+                                .valueOf(stringFromNode(mandatoryTree));
+                        refine.setMandatory(mandatory);
+                    }
+                }
+            } else if (refineArg instanceof Must_stmtContext) {
+                MustDefinition must = parseMust((Must_stmtContext) refineArg);
+                refine.setMust(must);
+
+            }
+        }
+        return refine;
+    }
+
+    private static RefineHolder parseRefine(RefineHolder refine,
+            Refine_container_stmtsContext refineStmt) {
+        for (int m = 0; m < refineStmt.getChildCount(); m++) {
+            ParseTree refineArg = refineStmt.getChild(m);
+            if (refineArg instanceof Must_stmtContext) {
+                MustDefinition must = parseMust((Must_stmtContext) refineArg);
+                refine.setMust(must);
+            } else if (refineArg instanceof Presence_stmtContext) {
+                refine.setPresence(true);
+            }
+        }
+        return refine;
+    }
+
+    private static RefineHolder parseRefine(RefineHolder refine,
+            Refine_list_stmtsContext refineStmt) {
+        for (int m = 0; m < refineStmt.getChildCount(); m++) {
+            ParseTree refineArg = refineStmt.getChild(m);
+            if (refineArg instanceof Must_stmtContext) {
+                MustDefinition must = parseMust((Must_stmtContext) refineArg);
+                refine.setMust(must);
+            } else if (refineArg instanceof Max_elements_stmtContext) {
+                Integer max = Integer.valueOf(stringFromNode(refineArg));
+                refine.setMinElements(max);
+            } else if (refineArg instanceof Min_elements_stmtContext) {
+                Integer min = Integer.valueOf(stringFromNode(refineArg));
+                refine.setMinElements(min);
+            }
+        }
+        return refine;
+    }
+
+    private static RefineHolder parseRefine(RefineHolder refine,
+            Refine_leaf_list_stmtsContext refineStmt) {
+        for (int m = 0; m < refineStmt.getChildCount(); m++) {
+            ParseTree refineArg = refineStmt.getChild(m);
+            if (refineArg instanceof Must_stmtContext) {
+                MustDefinition must = parseMust((Must_stmtContext) refineArg);
+                refine.setMust(must);
+            } else if (refineArg instanceof Max_elements_stmtContext) {
+                Integer max = Integer.valueOf(stringFromNode(refineArg));
+                refine.setMinElements(max);
+            } else if (refineArg instanceof Min_elements_stmtContext) {
+                Integer min = Integer.valueOf(stringFromNode(refineArg));
+                refine.setMinElements(min);
+            }
+        }
+        return refine;
+    }
+
+    private static RefineHolder parseRefine(RefineHolder refine,
+            Refine_choice_stmtsContext refineStmt) {
+        for (int i = 0; i < refineStmt.getChildCount(); i++) {
+            ParseTree refineArg = refineStmt.getChild(i);
+            if (refineArg instanceof Default_stmtContext) {
+                String defaultStr = stringFromNode(refineArg);
+                refine.setDefaultStr(defaultStr);
+            } else if (refineArg instanceof Mandatory_stmtContext) {
+                for (int j = 0; j < refineArg.getChildCount(); j++) {
+                    ParseTree mandatoryTree = refineArg.getChild(j);
+                    if (mandatoryTree instanceof Mandatory_argContext) {
+                        Boolean mandatory = Boolean
+                                .valueOf(stringFromNode(mandatoryTree));
+                        refine.setMandatory(mandatory);
+                    }
+                }
+            }
+        }
+        return refine;
+    }
+
+    private static RefineHolder parseRefine(RefineHolder refine,
+            Refine_anyxml_stmtsContext refineStmt) {
+        for (int i = 0; i < refineStmt.getChildCount(); i++) {
+            ParseTree refineArg = refineStmt.getChild(i);
+            if (refineArg instanceof Must_stmtContext) {
+                MustDefinition must = parseMust((Must_stmtContext) refineArg);
+                refine.setMust(must);
+            } else if (refineArg instanceof Mandatory_stmtContext) {
+                for (int j = 0; j < refineArg.getChildCount(); j++) {
+                    ParseTree mandatoryTree = refineArg.getChild(j);
+                    if (mandatoryTree instanceof Mandatory_argContext) {
+                        Boolean mandatory = Boolean
+                                .valueOf(stringFromNode(mandatoryTree));
+                        refine.setMandatory(mandatory);
+                    }
+                }
+            }
+        }
+        return refine;
+    }
+
 }