-/*\r
- * Copyright (c) 2013 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/eplv10.html\r
- */\r
-package org.opendaylight.controller.yang.model.parser.util;\r
-\r
-import java.net.URI;\r
-import java.util.ArrayList;\r
-import java.util.Collections;\r
-import java.util.Date;\r
-import java.util.List;\r
-import java.util.Stack;\r
-\r
-import org.antlr.v4.runtime.tree.ParseTree;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Bit_stmtContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Bits_specificationContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Config_argContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Config_stmtContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Decimal64_specificationContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Description_stmtContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Enum_specificationContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Enum_stmtContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Fraction_digits_stmtContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Leafref_specificationContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Length_stmtContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Mandatory_argContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Mandatory_stmtContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Max_elements_stmtContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Min_elements_stmtContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Must_stmtContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Numerical_restrictionsContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Ordered_by_argContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Ordered_by_stmtContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Path_stmtContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Pattern_stmtContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Position_stmtContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Range_stmtContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Reference_stmtContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Require_instance_argContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Require_instance_stmtContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_argContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_stmtContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.StringContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.String_restrictionsContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Type_body_stmtsContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.Units_stmtContext;\r
-import org.opendaylight.controller.antlrv4.code.gen.YangParser.When_stmtContext;\r
-import org.opendaylight.controller.yang.common.QName;\r
-import org.opendaylight.controller.yang.model.api.RevisionAwareXPath;\r
-import org.opendaylight.controller.yang.model.api.SchemaPath;\r
-import org.opendaylight.controller.yang.model.api.Status;\r
-import org.opendaylight.controller.yang.model.api.TypeDefinition;\r
-import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;\r
-import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition;\r
-import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition;\r
-import org.opendaylight.controller.yang.model.api.type.LengthConstraint;\r
-import org.opendaylight.controller.yang.model.api.type.PatternConstraint;\r
-import org.opendaylight.controller.yang.model.api.type.RangeConstraint;\r
-import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition.Bit;\r
-import org.opendaylight.controller.yang.model.parser.builder.api.SchemaNodeBuilder;\r
-import org.opendaylight.controller.yang.model.parser.builder.impl.ConstraintsBuilder;\r
-import org.opendaylight.controller.yang.model.util.BaseConstraints;\r
-import org.opendaylight.controller.yang.model.util.BinaryType;\r
-import org.opendaylight.controller.yang.model.util.BitsType;\r
-import org.opendaylight.controller.yang.model.util.EnumerationType;\r
-import org.opendaylight.controller.yang.model.util.InstanceIdentifier;\r
-import org.opendaylight.controller.yang.model.util.Leafref;\r
-import org.opendaylight.controller.yang.model.util.RevisionAwareXPathImpl;\r
-import org.opendaylight.controller.yang.model.util.StringType;\r
-import org.opendaylight.controller.yang.model.util.UnknownType;\r
-import org.opendaylight.controller.yang.model.util.YangTypesConverter;\r
-import org.slf4j.Logger;\r
-import org.slf4j.LoggerFactory;\r
-\r
-public class YangModelBuilderUtil {\r
-\r
- private static final Logger logger = LoggerFactory\r
- .getLogger(YangModelBuilderUtil.class);\r
-\r
- /**\r
- * Parse given tree and get first string value.\r
- *\r
- * @param treeNode\r
- * tree to parse\r
- * @return first string value from given tree\r
- */\r
- public static String stringFromNode(final ParseTree treeNode) {\r
- final String result = "";\r
- for (int i = 0; i < treeNode.getChildCount(); ++i) {\r
- if (treeNode.getChild(i) instanceof StringContext) {\r
- final StringContext context = (StringContext) treeNode\r
- .getChild(i);\r
- if (context != null) {\r
- return context.getChild(0).getText().replace("\"", "");\r
- }\r
- }\r
- }\r
- return result;\r
- }\r
-\r
- /**\r
- * Parse 'description', 'reference' and 'status' statements and fill in\r
- * given builder.\r
- *\r
- * @param ctx\r
- * context to parse\r
- * @param builder\r
- * builder to fill in with parsed statements\r
- */\r
- public static void parseSchemaNodeArgs(ParseTree ctx,\r
- SchemaNodeBuilder builder) {\r
- for (int i = 0; i < ctx.getChildCount(); i++) {\r
- ParseTree child = ctx.getChild(i);\r
- if (child instanceof Description_stmtContext) {\r
- String desc = stringFromNode(child);\r
- builder.setDescription(desc);\r
- } else if (child instanceof Reference_stmtContext) {\r
- String ref = stringFromNode(child);\r
- builder.setReference(ref);\r
- } else if (child instanceof Status_stmtContext) {\r
- Status status = parseStatus((Status_stmtContext) child);\r
- builder.setStatus(status);\r
- }\r
- }\r
- }\r
-\r
- /**\r
- * Parse given context and return its value;\r
- *\r
- * @param ctx\r
- * status context\r
- * @return value parsed from context\r
- */\r
- public static Status parseStatus(Status_stmtContext ctx) {\r
- for (int i = 0; i < ctx.getChildCount(); i++) {\r
- ParseTree statusArg = ctx.getChild(i);\r
- if (statusArg instanceof Status_argContext) {\r
- String statusArgStr = stringFromNode(statusArg);\r
- if (statusArgStr.equals("current")) {\r
- return Status.CURRENT;\r
- } else if (statusArgStr.equals("deprecated")) {\r
- return Status.DEPRECATED;\r
- } else if (statusArgStr.equals("obsolete")) {\r
- return Status.OBSOLETE;\r
- } else {\r
- logger.warn("Invalid 'status' statement: " + statusArgStr);\r
- }\r
- }\r
- }\r
- return null;\r
- }\r
-\r
- /**\r
- * Parse given tree and returns units statement as string.\r
- *\r
- * @param ctx\r
- * context to parse\r
- * @return value of units statement as string or null if there is no units\r
- * statement\r
- */\r
- public static String parseUnits(ParseTree ctx) {\r
- String units = null;\r
- for (int i = 0; i < ctx.getChildCount(); i++) {\r
- ParseTree child = ctx.getChild(i);\r
- if (child instanceof Units_stmtContext) {\r
- units = stringFromNode(child);\r
- break;\r
- }\r
- }\r
- return units;\r
- }\r
-\r
- /**\r
- * Create SchemaPath object from given path list with namespace, revision\r
- * and prefix based on given values.\r
- *\r
- * @param actualPath\r
- * @param namespace\r
- * @param revision\r
- * @param prefix\r
- * @return SchemaPath object.\r
- */\r
- public static SchemaPath createActualSchemaPath(List<String> actualPath,\r
- URI namespace, Date revision, String prefix) {\r
- final List<QName> path = new ArrayList<QName>();\r
- QName qname;\r
- for (String pathElement : actualPath) {\r
- qname = new QName(namespace, revision, prefix, pathElement);\r
- path.add(qname);\r
- }\r
- return new SchemaPath(path, true);\r
- }\r
-\r
- /**\r
- * Create SchemaPath from given string.\r
- *\r
- * @param augmentPath\r
- * string representation of path\r
- * @return SchemaPath object\r
- */\r
- public static SchemaPath parseAugmentPath(String augmentPath) {\r
- boolean absolute = augmentPath.startsWith("/");\r
- String[] splittedPath = augmentPath.split("/");\r
- List<QName> path = new ArrayList<QName>();\r
- QName name;\r
- for (String pathElement : splittedPath) {\r
- if (pathElement.length() > 0) {\r
- String[] splittedElement = pathElement.split(":");\r
- if (splittedElement.length == 1) {\r
- name = new QName(null, null, null, splittedElement[0]);\r
- } else {\r
- name = new QName(null, null, splittedElement[0],\r
- splittedElement[1]);\r
- }\r
- path.add(name);\r
- }\r
- }\r
- return new SchemaPath(path, absolute);\r
- }\r
-\r
- /**\r
- * Create java.util.List of QName objects from given key definition as\r
- * string.\r
- *\r
- * @param keyDefinition\r
- * key definition as string\r
- * @param namespace\r
- * current namespace\r
- * @param revision\r
- * current revision\r
- * @param prefix\r
- * current prefix\r
- * @return YANG list key as java.util.List of QName objects\r
- */\r
- public static List<QName> createListKey(String keyDefinition,\r
- URI namespace, Date revision, String prefix) {\r
- List<QName> key = new ArrayList<QName>();\r
- String[] splittedKey = keyDefinition.split(" ");\r
-\r
- QName qname = null;\r
- for (String keyElement : splittedKey) {\r
- if (keyElement.length() != 0) {\r
- qname = new QName(namespace, revision, prefix, keyElement);\r
- key.add(qname);\r
- }\r
- }\r
- return key;\r
- }\r
-\r
- private static List<EnumTypeDefinition.EnumPair> getEnumConstants(\r
- Type_body_stmtsContext ctx, List<String> path, URI namespace,\r
- Date revision, String prefix) {\r
- List<EnumTypeDefinition.EnumPair> enumConstants = new ArrayList<EnumTypeDefinition.EnumPair>();\r
-\r
- out: for (int j = 0; j < ctx.getChildCount(); j++) {\r
- ParseTree enumSpecChild = ctx.getChild(j);\r
- if (enumSpecChild instanceof Enum_specificationContext) {\r
- for (int k = 0; k < enumSpecChild.getChildCount(); k++) {\r
- ParseTree enumChild = enumSpecChild.getChild(k);\r
- if (enumChild instanceof Enum_stmtContext) {\r
- enumConstants.add(createEnumPair(\r
- (Enum_stmtContext) enumChild, k, path,\r
- namespace, revision, prefix));\r
- if (k == enumSpecChild.getChildCount() - 1) {\r
- break out;\r
- }\r
- }\r
- }\r
- }\r
- }\r
- return enumConstants;\r
- }\r
-\r
- private static EnumTypeDefinition.EnumPair createEnumPair(\r
- Enum_stmtContext ctx, final int value, List<String> path,\r
- final URI namespace, final Date revision, final String prefix) {\r
- final String name = stringFromNode(ctx);\r
- final QName qname = new QName(namespace, revision, prefix, name);\r
- String description = null;\r
- String reference = null;\r
- Status status = null;\r
- List<String> enumPairPath = new ArrayList<String>(path);\r
- enumPairPath.add(name);\r
-\r
- for (int i = 0; i < ctx.getChildCount(); i++) {\r
- ParseTree child = ctx.getChild(i);\r
- if (child instanceof Description_stmtContext) {\r
- description = stringFromNode(child);\r
- } else if (child instanceof Reference_stmtContext) {\r
- reference = stringFromNode(child);\r
- } else if (child instanceof Status_stmtContext) {\r
- status = parseStatus((Status_stmtContext) child);\r
- }\r
- }\r
-\r
- EnumPairImpl result = new EnumPairImpl();\r
- result.qname = qname;\r
- result.path = createActualSchemaPath(enumPairPath, namespace, revision,\r
- prefix);\r
- result.description = description;\r
- result.reference = reference;\r
- result.status = status;\r
- // TODO: extensionSchemaNodes\r
- result.name = name;\r
- result.value = value;\r
- return result;\r
- }\r
-\r
- private static class EnumPairImpl implements EnumTypeDefinition.EnumPair {\r
-\r
- private QName qname;\r
- private SchemaPath path;\r
- private String description;\r
- private String reference;\r
- private Status status;\r
- private List<UnknownSchemaNode> extensionSchemaNodes = Collections\r
- .emptyList();\r
- private String name;\r
- private Integer value;\r
-\r
- @Override\r
- public QName getQName() {\r
- return qname;\r
- }\r
-\r
- @Override\r
- public SchemaPath getPath() {\r
- return path;\r
- }\r
-\r
- @Override\r
- public String getDescription() {\r
- return description;\r
- }\r
-\r
- @Override\r
- public String getReference() {\r
- return reference;\r
- }\r
-\r
- @Override\r
- public Status getStatus() {\r
- return status;\r
- }\r
-\r
- @Override\r
- public List<UnknownSchemaNode> getUnknownSchemaNodes() {\r
- return extensionSchemaNodes;\r
- }\r
-\r
- @Override\r
- public String getName() {\r
- return name;\r
- }\r
-\r
- @Override\r
- public Integer getValue() {\r
- return value;\r
- }\r
-\r
- @Override\r
- public int hashCode() {\r
- final int prime = 31;\r
- int result = 1;\r
- result = prime * result + ((qname == null) ? 0 : qname.hashCode());\r
- result = prime * result + ((path == null) ? 0 : path.hashCode());\r
- result = prime * result\r
- + ((description == null) ? 0 : description.hashCode());\r
- result = prime * result\r
- + ((reference == null) ? 0 : reference.hashCode());\r
- result = prime * result\r
- + ((status == null) ? 0 : status.hashCode());\r
- result = prime\r
- * result\r
- + ((extensionSchemaNodes == null) ? 0\r
- : extensionSchemaNodes.hashCode());\r
- result = prime * result + ((name == null) ? 0 : name.hashCode());\r
- result = prime * result + ((value == null) ? 0 : value.hashCode());\r
- return result;\r
- }\r
-\r
- @Override\r
- public boolean equals(Object obj) {\r
- if (this == obj) {\r
- return true;\r
- }\r
- if (obj == null) {\r
- return false;\r
- }\r
- if (getClass() != obj.getClass()) {\r
- return false;\r
- }\r
- EnumPairImpl other = (EnumPairImpl) obj;\r
- if (qname == null) {\r
- if (other.qname != null) {\r
- return false;\r
- }\r
- } else if (!qname.equals(other.qname)) {\r
- return false;\r
- }\r
- if (path == null) {\r
- if (other.path != null) {\r
- return false;\r
- }\r
- } else if (!path.equals(other.path)) {\r
- return false;\r
- }\r
- if (description == null) {\r
- if (other.description != null) {\r
- return false;\r
- }\r
- } else if (!description.equals(other.description)) {\r
- return false;\r
- }\r
- if (reference == null) {\r
- if (other.reference != null) {\r
- return false;\r
- }\r
- } else if (!reference.equals(other.reference)) {\r
- return false;\r
- }\r
- if (status == null) {\r
- if (other.status != null) {\r
- return false;\r
- }\r
- } else if (!status.equals(other.status)) {\r
- return false;\r
- }\r
- if (extensionSchemaNodes == null) {\r
- if (other.extensionSchemaNodes != null) {\r
- return false;\r
- }\r
- } else if (!extensionSchemaNodes.equals(other.extensionSchemaNodes)) {\r
- return false;\r
- }\r
- if (name == null) {\r
- if (other.name != null) {\r
- return false;\r
- }\r
- } else if (!name.equals(other.name)) {\r
- return false;\r
- }\r
- if (value == null) {\r
- if (other.value != null) {\r
- return false;\r
- }\r
- } else if (!value.equals(other.value)) {\r
- return false;\r
- }\r
- return true;\r
- }\r
-\r
- @Override\r
- public String toString() {\r
- return EnumTypeDefinition.EnumPair.class.getSimpleName() + "[name="\r
- + name + ", value=" + value + "]";\r
- }\r
- };\r
-\r
- private static List<RangeConstraint> getRangeConstraints(\r
- Type_body_stmtsContext ctx) {\r
- final List<RangeConstraint> rangeConstraints = new ArrayList<RangeConstraint>();\r
- for (int j = 0; j < ctx.getChildCount(); j++) {\r
- ParseTree numRestrChild = ctx.getChild(j);\r
- if (numRestrChild instanceof Numerical_restrictionsContext) {\r
- for (int k = 0; k < numRestrChild.getChildCount(); k++) {\r
- ParseTree rangeChild = numRestrChild.getChild(k);\r
- if (rangeChild instanceof Range_stmtContext) {\r
- rangeConstraints\r
- .addAll(parseRangeConstraints((Range_stmtContext) rangeChild));\r
- break;\r
- }\r
- }\r
- }\r
- }\r
- return rangeConstraints;\r
- }\r
-\r
- private static List<RangeConstraint> parseRangeConstraints(\r
- Range_stmtContext ctx) {\r
- List<RangeConstraint> rangeConstraints = new ArrayList<RangeConstraint>();\r
- String description = null;\r
- String reference = null;\r
-\r
- for (int i = 0; i < ctx.getChildCount(); i++) {\r
- ParseTree child = ctx.getChild(i);\r
- if (child instanceof Description_stmtContext) {\r
- description = stringFromNode(child);\r
- } else if (child instanceof Reference_stmtContext) {\r
- reference = stringFromNode(child);\r
- }\r
- }\r
-\r
- String rangeStr = stringFromNode(ctx);\r
- String trimmed = rangeStr.replace(" ", "");\r
- String[] splittedRange = trimmed.split("\\|");\r
- for (String rangeDef : splittedRange) {\r
- String[] splittedRangeDef = rangeDef.split("\\.\\.");\r
- Long min;\r
- Long max;\r
- if (splittedRangeDef.length == 1) {\r
- min = max = parseRangeValue(splittedRangeDef[0]);\r
- } else {\r
- min = parseRangeValue(splittedRangeDef[0]);\r
- max = parseRangeValue(splittedRangeDef[1]);\r
- }\r
- RangeConstraint range = BaseConstraints.rangeConstraint(min, max,\r
- description, reference);\r
- rangeConstraints.add(range);\r
- }\r
-\r
- return rangeConstraints;\r
- }\r
-\r
- private static List<LengthConstraint> getLengthConstraints(\r
- Type_body_stmtsContext ctx) {\r
- List<LengthConstraint> lengthConstraints = new ArrayList<LengthConstraint>();\r
- for (int j = 0; j < ctx.getChildCount(); j++) {\r
- ParseTree stringRestrChild = ctx.getChild(j);\r
- if (stringRestrChild instanceof String_restrictionsContext) {\r
- for (int k = 0; k < stringRestrChild.getChildCount(); k++) {\r
- ParseTree lengthChild = stringRestrChild.getChild(k);\r
- if (lengthChild instanceof Length_stmtContext) {\r
- lengthConstraints\r
- .addAll(parseLengthConstraints((Length_stmtContext) lengthChild));\r
- }\r
- }\r
- }\r
- }\r
- return lengthConstraints;\r
- }\r
-\r
- private static List<LengthConstraint> parseLengthConstraints(\r
- Length_stmtContext ctx) {\r
- List<LengthConstraint> lengthConstraints = new ArrayList<LengthConstraint>();\r
- String description = null;\r
- String reference = null;\r
-\r
- for (int i = 0; i < ctx.getChildCount(); i++) {\r
- ParseTree child = ctx.getChild(i);\r
- if (child instanceof Description_stmtContext) {\r
- description = stringFromNode(child);\r
- } else if (child instanceof Reference_stmtContext) {\r
- reference = stringFromNode(child);\r
- }\r
- }\r
-\r
- String lengthStr = stringFromNode(ctx);\r
- String trimmed = lengthStr.replace(" ", "");\r
- String[] splittedRange = trimmed.split("\\|");\r
- for (String rangeDef : splittedRange) {\r
- String[] splittedRangeDef = rangeDef.split("\\.\\.");\r
- Long min;\r
- Long max;\r
- if (splittedRangeDef.length == 1) {\r
- min = max = parseRangeValue(splittedRangeDef[0]);\r
- } else {\r
- min = parseRangeValue(splittedRangeDef[0]);\r
- max = parseRangeValue(splittedRangeDef[1]);\r
- }\r
- LengthConstraint range = BaseConstraints.lengthConstraint(min, max,\r
- description, reference);\r
- lengthConstraints.add(range);\r
- }\r
-\r
- return lengthConstraints;\r
- }\r
-\r
- private static Long parseRangeValue(String value) {\r
- Long result = null;\r
- if (value.equals("min")) {\r
- result = Long.MIN_VALUE;\r
- } else if (value.equals("max")) {\r
- result = Long.MAX_VALUE;\r
- } else {\r
- result = Long.valueOf(value);\r
- }\r
- return result;\r
- }\r
-\r
- private static List<PatternConstraint> getPatternConstraint(\r
- Type_body_stmtsContext ctx) {\r
- List<PatternConstraint> patterns = new ArrayList<PatternConstraint>();\r
-\r
- out: for (int j = 0; j < ctx.getChildCount(); j++) {\r
- ParseTree stringRestrChild = ctx.getChild(j);\r
- if (stringRestrChild instanceof String_restrictionsContext) {\r
- for (int k = 0; k < stringRestrChild.getChildCount(); k++) {\r
- ParseTree lengthChild = stringRestrChild.getChild(k);\r
- if (lengthChild instanceof Pattern_stmtContext) {\r
- patterns.add(parsePatternConstraint((Pattern_stmtContext) lengthChild));\r
- if (k == lengthChild.getChildCount() - 1) {\r
- break out;\r
- }\r
- }\r
- }\r
- }\r
- }\r
- return patterns;\r
- }\r
-\r
- /**\r
- * Internal helper method.\r
- *\r
- * @param ctx\r
- * pattern context\r
- * @return PatternConstraint object\r
- */\r
- private static PatternConstraint parsePatternConstraint(\r
- Pattern_stmtContext ctx) {\r
- String description = null;\r
- String reference = null;\r
- for (int i = 0; i < ctx.getChildCount(); i++) {\r
- ParseTree child = ctx.getChild(i);\r
- if (child instanceof Description_stmtContext) {\r
- description = stringFromNode(child);\r
- } else if (child instanceof Reference_stmtContext) {\r
- reference = stringFromNode(child);\r
- }\r
- }\r
- String pattern = patternStringFromNode(ctx);\r
- return BaseConstraints.patternConstraint(pattern, description,\r
- reference);\r
- }\r
-\r
- public static String patternStringFromNode(final Pattern_stmtContext treeNode) {\r
- String result = "";\r
- for (int i = 0; i < treeNode.getChildCount(); ++i) {\r
- ParseTree child = treeNode.getChild(i);\r
- if (child instanceof StringContext) {\r
- for(int j = 0; j < child.getChildCount(); j++) {\r
- if(j % 2 == 0) {\r
- String patternToken = child.getChild(j).getText();\r
- result += patternToken.substring(1, patternToken.length()-1);\r
- }\r
- }\r
- }\r
- }\r
- return result;\r
- }\r
-\r
- private static Integer getFractionDigits(Type_body_stmtsContext ctx) {\r
- for (int j = 0; j < ctx.getChildCount(); j++) {\r
- ParseTree dec64specChild = ctx.getChild(j);\r
- if (dec64specChild instanceof Decimal64_specificationContext) {\r
- return parseFractionDigits((Decimal64_specificationContext) dec64specChild);\r
- }\r
- }\r
- return null;\r
- }\r
-\r
- private static Integer parseFractionDigits(\r
- Decimal64_specificationContext ctx) {\r
- for (int k = 0; k < ctx.getChildCount(); k++) {\r
- ParseTree fdChild = ctx.getChild(k);\r
- if (fdChild instanceof Fraction_digits_stmtContext) {\r
- return Integer.valueOf(stringFromNode(fdChild));\r
- }\r
- }\r
- return null;\r
- }\r
-\r
- private static List<BitsTypeDefinition.Bit> getBits(\r
- Type_body_stmtsContext ctx, List<String> actualPath, URI namespace,\r
- Date revision, String prefix) {\r
- List<BitsTypeDefinition.Bit> bits = new ArrayList<BitsTypeDefinition.Bit>();\r
- for (int j = 0; j < ctx.getChildCount(); j++) {\r
- ParseTree bitsSpecChild = ctx.getChild(j);\r
- if (bitsSpecChild instanceof Bits_specificationContext) {\r
- for (int k = 0; k < bitsSpecChild.getChildCount(); k++) {\r
- ParseTree bitChild = bitsSpecChild.getChild(k);\r
- if (bitChild instanceof Bit_stmtContext) {\r
- bits.add(parseBit((Bit_stmtContext) bitChild,\r
- actualPath, namespace, revision, prefix));\r
- }\r
- }\r
- }\r
- }\r
- return bits;\r
- }\r
-\r
- private static boolean isRequireInstance(Type_body_stmtsContext ctx) {\r
- for (int i = 0; i < ctx.getChildCount(); i++) {\r
- ParseTree child = ctx.getChild(i);\r
- if (child instanceof Require_instance_stmtContext) {\r
- for (int j = 0; j < child.getChildCount(); j++) {\r
- ParseTree reqArg = child.getChild(j);\r
- if (reqArg instanceof Require_instance_argContext) {\r
- return Boolean.valueOf(stringFromNode(reqArg));\r
- }\r
- }\r
- }\r
- }\r
- return false;\r
- }\r
-\r
- private static BitsTypeDefinition.Bit parseBit(final Bit_stmtContext ctx,\r
- List<String> actualPath, final URI namespace, final Date revision,\r
- final String prefix) {\r
- String name = stringFromNode(ctx);\r
- final QName qname = new QName(namespace, revision, prefix, name);\r
- Long position = null;\r
-\r
- String description = null;\r
- String reference = null;\r
- Status status = Status.CURRENT;\r
-\r
- Stack<String> bitPath = new Stack<String>();\r
- bitPath.addAll(actualPath);\r
- bitPath.add(name);\r
-\r
- SchemaPath schemaPath = createActualSchemaPath(bitPath, namespace,\r
- revision, prefix);\r
-\r
- for (int i = 0; i < ctx.getChildCount(); i++) {\r
- ParseTree child = ctx.getChild(i);\r
- if (child instanceof Position_stmtContext) {\r
- String positionStr = stringFromNode(child);\r
- position = Long.valueOf(positionStr);\r
- if (position < 0 || position > 4294967295L) {\r
- throw new IllegalArgumentException(\r
- "position value MUST be in the range 0 to 4294967295, but was: "\r
- + position);\r
- }\r
- } else if (child instanceof Description_stmtContext) {\r
- description = stringFromNode(child);\r
- } else if (child instanceof Reference_stmtContext) {\r
- reference = stringFromNode(child);\r
- } else if (child instanceof Status_stmtContext) {\r
- status = parseStatus((Status_stmtContext) child);\r
- }\r
- }\r
-\r
- // TODO: extensionDefinitions\r
- return createBit(qname, schemaPath, description, reference, status,\r
- null, position);\r
- }\r
-\r
- private static BitsTypeDefinition.Bit createBit(final QName qname,\r
- final SchemaPath schemaPath, final String description,\r
- final String reference, final Status status,\r
- final List<UnknownSchemaNode> extensionDefinitions,\r
- final Long position) {\r
- return new BitsTypeDefinition.Bit() {\r
-\r
- @Override\r
- public QName getQName() {\r
- return qname;\r
- }\r
-\r
- @Override\r
- public SchemaPath getPath() {\r
- return schemaPath;\r
- }\r
-\r
- @Override\r
- public String getDescription() {\r
- return description;\r
- }\r
-\r
- @Override\r
- public String getReference() {\r
- return reference;\r
- }\r
-\r
- @Override\r
- public Status getStatus() {\r
- return status;\r
- }\r
-\r
- @Override\r
- public List<UnknownSchemaNode> getUnknownSchemaNodes() {\r
- return extensionDefinitions;\r
- }\r
-\r
- @Override\r
- public Long getPosition() {\r
- return position;\r
- }\r
-\r
- @Override\r
- public String getName() {\r
- return qname.getLocalName();\r
- }\r
-\r
- @Override\r
- public int hashCode() {\r
- final int prime = 31;\r
- int result = 1;\r
- result = prime * result\r
- + ((qname == null) ? 0 : qname.hashCode());\r
- result = prime * result\r
- + ((schemaPath == null) ? 0 : schemaPath.hashCode());\r
- result = prime * result\r
- + ((description == null) ? 0 : description.hashCode());\r
- result = prime * result\r
- + ((reference == null) ? 0 : reference.hashCode());\r
- result = prime * result\r
- + ((status == null) ? 0 : status.hashCode());\r
- result = prime * result\r
- + ((position == null) ? 0 : position.hashCode());\r
- result = prime\r
- * result\r
- + ((extensionDefinitions == null) ? 0\r
- : extensionDefinitions.hashCode());\r
- return result;\r
- }\r
-\r
- @Override\r
- public boolean equals(Object obj) {\r
- if (this == obj) {\r
- return true;\r
- }\r
- if (obj == null) {\r
- return false;\r
- }\r
- if (getClass() != obj.getClass()) {\r
- return false;\r
- }\r
- Bit other = (Bit) obj;\r
- if (qname == null) {\r
- if (other.getQName() != null) {\r
- return false;\r
- }\r
- } else if (!qname.equals(other.getQName())) {\r
- return false;\r
- }\r
- if (schemaPath == null) {\r
- if (other.getPath() != null) {\r
- return false;\r
- }\r
- } else if (!schemaPath.equals(other.getPath())) {\r
- return false;\r
- }\r
- if (description == null) {\r
- if (other.getDescription() != null) {\r
- return false;\r
- }\r
- } else if (!description.equals(other.getDescription())) {\r
- return false;\r
- }\r
- if (reference == null) {\r
- if (other.getReference() != null) {\r
- return false;\r
- }\r
- } else if (!reference.equals(other.getReference())) {\r
- return false;\r
- }\r
- if (status == null) {\r
- if (other.getStatus() != null) {\r
- return false;\r
- }\r
- } else if (!status.equals(other.getStatus())) {\r
- return false;\r
- }\r
- if (extensionDefinitions == null) {\r
- if (other.getUnknownSchemaNodes() != null) {\r
- return false;\r
- }\r
- } else if (!extensionDefinitions.equals(other\r
- .getUnknownSchemaNodes())) {\r
- return false;\r
- }\r
- if (position == null) {\r
- if (other.getPosition() != null) {\r
- return false;\r
- }\r
- } else if (!position.equals(other.getPosition())) {\r
- return false;\r
- }\r
- return true;\r
- }\r
-\r
- @Override\r
- public String toString() {\r
- return Bit.class.getSimpleName() + "[name="\r
- + qname.getLocalName() + ", position=" + position + "]";\r
- }\r
- };\r
- }\r
-\r
- /**\r
- * Parse orderedby statement.\r
- *\r
- * @param childNode\r
- * Ordered_by_stmtContext\r
- * @return true, if orderedby contains value 'user' or false otherwise\r
- */\r
- public static boolean parseUserOrdered(Ordered_by_stmtContext childNode) {\r
- boolean result = false;\r
- for (int j = 0; j < childNode.getChildCount(); j++) {\r
- ParseTree orderArg = childNode.getChild(j);\r
- if (orderArg instanceof Ordered_by_argContext) {\r
- String orderStr = stringFromNode(orderArg);\r
- if (orderStr.equals("system")) {\r
- result = false;\r
- } else if (orderStr.equals("user")) {\r
- result = true;\r
- } else {\r
- logger.warn("Invalid 'orderedby' statement.");\r
- }\r
- }\r
- }\r
- return result;\r
- }\r
-\r
- /**\r
- * Parse given config context and return true if it contains string 'true',\r
- * false otherwise.\r
- *\r
- * @param ctx\r
- * config context to parse.\r
- * @return true if given context contains string 'true', false otherwise\r
- */\r
- public static boolean parseConfig(final Config_stmtContext ctx) {\r
- if (ctx != null) {\r
- for (int i = 0; i < ctx.getChildCount(); ++i) {\r
- final ParseTree configContext = ctx.getChild(i);\r
- if (configContext instanceof Config_argContext) {\r
- final String value = stringFromNode(configContext);\r
- if (value.equals("true")) {\r
- return true;\r
- }\r
- }\r
- }\r
- }\r
- return false;\r
- }\r
-\r
- /**\r
- * Parse given type body and creates UnknownType definition.\r
- *\r
- * @param typedefQName\r
- * qname of current type\r
- * @param ctx\r
- * type body\r
- * @return UnknownType object with constraints from parsed type body\r
- */\r
- public static TypeDefinition<?> parseUnknownTypeBody(QName typedefQName,\r
- Type_body_stmtsContext ctx) {\r
- UnknownType.Builder ut = new UnknownType.Builder(typedefQName);\r
-\r
- if (ctx != null) {\r
- List<RangeConstraint> rangeStatements = getRangeConstraints(ctx);\r
- List<LengthConstraint> lengthStatements = getLengthConstraints(ctx);\r
- List<PatternConstraint> patternStatements = getPatternConstraint(ctx);\r
- Integer fractionDigits = getFractionDigits(ctx);\r
-\r
- ut.rangeStatements(rangeStatements);\r
- ut.lengthStatements(lengthStatements);\r
- ut.patterns(patternStatements);\r
- ut.fractionDigits(fractionDigits);\r
- }\r
-\r
- return ut.build();\r
- }\r
-\r
- /**\r
- * Create TypeDefinition object based on given type name and type body.\r
- *\r
- * @param typeName\r
- * name of type\r
- * @param typeBody\r
- * type body\r
- * @param actualPath\r
- * current path in schema\r
- * @param namespace\r
- * current namespace\r
- * @param revision\r
- * current revision\r
- * @param prefix\r
- * current prefix\r
- * @return TypeDefinition object based on parsed values.\r
- */\r
- public static TypeDefinition<?> parseTypeBody(String typeName,\r
- Type_body_stmtsContext typeBody, List<String> actualPath,\r
- URI namespace, Date revision, String prefix) {\r
- TypeDefinition<?> type = null;\r
-\r
- List<RangeConstraint> rangeStatements = getRangeConstraints(typeBody);\r
- Integer fractionDigits = getFractionDigits(typeBody);\r
- List<LengthConstraint> lengthStatements = getLengthConstraints(typeBody);\r
- List<PatternConstraint> patternStatements = getPatternConstraint(typeBody);\r
- List<EnumTypeDefinition.EnumPair> enumConstants = getEnumConstants(typeBody, actualPath, namespace, revision, prefix);\r
-\r
- if (typeName.equals("decimal64")) {\r
- type = YangTypesConverter.javaTypeForBaseYangDecimal64Type(\r
- rangeStatements, fractionDigits);\r
- } else if (typeName.startsWith("int")) {\r
- type = YangTypesConverter.javaTypeForBaseYangSignedIntegerType(typeName,\r
- rangeStatements);\r
- } else if(typeName.startsWith("uint")) {\r
- type = YangTypesConverter.javaTypeForBaseYangUnsignedIntegerType(typeName,\r
- rangeStatements);\r
- } else if (typeName.equals("enumeration")) {\r
- type = new EnumerationType(enumConstants);\r
- } else if (typeName.equals("string")) {\r
- type = new StringType(lengthStatements, patternStatements);\r
- } else if (typeName.equals("bits")) {\r
- type = new BitsType(getBits(typeBody, actualPath, namespace,\r
- revision, prefix));\r
- } else if (typeName.equals("leafref")) {\r
- final String path = parseLeafrefPath(typeBody);\r
- final boolean absolute = path.startsWith("/");\r
- RevisionAwareXPath xpath = new RevisionAwareXPathImpl(path,\r
- absolute);\r
- type = new Leafref(actualPath, namespace, revision, xpath);\r
- } else if (typeName.equals("binary")) {\r
- type = new BinaryType(null, lengthStatements, null);\r
- } else if (typeName.equals("instance-identifier")) {\r
- boolean requireInstance = isRequireInstance(typeBody);\r
- type = new InstanceIdentifier(null, requireInstance);\r
- }\r
- return type;\r
- }\r
-\r
- private static String parseLeafrefPath(Type_body_stmtsContext ctx) {\r
- for (int i = 0; i < ctx.getChildCount(); i++) {\r
- ParseTree child = ctx.getChild(i);\r
- if (child instanceof Leafref_specificationContext) {\r
- for (int j = 0; j < child.getChildCount(); j++) {\r
- ParseTree leafRefSpec = child.getChild(j);\r
- if (leafRefSpec instanceof Path_stmtContext) {\r
- return stringFromNode(leafRefSpec);\r
- }\r
- }\r
- }\r
- }\r
- return null;\r
- }\r
-\r
- /**\r
- * Internal helper method for parsing Must_stmtContext.\r
- *\r
- * @param ctx\r
- * Must_stmtContext\r
- * @return an array of strings with following fields: [0] must text [1]\r
- * description [2] reference\r
- */\r
- public static String[] parseMust(YangParser.Must_stmtContext ctx) {\r
- String[] params = new String[3];\r
-\r
- String mustText = "";\r
- String description = null;\r
- String reference = null;\r
- for (int i = 0; i < ctx.getChildCount(); ++i) {\r
- ParseTree child = ctx.getChild(i);\r
- if (child instanceof StringContext) {\r
- final StringContext context = (StringContext) child;\r
- for (int j = 0; j < context.getChildCount(); j++) {\r
- String mustPart = context.getChild(j).getText();\r
- if (j == 0) {\r
- mustText += mustPart\r
- .substring(0, mustPart.length() - 1);\r
- continue;\r
- }\r
- if (j % 2 == 0) {\r
- mustText += mustPart.substring(1);\r
- }\r
- }\r
- } else if (child instanceof Description_stmtContext) {\r
- description = stringFromNode(child);\r
- } else if (child instanceof Reference_stmtContext) {\r
- reference = stringFromNode(child);\r
- }\r
- }\r
- params[0] = mustText;\r
- params[1] = description;\r
- params[2] = reference;\r
-\r
- return params;\r
- }\r
-\r
- /**\r
- * Parse given tree and set constraints to given builder.\r
- *\r
- * @param ctx\r
- * Context to search.\r
- * @param constraintsBuilder\r
- * ConstraintsBuilder to fill.\r
- */\r
- public static void parseConstraints(ParseTree ctx,\r
- ConstraintsBuilder constraintsBuilder) {\r
- for (int i = 0; i < ctx.getChildCount(); ++i) {\r
- final ParseTree childNode = ctx.getChild(i);\r
- if (childNode instanceof Max_elements_stmtContext) {\r
- Integer max = Integer.valueOf(stringFromNode(childNode));\r
- constraintsBuilder.setMinElements(max);\r
- } else if (childNode instanceof Min_elements_stmtContext) {\r
- Integer min = Integer.valueOf(stringFromNode(childNode));\r
- constraintsBuilder.setMinElements(min);\r
- } else if (childNode instanceof Must_stmtContext) {\r
- String[] mustParams = parseMust((Must_stmtContext) childNode);\r
- constraintsBuilder.addMustDefinition(mustParams[0],\r
- mustParams[1], mustParams[2]);\r
- } else if (childNode instanceof Mandatory_stmtContext) {\r
- for (int j = 0; j < childNode.getChildCount(); j++) {\r
- ParseTree mandatoryTree = ctx.getChild(j);\r
- if (mandatoryTree instanceof Mandatory_argContext) {\r
- Boolean mandatory = Boolean\r
- .valueOf(stringFromNode(mandatoryTree));\r
- constraintsBuilder.setMandatory(mandatory);\r
- }\r
- }\r
- } else if (childNode instanceof When_stmtContext) {\r
- constraintsBuilder.addWhenCondition(stringFromNode(childNode));\r
- }\r
- }\r
- }\r
-\r
-}\r
+/*
+ * 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/eplv10.html
+ */
+package org.opendaylight.controller.yang.model.parser.util;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+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.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.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.Fraction_digits_stmtContext;
+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;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Mandatory_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Max_elements_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Min_elements_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Must_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Numerical_restrictionsContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Ordered_by_argContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Ordered_by_stmtContext;
+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.Range_stmtContext;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Reference_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;
+import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_stmtContext;
+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.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.RevisionAwareXPath;
+import org.opendaylight.controller.yang.model.api.SchemaPath;
+import org.opendaylight.controller.yang.model.api.Status;
+import org.opendaylight.controller.yang.model.api.TypeDefinition;
+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.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.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.EnumerationType;
+import org.opendaylight.controller.yang.model.util.InstanceIdentifier;
+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.UnknownType;
+import org.opendaylight.controller.yang.model.util.YangTypesConverter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class YangModelBuilderUtil {
+
+ private static final Logger logger = LoggerFactory
+ .getLogger(YangModelBuilderUtil.class);
+
+ /**
+ * Parse given tree and get first string value.
+ *
+ * @param treeNode
+ * tree to parse
+ * @return first string value from given tree
+ */
+ public static String stringFromNode(final ParseTree treeNode) {
+ final String result = "";
+ for (int i = 0; i < treeNode.getChildCount(); ++i) {
+ if (treeNode.getChild(i) instanceof StringContext) {
+ final StringContext context = (StringContext) treeNode
+ .getChild(i);
+ if (context != null) {
+ return context.getChild(0).getText().replace("\"", "");
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Parse 'description', 'reference' and 'status' statements and fill in
+ * given builder.
+ *
+ * @param ctx
+ * context to parse
+ * @param builder
+ * builder to fill in with parsed statements
+ */
+ public static void parseSchemaNodeArgs(ParseTree ctx,
+ SchemaNodeBuilder builder) {
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Description_stmtContext) {
+ String desc = stringFromNode(child);
+ builder.setDescription(desc);
+ } else if (child instanceof Reference_stmtContext) {
+ String ref = stringFromNode(child);
+ builder.setReference(ref);
+ } else if (child instanceof Status_stmtContext) {
+ Status status = parseStatus((Status_stmtContext) child);
+ builder.setStatus(status);
+ }
+ }
+ }
+
+ /**
+ * Parse given context and return its value;
+ *
+ * @param ctx
+ * status context
+ * @return value parsed from context
+ */
+ public static Status parseStatus(Status_stmtContext ctx) {
+ Status result = null;
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree statusArg = ctx.getChild(i);
+ if (statusArg instanceof Status_argContext) {
+ String statusArgStr = stringFromNode(statusArg);
+ if ("current".equals(statusArgStr)) {
+ result = Status.CURRENT;
+ } else if ("deprecated".equals(statusArgStr)) {
+ result = Status.DEPRECATED;
+ } else if ("obsolete".equals(statusArgStr)) {
+ result = Status.OBSOLETE;
+ } else {
+ logger.warn("Invalid 'status' statement: " + statusArgStr);
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Parse given tree and returns units statement as string.
+ *
+ * @param ctx
+ * context to parse
+ * @return value of units statement as string or null if there is no units
+ * statement
+ */
+ public static String parseUnits(ParseTree ctx) {
+ String units = null;
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Units_stmtContext) {
+ units = stringFromNode(child);
+ break;
+ }
+ }
+ return units;
+ }
+
+ /**
+ * Create SchemaPath object from given path list with namespace, revision
+ * and prefix based on given values.
+ *
+ * @param actualPath
+ * current position in model
+ * @param namespace
+ * @param revision
+ * @param prefix
+ * @return SchemaPath object.
+ */
+ public static SchemaPath createActualSchemaPath(List<String> actualPath,
+ URI namespace, Date revision, String prefix) {
+ final List<QName> path = new ArrayList<QName>();
+ QName qname;
+ // start from index 1 - module name ommited
+ for (int i = 1; i < actualPath.size(); i++) {
+ qname = new QName(namespace, revision, prefix, actualPath.get(i));
+ path.add(qname);
+ }
+ return new SchemaPath(path, true);
+ }
+
+ /**
+ * Create SchemaPath from given string.
+ *
+ * @param augmentPath
+ * string representation of path
+ * @return SchemaPath object
+ */
+ public static SchemaPath parseAugmentPath(String augmentPath) {
+ boolean absolute = augmentPath.startsWith("/");
+ String[] splittedPath = augmentPath.split("/");
+ List<QName> path = new ArrayList<QName>();
+ QName name;
+ for (String pathElement : splittedPath) {
+ if (pathElement.length() > 0) {
+ String[] splittedElement = pathElement.split(":");
+ if (splittedElement.length == 1) {
+ name = new QName(null, null, null, splittedElement[0]);
+ } else {
+ name = new QName(null, null, splittedElement[0],
+ splittedElement[1]);
+ }
+ path.add(name);
+ }
+ }
+ return new SchemaPath(path, absolute);
+ }
+
+ /**
+ * Create java.util.List of QName objects from given key definition as
+ * string.
+ *
+ * @param keyDefinition
+ * key definition as string
+ * @param namespace
+ * current namespace
+ * @param revision
+ * current revision
+ * @param prefix
+ * 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) {
+ List<QName> key = new ArrayList<QName>();
+ String[] splittedKey = keyDefinition.split(" ");
+
+ QName qname = null;
+ for (String keyElement : splittedKey) {
+ if (keyElement.length() != 0) {
+ qname = new QName(namespace, revision, prefix, keyElement);
+ key.add(qname);
+ }
+ }
+ return key;
+ }
+
+ 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++) {
+ ParseTree enumSpecChild = ctx.getChild(j);
+ if (enumSpecChild instanceof Enum_specificationContext) {
+ 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;
+ }
+ }
+ }
+ }
+ }
+ return enumConstants;
+ }
+
+ private static EnumTypeDefinition.EnumPair createEnumPair(
+ Enum_stmtContext ctx, final int value, 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);
+ 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) {
+ description = stringFromNode(child);
+ } else if (child instanceof Reference_stmtContext) {
+ reference = stringFromNode(child);
+ } else if (child instanceof Status_stmtContext) {
+ status = parseStatus((Status_stmtContext) child);
+ }
+ }
+
+ EnumPairImpl result = new EnumPairImpl();
+ result.qname = qname;
+ result.path = createActualSchemaPath(enumPairPath, namespace, revision,
+ prefix);
+ result.description = description;
+ result.reference = reference;
+ result.status = status;
+ result.name = name;
+ result.value = value;
+ return result;
+ }
+
+ private static class EnumPairImpl implements EnumTypeDefinition.EnumPair {
+ private QName qname;
+ private SchemaPath path;
+ private String description;
+ private String reference;
+ private Status status;
+ private List<UnknownSchemaNode> extensionSchemaNodes = Collections
+ .emptyList();
+ private String name;
+ private Integer value;
+
+ @Override
+ public QName getQName() {
+ return qname;
+ }
+
+ @Override
+ public SchemaPath getPath() {
+ return path;
+ }
+
+ @Override
+ public String getDescription() {
+ return description;
+ }
+
+ @Override
+ public String getReference() {
+ return reference;
+ }
+
+ @Override
+ public Status getStatus() {
+ return status;
+ }
+
+ @Override
+ public List<UnknownSchemaNode> getUnknownSchemaNodes() {
+ return extensionSchemaNodes;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public Integer getValue() {
+ return value;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((qname == null) ? 0 : qname.hashCode());
+ result = prime * result + ((path == null) ? 0 : path.hashCode());
+ result = prime
+ * result
+ + ((extensionSchemaNodes == null) ? 0
+ : extensionSchemaNodes.hashCode());
+ result = prime * result + ((name == null) ? 0 : name.hashCode());
+ result = prime * result + ((value == null) ? 0 : value.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;
+ }
+ EnumPairImpl other = (EnumPairImpl) obj;
+ if (qname == null) {
+ if (other.qname != null) {
+ return false;
+ }
+ } else if (!qname.equals(other.qname)) {
+ return false;
+ }
+ if (path == null) {
+ if (other.path != null) {
+ return false;
+ }
+ } else if (!path.equals(other.path)) {
+ return false;
+ }
+ if (extensionSchemaNodes == null) {
+ if (other.extensionSchemaNodes != null) {
+ return false;
+ }
+ } else if (!extensionSchemaNodes.equals(other.extensionSchemaNodes)) {
+ return false;
+ }
+ if (name == null) {
+ if (other.name != null) {
+ return false;
+ }
+ } else if (!name.equals(other.name)) {
+ return false;
+ }
+ if (value == null) {
+ if (other.value != null) {
+ return false;
+ }
+ } else if (!value.equals(other.value)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return EnumTypeDefinition.EnumPair.class.getSimpleName() + "[name="
+ + name + ", value=" + value + "]";
+ }
+ };
+
+ private static List<RangeConstraint> getRangeConstraints(
+ Type_body_stmtsContext ctx) {
+ final List<RangeConstraint> rangeConstraints = new ArrayList<RangeConstraint>();
+ 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;
+ }
+ }
+ }
+ }
+ return rangeConstraints;
+ }
+
+ private static List<RangeConstraint> parseRangeConstraints(
+ Range_stmtContext ctx) {
+ List<RangeConstraint> rangeConstraints = new ArrayList<RangeConstraint>();
+ String description = null;
+ String reference = null;
+
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Description_stmtContext) {
+ description = stringFromNode(child);
+ } else if (child instanceof Reference_stmtContext) {
+ reference = stringFromNode(child);
+ }
+ }
+
+ String rangeStr = stringFromNode(ctx);
+ String trimmed = rangeStr.replace(" ", "");
+ String[] splittedRange = trimmed.split("\\|");
+ for (String rangeDef : splittedRange) {
+ String[] splittedRangeDef = rangeDef.split("\\.\\.");
+ Number min;
+ Number max;
+ if (splittedRangeDef.length == 1) {
+ min = max = parseRangeValue(splittedRangeDef[0]);
+ } else {
+ min = parseRangeValue(splittedRangeDef[0]);
+ max = parseRangeValue(splittedRangeDef[1]);
+ }
+ RangeConstraint range = BaseConstraints.rangeConstraint(min, max,
+ description, reference);
+ rangeConstraints.add(range);
+ }
+
+ return rangeConstraints;
+ }
+
+ private static List<LengthConstraint> getLengthConstraints(
+ Type_body_stmtsContext ctx) {
+ List<LengthConstraint> lengthConstraints = new ArrayList<LengthConstraint>();
+ 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));
+ }
+ }
+ }
+ }
+ return lengthConstraints;
+ }
+
+ private static List<LengthConstraint> parseLengthConstraints(
+ Length_stmtContext ctx) {
+ List<LengthConstraint> lengthConstraints = new ArrayList<LengthConstraint>();
+ String description = null;
+ String reference = null;
+
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Description_stmtContext) {
+ description = stringFromNode(child);
+ } else if (child instanceof Reference_stmtContext) {
+ reference = stringFromNode(child);
+ }
+ }
+
+ String lengthStr = stringFromNode(ctx);
+ String trimmed = lengthStr.replace(" ", "");
+ String[] splittedRange = trimmed.split("\\|");
+ for (String rangeDef : splittedRange) {
+ String[] splittedRangeDef = rangeDef.split("\\.\\.");
+ Number min;
+ Number max;
+ if (splittedRangeDef.length == 1) {
+ min = max = parseRangeValue(splittedRangeDef[0]);
+ } else {
+ min = parseRangeValue(splittedRangeDef[0]);
+ max = parseRangeValue(splittedRangeDef[1]);
+ }
+ LengthConstraint range = BaseConstraints.lengthConstraint(min, max,
+ description, reference);
+ lengthConstraints.add(range);
+ }
+
+ return lengthConstraints;
+ }
+
+ private static Number parseRangeValue(String value) {
+ Number result = null;
+ if ("min".equals(value) || "max".equals(value)) {
+ result = new UnknownBoundaryNumber(value);
+ } else {
+ try {
+ result = Long.valueOf(value);
+ } catch (NumberFormatException e) {
+ throw new YangParseException("Unable to parse range value '"
+ + value + "'.", e);
+ }
+ }
+ return result;
+ }
+
+ private static List<PatternConstraint> getPatternConstraint(
+ Type_body_stmtsContext ctx) {
+ List<PatternConstraint> patterns = new ArrayList<PatternConstraint>();
+
+ out: 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 Pattern_stmtContext) {
+ patterns.add(parsePatternConstraint((Pattern_stmtContext) lengthChild));
+ if (k == lengthChild.getChildCount() - 1) {
+ break out;
+ }
+ }
+ }
+ }
+ }
+ return patterns;
+ }
+
+ /**
+ * Internal helper method.
+ *
+ * @param ctx
+ * pattern context
+ * @return PatternConstraint object
+ */
+ private static PatternConstraint parsePatternConstraint(
+ Pattern_stmtContext ctx) {
+ String description = null;
+ String reference = null;
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Description_stmtContext) {
+ description = stringFromNode(child);
+ } else if (child instanceof Reference_stmtContext) {
+ reference = stringFromNode(child);
+ }
+ }
+ String pattern = patternStringFromNode(ctx);
+ return BaseConstraints.patternConstraint(pattern, description,
+ reference);
+ }
+
+ /**
+ * Parse given context and return pattern value.
+ *
+ * @param ctx
+ * context to parse
+ * @return pattern value as String
+ */
+ public static String patternStringFromNode(final Pattern_stmtContext ctx) {
+ StringBuilder result = new StringBuilder();
+ for (int i = 0; i < ctx.getChildCount(); ++i) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof StringContext) {
+ for (int j = 0; j < child.getChildCount(); j++) {
+ if (j % 2 == 0) {
+ String patternToken = child.getChild(j).getText();
+ result.append(patternToken.substring(1,
+ patternToken.length() - 1));
+ }
+ }
+ }
+ }
+ return result.toString();
+ }
+
+ private static Integer getFractionDigits(Type_body_stmtsContext ctx) {
+ Integer result = null;
+ for (int j = 0; j < ctx.getChildCount(); j++) {
+ ParseTree dec64specChild = ctx.getChild(j);
+ if (dec64specChild instanceof Decimal64_specificationContext) {
+ result = parseFractionDigits((Decimal64_specificationContext) dec64specChild);
+ }
+ }
+ return result;
+ }
+
+ private static Integer parseFractionDigits(
+ Decimal64_specificationContext ctx) {
+ Integer result = null;
+ for (int k = 0; k < ctx.getChildCount(); k++) {
+ ParseTree fdChild = ctx.getChild(k);
+ if (fdChild instanceof Fraction_digits_stmtContext) {
+ String value = stringFromNode(fdChild);
+ try {
+ result = Integer.valueOf(value);
+ } catch (NumberFormatException e) {
+ throw new YangParseException(
+ "Unable to parse fraction digits value '" + value
+ + "'.", e);
+ }
+ }
+ }
+ return result;
+ }
+
+ 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>();
+ for (int j = 0; j < ctx.getChildCount(); j++) {
+ ParseTree bitsSpecChild = ctx.getChild(j);
+ if (bitsSpecChild instanceof Bits_specificationContext) {
+ long highestPosition = -1;
+ for (int k = 0; k < bitsSpecChild.getChildCount(); k++) {
+ ParseTree bitChild = bitsSpecChild.getChild(k);
+ if (bitChild instanceof Bit_stmtContext) {
+ Bit bit = parseBit((Bit_stmtContext) bitChild,
+ highestPosition, actualPath, namespace,
+ revision, prefix);
+ if (bit.getPosition() > highestPosition) {
+ highestPosition = bit.getPosition();
+ }
+ bits.add(bit);
+ }
+ }
+ }
+ }
+ return bits;
+ }
+
+ private static BitsTypeDefinition.Bit parseBit(final Bit_stmtContext ctx,
+ long highestPosition, List<String> actualPath, final URI namespace,
+ final Date revision, final String prefix) {
+ String name = stringFromNode(ctx);
+ final QName qname = new QName(namespace, revision, prefix, name);
+ Long position = null;
+
+ String description = null;
+ String reference = null;
+ Status status = Status.CURRENT;
+
+ Stack<String> bitPath = new Stack<String>();
+ bitPath.addAll(actualPath);
+ bitPath.add(name);
+
+ SchemaPath schemaPath = createActualSchemaPath(bitPath, namespace,
+ revision, prefix);
+
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Position_stmtContext) {
+ String positionStr = stringFromNode(child);
+ position = Long.valueOf(positionStr);
+ } else if (child instanceof Description_stmtContext) {
+ description = stringFromNode(child);
+ } else if (child instanceof Reference_stmtContext) {
+ reference = stringFromNode(child);
+ } else if (child instanceof Status_stmtContext) {
+ status = parseStatus((Status_stmtContext) child);
+ }
+ }
+
+ if (position == null) {
+ position = highestPosition + 1;
+ }
+ if (position < 0 || position > 4294967295L) {
+ throw new YangParseException(
+ "Error on bit '"
+ + name
+ + "': 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 + "]";
+ }
+ };
+ }
+
+ /**
+ * Parse orderedby statement.
+ *
+ * @param childNode
+ * Ordered_by_stmtContext
+ * @return true, if orderedby contains value 'user' or false otherwise
+ */
+ public static boolean parseUserOrdered(Ordered_by_stmtContext childNode) {
+ boolean result = false;
+ for (int j = 0; j < childNode.getChildCount(); j++) {
+ ParseTree orderArg = childNode.getChild(j);
+ if (orderArg instanceof Ordered_by_argContext) {
+ String orderStr = stringFromNode(orderArg);
+ if ("system".equals(orderStr)) {
+ result = false;
+ } else if ("user".equals(orderStr)) {
+ result = true;
+ } else {
+ logger.warn("Invalid 'orderedby' statement.");
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Parse given config context and return true if it contains string 'true',
+ * false otherwise.
+ *
+ * @param ctx
+ * config context to parse.
+ * @return true if given context contains string 'true', false otherwise
+ */
+ public static boolean parseConfig(final Config_stmtContext ctx) {
+ boolean result = false;
+ if (ctx != null) {
+ for (int i = 0; i < ctx.getChildCount(); ++i) {
+ final ParseTree configContext = ctx.getChild(i);
+ if (configContext instanceof Config_argContext) {
+ final String value = stringFromNode(configContext);
+ if ("true".equals(value)) {
+ result = true;
+ break;
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Parse given type body and creates UnknownType definition.
+ *
+ * @param typedefQName
+ * qname of current type
+ * @param ctx
+ * type body
+ * @return UnknownType object with constraints from parsed type body
+ */
+ public static TypeDefinition<?> parseUnknownTypeBody(QName typedefQName,
+ Type_body_stmtsContext ctx) {
+ UnknownType.Builder unknownType = new UnknownType.Builder(typedefQName);
+
+ if (ctx != null) {
+ List<RangeConstraint> rangeStatements = getRangeConstraints(ctx);
+ List<LengthConstraint> lengthStatements = getLengthConstraints(ctx);
+ List<PatternConstraint> patternStatements = getPatternConstraint(ctx);
+ Integer fractionDigits = getFractionDigits(ctx);
+
+ unknownType.rangeStatements(rangeStatements);
+ unknownType.lengthStatements(lengthStatements);
+ unknownType.patterns(patternStatements);
+ unknownType.fractionDigits(fractionDigits);
+ }
+
+ return unknownType.build();
+ }
+
+ /**
+ * Create TypeDefinition object based on given type name and type body.
+ *
+ * @param typeName
+ * name of type
+ * @param typeBody
+ * type body
+ * @param actualPath
+ * current path in schema
+ * @param namespace
+ * current namespace
+ * @param revision
+ * current revision
+ * @param prefix
+ * 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) {
+ TypeDefinition<?> type = null;
+
+ List<RangeConstraint> rangeStatements = getRangeConstraints(typeBody);
+ Integer fractionDigits = getFractionDigits(typeBody);
+ List<LengthConstraint> lengthStatements = getLengthConstraints(typeBody);
+ List<PatternConstraint> patternStatements = getPatternConstraint(typeBody);
+ List<EnumTypeDefinition.EnumPair> enumConstants = getEnumConstants(
+ typeBody, actualPath, namespace, revision, prefix);
+
+ if ("decimal64".equals(typeName)) {
+ type = YangTypesConverter.javaTypeForBaseYangDecimal64Type(
+ rangeStatements, fractionDigits);
+ } else if (typeName.startsWith("int")) {
+ type = YangTypesConverter.javaTypeForBaseYangSignedIntegerType(
+ typeName, rangeStatements);
+ } else if (typeName.startsWith("uint")) {
+ type = YangTypesConverter.javaTypeForBaseYangUnsignedIntegerType(
+ typeName, rangeStatements);
+ } else if ("enumeration".equals(typeName)) {
+ type = new EnumerationType(enumConstants);
+ } else if ("string".equals(typeName)) {
+ type = new StringType(lengthStatements, patternStatements);
+ } else if ("bits".equals(typeName)) {
+ type = new BitsType(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);
+ } else if ("binary".equals(typeName)) {
+ List<Byte> bytes = Collections.emptyList();
+ type = new BinaryType(bytes, lengthStatements, null);
+ } else if ("instance-identifier".equals(typeName)) {
+ boolean requireInstance = isRequireInstance(typeBody);
+ type = new InstanceIdentifier(null, requireInstance);
+ }
+ return type;
+ }
+
+ private static boolean isRequireInstance(Type_body_stmtsContext ctx) {
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Require_instance_stmtContext) {
+ for (int j = 0; j < child.getChildCount(); j++) {
+ ParseTree reqArg = child.getChild(j);
+ if (reqArg instanceof Require_instance_argContext) {
+ return Boolean.valueOf(stringFromNode(reqArg));
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ private static String parseLeafrefPath(Type_body_stmtsContext ctx) {
+ for (int i = 0; i < ctx.getChildCount(); i++) {
+ ParseTree child = ctx.getChild(i);
+ if (child instanceof Leafref_specificationContext) {
+ for (int j = 0; j < child.getChildCount(); j++) {
+ ParseTree leafRefSpec = child.getChild(j);
+ if (leafRefSpec instanceof Path_stmtContext) {
+ return stringFromNode(leafRefSpec);
+ }
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Internal helper method for parsing Must_stmtContext.
+ *
+ * @param ctx
+ * Must_stmtContext
+ * @return an array of strings with following fields: [0] must text [1]
+ * description [2] reference
+ */
+ public static String[] parseMust(YangParser.Must_stmtContext ctx) {
+ String[] params = new String[3];
+
+ StringBuilder mustText = new StringBuilder();
+ String description = null;
+ String reference = 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));
+ }
+ }
+ } else if (child instanceof Description_stmtContext) {
+ description = stringFromNode(child);
+ } else if (child instanceof Reference_stmtContext) {
+ reference = stringFromNode(child);
+ }
+ }
+ params[0] = mustText.toString();
+ params[1] = description;
+ params[2] = reference;
+
+ return params;
+ }
+
+ /**
+ * Parse given tree and set constraints to given builder.
+ *
+ * @param ctx
+ * Context to search.
+ * @param constraintsBuilder
+ * ConstraintsBuilder to fill.
+ */
+ public static void parseConstraints(ParseTree ctx,
+ ConstraintsBuilder constraintsBuilder) {
+ 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);
+ } else if (childNode instanceof Min_elements_stmtContext) {
+ 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]);
+ } 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);
+ }
+ }
+ } else if (childNode instanceof When_stmtContext) {
+ constraintsBuilder.addWhenCondition(stringFromNode(childNode));
+ }
+ }
+ }
+
+ /**
+ * Parse given context and return yin value.
+ *
+ * @param ctx
+ * context to parse
+ * @return true if value is 'true', false otherwise
+ */
+ public static boolean parseYinValue(Argument_stmtContext ctx) {
+ boolean yinValue = false;
+ outer: for (int j = 0; j < ctx.getChildCount(); j++) {
+ ParseTree yin = ctx.getChild(j);
+ if (yin instanceof Yin_element_stmtContext) {
+ for (int k = 0; k < yin.getChildCount(); k++) {
+ ParseTree yinArg = yin.getChild(k);
+ if (yinArg instanceof Yin_element_argContext) {
+ String yinString = stringFromNode(yinArg);
+ if ("true".equals(yinString)) {
+ yinValue = true;
+ break outer;
+ }
+ }
+ }
+ }
+ }
+ return yinValue;
+ }
+
+}