Implemented refine statement parsing.
[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..a01565fd6bee3f41022581c3cc2a1f3696193d96 100644 (file)
@@ -22,9 +22,12 @@ import org.opendaylight.controller.antlrv4.code.gen.YangParser.Bits_specificatio
 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.Leafref_specificationContext;
 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Length_stmtContext;
@@ -39,8 +42,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 +61,13 @@ 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.Uses_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,11 +76,13 @@ 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;
 import org.opendaylight.controller.yang.model.parser.builder.api.SchemaNodeBuilder;
 import org.opendaylight.controller.yang.model.parser.builder.impl.ConstraintsBuilder;
+import org.opendaylight.controller.yang.model.parser.util.RefineHolder.Refine;
 import org.opendaylight.controller.yang.model.util.BaseConstraints;
 import org.opendaylight.controller.yang.model.util.BinaryType;
 import org.opendaylight.controller.yang.model.util.BitsType;
@@ -84,6 +101,9 @@ public final class YangModelBuilderUtil {
     private static final Logger logger = LoggerFactory
             .getLogger(YangModelBuilderUtil.class);
 
+    private YangModelBuilderUtil() {
+    }
+
     /**
      * Parse given tree and get first string value.
      *
@@ -193,7 +213,7 @@ public final class YangModelBuilderUtil {
             URI namespace, Date revision, 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);
@@ -257,23 +277,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) {
         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 +315,40 @@ 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,
+            Enum_stmtContext ctx, final int highestValue, 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 +357,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 +380,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 +504,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++) {
+        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,6 +531,13 @@ 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) {
         List<RangeConstraint> rangeConstraints = new ArrayList<RangeConstraint>();
@@ -480,10 +561,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 +574,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++) {
+        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,6 +599,13 @@ 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) {
         List<LengthConstraint> lengthConstraints = new ArrayList<LengthConstraint>();
@@ -534,10 +629,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 +642,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(String value) {
         Number result = null;
         if ("min".equals(value) || "max".equals(value)) {
             result = new UnknownBoundaryNumber(value);
@@ -566,7 +667,7 @@ public final class YangModelBuilderUtil {
             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 +675,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;
                         }
                     }
                 }
@@ -631,6 +732,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 +770,22 @@ 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 +807,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 +863,8 @@ 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);
     }
 
     /**
@@ -963,7 +984,7 @@ public final class YangModelBuilderUtil {
             type = YangTypesConverter.javaTypeForBaseYangUnsignedIntegerType(
                     typeName, rangeStatements);
         } 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);
         } else if ("bits".equals(typeName)) {
@@ -974,7 +995,7 @@ public final class YangModelBuilderUtil {
             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);
@@ -1020,50 +1041,58 @@ 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(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.
+     *            context to search
      * @param constraintsBuilder
-     *            ConstraintsBuilder to fill.
+     *            ConstraintsBuilder to fill
      */
     public static void parseConstraints(ParseTree ctx,
             ConstraintsBuilder constraintsBuilder) {
@@ -1076,9 +1105,8 @@ public final class YangModelBuilderUtil {
                 Integer min = Integer.valueOf(stringFromNode(childNode));
                 constraintsBuilder.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);
+                constraintsBuilder.addMustDefinition(must);
             } else if (childNode instanceof Mandatory_stmtContext) {
                 for (int j = 0; j < childNode.getChildCount(); j++) {
                     ParseTree mandatoryTree = ctx.getChild(j);
@@ -1121,4 +1149,170 @@ 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) {
+                String refineTarget = stringFromNode(child);
+                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;
+    }
+
+    private static RefineHolder parseRefine(RefineHolder refine,
+            Refine_leaf_stmtsContext refineStmt) {
+        refine.setType(Refine.LEAF);
+        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) {
+        refine.setType(Refine.CONTAINER);
+        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) {
+        refine.setType(Refine.LIST);
+        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) {
+        refine.setType(Refine.LEAF_LIST);
+        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) {
+        refine.setType(Refine.CHOICE);
+        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) {
+        refine.setType(Refine.ANYXML);
+        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;
+    }
+
 }