2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/eplv10.html
8 package org.opendaylight.controller.yang.model.parser.util;
11 import java.util.ArrayList;
12 import java.util.Collections;
13 import java.util.Date;
14 import java.util.List;
15 import java.util.Stack;
17 import org.antlr.v4.runtime.tree.ParseTree;
18 import org.opendaylight.controller.antlrv4.code.gen.YangParser;
19 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Argument_stmtContext;
20 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Bit_stmtContext;
21 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Bits_specificationContext;
22 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Config_argContext;
23 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Config_stmtContext;
24 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Decimal64_specificationContext;
25 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Description_stmtContext;
26 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Enum_specificationContext;
27 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Enum_stmtContext;
28 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Fraction_digits_stmtContext;
29 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Leafref_specificationContext;
30 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Length_stmtContext;
31 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Mandatory_argContext;
32 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Mandatory_stmtContext;
33 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Max_elements_stmtContext;
34 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Min_elements_stmtContext;
35 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Must_stmtContext;
36 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Numerical_restrictionsContext;
37 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Ordered_by_argContext;
38 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Ordered_by_stmtContext;
39 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Path_stmtContext;
40 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Pattern_stmtContext;
41 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Position_stmtContext;
42 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Range_stmtContext;
43 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Reference_stmtContext;
44 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Require_instance_argContext;
45 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Require_instance_stmtContext;
46 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_argContext;
47 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_stmtContext;
48 import org.opendaylight.controller.antlrv4.code.gen.YangParser.StringContext;
49 import org.opendaylight.controller.antlrv4.code.gen.YangParser.String_restrictionsContext;
50 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Type_body_stmtsContext;
51 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Units_stmtContext;
52 import org.opendaylight.controller.antlrv4.code.gen.YangParser.When_stmtContext;
53 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yin_element_argContext;
54 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Yin_element_stmtContext;
55 import org.opendaylight.controller.yang.common.QName;
56 import org.opendaylight.controller.yang.model.api.RevisionAwareXPath;
57 import org.opendaylight.controller.yang.model.api.SchemaPath;
58 import org.opendaylight.controller.yang.model.api.Status;
59 import org.opendaylight.controller.yang.model.api.TypeDefinition;
60 import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
61 import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition;
62 import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition.Bit;
63 import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition;
64 import org.opendaylight.controller.yang.model.api.type.LengthConstraint;
65 import org.opendaylight.controller.yang.model.api.type.PatternConstraint;
66 import org.opendaylight.controller.yang.model.api.type.RangeConstraint;
67 import org.opendaylight.controller.yang.model.parser.builder.api.SchemaNodeBuilder;
68 import org.opendaylight.controller.yang.model.parser.builder.impl.ConstraintsBuilder;
69 import org.opendaylight.controller.yang.model.util.BaseConstraints;
70 import org.opendaylight.controller.yang.model.util.BinaryType;
71 import org.opendaylight.controller.yang.model.util.BitsType;
72 import org.opendaylight.controller.yang.model.util.EnumerationType;
73 import org.opendaylight.controller.yang.model.util.InstanceIdentifier;
74 import org.opendaylight.controller.yang.model.util.Leafref;
75 import org.opendaylight.controller.yang.model.util.RevisionAwareXPathImpl;
76 import org.opendaylight.controller.yang.model.util.StringType;
77 import org.opendaylight.controller.yang.model.util.UnknownType;
78 import org.opendaylight.controller.yang.model.util.YangTypesConverter;
79 import org.slf4j.Logger;
80 import org.slf4j.LoggerFactory;
82 public final class YangModelBuilderUtil {
84 private static final Logger logger = LoggerFactory
85 .getLogger(YangModelBuilderUtil.class);
88 * Parse given tree and get first string value.
92 * @return first string value from given tree
94 public static String stringFromNode(final ParseTree treeNode) {
95 final String result = "";
96 for (int i = 0; i < treeNode.getChildCount(); ++i) {
97 if (treeNode.getChild(i) instanceof StringContext) {
98 final StringContext context = (StringContext) treeNode
100 if (context != null) {
101 return context.getChild(0).getText().replace("\"", "");
109 * Parse 'description', 'reference' and 'status' statements and fill in
115 * builder to fill in with parsed statements
117 public static void parseSchemaNodeArgs(ParseTree ctx,
118 SchemaNodeBuilder builder) {
119 for (int i = 0; i < ctx.getChildCount(); i++) {
120 ParseTree child = ctx.getChild(i);
121 if (child instanceof Description_stmtContext) {
122 String desc = stringFromNode(child);
123 builder.setDescription(desc);
124 } else if (child instanceof Reference_stmtContext) {
125 String ref = stringFromNode(child);
126 builder.setReference(ref);
127 } else if (child instanceof Status_stmtContext) {
128 Status status = parseStatus((Status_stmtContext) child);
129 builder.setStatus(status);
135 * Parse given context and return its value;
139 * @return value parsed from context
141 public static Status parseStatus(Status_stmtContext ctx) {
142 Status result = null;
143 for (int i = 0; i < ctx.getChildCount(); i++) {
144 ParseTree statusArg = ctx.getChild(i);
145 if (statusArg instanceof Status_argContext) {
146 String statusArgStr = stringFromNode(statusArg);
147 if ("current".equals(statusArgStr)) {
148 result = Status.CURRENT;
149 } else if ("deprecated".equals(statusArgStr)) {
150 result = Status.DEPRECATED;
151 } else if ("obsolete".equals(statusArgStr)) {
152 result = Status.OBSOLETE;
154 logger.warn("Invalid 'status' statement: " + statusArgStr);
162 * Parse given tree and returns units statement as string.
166 * @return value of units statement as string or null if there is no units
169 public static String parseUnits(ParseTree ctx) {
171 for (int i = 0; i < ctx.getChildCount(); i++) {
172 ParseTree child = ctx.getChild(i);
173 if (child instanceof Units_stmtContext) {
174 units = stringFromNode(child);
182 * Create SchemaPath object from given path list with namespace, revision
183 * and prefix based on given values.
186 * current position in model
190 * @return SchemaPath object.
192 public static SchemaPath createActualSchemaPath(List<String> actualPath,
193 URI namespace, Date revision, String prefix) {
194 final List<QName> path = new ArrayList<QName>();
196 // start from index 1 - module name omitted
197 for (int i = 1; i < actualPath.size(); i++) {
198 qname = new QName(namespace, revision, prefix, actualPath.get(i));
201 return new SchemaPath(path, true);
205 * Create SchemaPath from given string.
208 * string representation of path
209 * @return SchemaPath object
211 public static SchemaPath parseAugmentPath(String augmentPath) {
212 boolean absolute = augmentPath.startsWith("/");
213 String[] splittedPath = augmentPath.split("/");
214 List<QName> path = new ArrayList<QName>();
216 for (String pathElement : splittedPath) {
217 if (pathElement.length() > 0) {
218 String[] splittedElement = pathElement.split(":");
219 if (splittedElement.length == 1) {
220 name = new QName(null, null, null, splittedElement[0]);
222 name = new QName(null, null, splittedElement[0],
228 return new SchemaPath(path, absolute);
232 * Create java.util.List of QName objects from given key definition as
235 * @param keyDefinition
236 * key definition as string
243 * @return YANG list key as java.util.List of QName objects
245 public static List<QName> createListKey(String keyDefinition,
246 URI namespace, Date revision, String prefix) {
247 List<QName> key = new ArrayList<QName>();
248 String[] splittedKey = keyDefinition.split(" ");
251 for (String keyElement : splittedKey) {
252 if (keyElement.length() != 0) {
253 qname = new QName(namespace, revision, prefix, keyElement);
260 private static List<EnumTypeDefinition.EnumPair> getEnumConstants(
261 Type_body_stmtsContext ctx, List<String> path, URI namespace,
262 Date revision, String prefix) {
263 List<EnumTypeDefinition.EnumPair> enumConstants = new ArrayList<EnumTypeDefinition.EnumPair>();
265 out: for (int j = 0; j < ctx.getChildCount(); j++) {
266 ParseTree enumSpecChild = ctx.getChild(j);
267 if (enumSpecChild instanceof Enum_specificationContext) {
268 for (int k = 0; k < enumSpecChild.getChildCount(); k++) {
269 ParseTree enumChild = enumSpecChild.getChild(k);
270 if (enumChild instanceof Enum_stmtContext) {
271 enumConstants.add(createEnumPair(
272 (Enum_stmtContext) enumChild, k, path,
273 namespace, revision, prefix));
274 if (k == enumSpecChild.getChildCount() - 1) {
281 return enumConstants;
284 private static EnumTypeDefinition.EnumPair createEnumPair(
285 Enum_stmtContext ctx, final int value, List<String> path,
286 final URI namespace, final Date revision, final String prefix) {
287 final String name = stringFromNode(ctx);
288 final QName qname = new QName(namespace, revision, prefix, name);
289 String description = null;
290 String reference = null;
291 Status status = null;
292 List<String> enumPairPath = new ArrayList<String>(path);
293 enumPairPath.add(name);
295 for (int i = 0; i < ctx.getChildCount(); i++) {
296 ParseTree child = ctx.getChild(i);
297 if (child instanceof Description_stmtContext) {
298 description = stringFromNode(child);
299 } else if (child instanceof Reference_stmtContext) {
300 reference = stringFromNode(child);
301 } else if (child instanceof Status_stmtContext) {
302 status = parseStatus((Status_stmtContext) child);
306 EnumPairImpl result = new EnumPairImpl();
307 result.qname = qname;
308 result.path = createActualSchemaPath(enumPairPath, namespace, revision,
310 result.description = description;
311 result.reference = reference;
312 result.status = status;
314 result.value = value;
318 private static class EnumPairImpl implements EnumTypeDefinition.EnumPair {
320 private SchemaPath path;
321 private String description;
322 private String reference;
323 private Status status;
324 private List<UnknownSchemaNode> extensionSchemaNodes = Collections
327 private Integer value;
330 public QName getQName() {
335 public SchemaPath getPath() {
340 public String getDescription() {
345 public String getReference() {
350 public Status getStatus() {
355 public List<UnknownSchemaNode> getUnknownSchemaNodes() {
356 return extensionSchemaNodes;
360 public String getName() {
365 public Integer getValue() {
370 public int hashCode() {
371 final int prime = 31;
373 result = prime * result + ((qname == null) ? 0 : qname.hashCode());
374 result = prime * result + ((path == null) ? 0 : path.hashCode());
377 + ((extensionSchemaNodes == null) ? 0
378 : extensionSchemaNodes.hashCode());
379 result = prime * result + ((name == null) ? 0 : name.hashCode());
380 result = prime * result + ((value == null) ? 0 : value.hashCode());
385 public boolean equals(Object obj) {
392 if (getClass() != obj.getClass()) {
395 EnumPairImpl other = (EnumPairImpl) obj;
397 if (other.qname != null) {
400 } else if (!qname.equals(other.qname)) {
404 if (other.path != null) {
407 } else if (!path.equals(other.path)) {
410 if (extensionSchemaNodes == null) {
411 if (other.extensionSchemaNodes != null) {
414 } else if (!extensionSchemaNodes.equals(other.extensionSchemaNodes)) {
418 if (other.name != null) {
421 } else if (!name.equals(other.name)) {
425 if (other.value != null) {
428 } else if (!value.equals(other.value)) {
435 public String toString() {
436 return EnumTypeDefinition.EnumPair.class.getSimpleName() + "[name="
437 + name + ", value=" + value + "]";
441 private static List<RangeConstraint> getRangeConstraints(
442 Type_body_stmtsContext ctx) {
443 final List<RangeConstraint> rangeConstraints = new ArrayList<RangeConstraint>();
444 for (int j = 0; j < ctx.getChildCount(); j++) {
445 ParseTree numRestrChild = ctx.getChild(j);
446 if (numRestrChild instanceof Numerical_restrictionsContext) {
447 for (int k = 0; k < numRestrChild.getChildCount(); k++) {
448 ParseTree rangeChild = numRestrChild.getChild(k);
449 if (rangeChild instanceof Range_stmtContext) {
451 .addAll(parseRangeConstraints((Range_stmtContext) rangeChild));
457 return rangeConstraints;
460 private static List<RangeConstraint> parseRangeConstraints(
461 Range_stmtContext ctx) {
462 List<RangeConstraint> rangeConstraints = new ArrayList<RangeConstraint>();
463 String description = null;
464 String reference = null;
466 for (int i = 0; i < ctx.getChildCount(); i++) {
467 ParseTree child = ctx.getChild(i);
468 if (child instanceof Description_stmtContext) {
469 description = stringFromNode(child);
470 } else if (child instanceof Reference_stmtContext) {
471 reference = stringFromNode(child);
475 String rangeStr = stringFromNode(ctx);
476 String trimmed = rangeStr.replace(" ", "");
477 String[] splittedRange = trimmed.split("\\|");
478 for (String rangeDef : splittedRange) {
479 String[] splittedRangeDef = rangeDef.split("\\.\\.");
482 if (splittedRangeDef.length == 1) {
483 min = max = parseRangeValue(splittedRangeDef[0]);
485 min = parseRangeValue(splittedRangeDef[0]);
486 max = parseRangeValue(splittedRangeDef[1]);
488 RangeConstraint range = BaseConstraints.rangeConstraint(min, max,
489 description, reference);
490 rangeConstraints.add(range);
493 return rangeConstraints;
496 private static List<LengthConstraint> getLengthConstraints(
497 Type_body_stmtsContext ctx) {
498 List<LengthConstraint> lengthConstraints = new ArrayList<LengthConstraint>();
499 for (int j = 0; j < ctx.getChildCount(); j++) {
500 ParseTree stringRestrChild = ctx.getChild(j);
501 if (stringRestrChild instanceof String_restrictionsContext) {
502 for (int k = 0; k < stringRestrChild.getChildCount(); k++) {
503 ParseTree lengthChild = stringRestrChild.getChild(k);
504 if (lengthChild instanceof Length_stmtContext) {
506 .addAll(parseLengthConstraints((Length_stmtContext) lengthChild));
511 return lengthConstraints;
514 private static List<LengthConstraint> parseLengthConstraints(
515 Length_stmtContext ctx) {
516 List<LengthConstraint> lengthConstraints = new ArrayList<LengthConstraint>();
517 String description = null;
518 String reference = null;
520 for (int i = 0; i < ctx.getChildCount(); i++) {
521 ParseTree child = ctx.getChild(i);
522 if (child instanceof Description_stmtContext) {
523 description = stringFromNode(child);
524 } else if (child instanceof Reference_stmtContext) {
525 reference = stringFromNode(child);
529 String lengthStr = stringFromNode(ctx);
530 String trimmed = lengthStr.replace(" ", "");
531 String[] splittedRange = trimmed.split("\\|");
532 for (String rangeDef : splittedRange) {
533 String[] splittedRangeDef = rangeDef.split("\\.\\.");
536 if (splittedRangeDef.length == 1) {
537 min = max = parseRangeValue(splittedRangeDef[0]);
539 min = parseRangeValue(splittedRangeDef[0]);
540 max = parseRangeValue(splittedRangeDef[1]);
542 LengthConstraint range = BaseConstraints.lengthConstraint(min, max,
543 description, reference);
544 lengthConstraints.add(range);
547 return lengthConstraints;
550 private static Number parseRangeValue(String value) {
551 Number result = null;
552 if ("min".equals(value) || "max".equals(value)) {
553 result = new UnknownBoundaryNumber(value);
556 result = Long.valueOf(value);
557 } catch (NumberFormatException e) {
558 throw new YangParseException("Unable to parse range value '"
565 private static List<PatternConstraint> getPatternConstraint(
566 Type_body_stmtsContext ctx) {
567 List<PatternConstraint> patterns = new ArrayList<PatternConstraint>();
569 out: for (int j = 0; j < ctx.getChildCount(); j++) {
570 ParseTree stringRestrChild = ctx.getChild(j);
571 if (stringRestrChild instanceof String_restrictionsContext) {
572 for (int k = 0; k < stringRestrChild.getChildCount(); k++) {
573 ParseTree lengthChild = stringRestrChild.getChild(k);
574 if (lengthChild instanceof Pattern_stmtContext) {
575 patterns.add(parsePatternConstraint((Pattern_stmtContext) lengthChild));
576 if (k == lengthChild.getChildCount() - 1) {
587 * Internal helper method.
591 * @return PatternConstraint object
593 private static PatternConstraint parsePatternConstraint(
594 Pattern_stmtContext ctx) {
595 String description = null;
596 String reference = null;
597 for (int i = 0; i < ctx.getChildCount(); i++) {
598 ParseTree child = ctx.getChild(i);
599 if (child instanceof Description_stmtContext) {
600 description = stringFromNode(child);
601 } else if (child instanceof Reference_stmtContext) {
602 reference = stringFromNode(child);
605 String pattern = patternStringFromNode(ctx);
606 return BaseConstraints.patternConstraint(pattern, description,
611 * Parse given context and return pattern value.
615 * @return pattern value as String
617 public static String patternStringFromNode(final Pattern_stmtContext ctx) {
618 StringBuilder result = new StringBuilder();
619 for (int i = 0; i < ctx.getChildCount(); ++i) {
620 ParseTree child = ctx.getChild(i);
621 if (child instanceof StringContext) {
622 for (int j = 0; j < child.getChildCount(); j++) {
624 String patternToken = child.getChild(j).getText();
625 result.append(patternToken.substring(1,
626 patternToken.length() - 1));
631 return result.toString();
634 private static Integer getFractionDigits(Type_body_stmtsContext ctx) {
635 Integer result = null;
636 for (int j = 0; j < ctx.getChildCount(); j++) {
637 ParseTree dec64specChild = ctx.getChild(j);
638 if (dec64specChild instanceof Decimal64_specificationContext) {
639 result = parseFractionDigits((Decimal64_specificationContext) dec64specChild);
645 private static Integer parseFractionDigits(
646 Decimal64_specificationContext ctx) {
647 Integer result = null;
648 for (int k = 0; k < ctx.getChildCount(); k++) {
649 ParseTree fdChild = ctx.getChild(k);
650 if (fdChild instanceof Fraction_digits_stmtContext) {
651 String value = stringFromNode(fdChild);
653 result = Integer.valueOf(value);
654 } catch (NumberFormatException e) {
655 throw new YangParseException(
656 "Unable to parse fraction digits value '" + value
664 private static List<BitsTypeDefinition.Bit> getBits(
665 Type_body_stmtsContext ctx, List<String> actualPath, URI namespace,
666 Date revision, String prefix) {
667 List<BitsTypeDefinition.Bit> bits = new ArrayList<BitsTypeDefinition.Bit>();
668 for (int j = 0; j < ctx.getChildCount(); j++) {
669 ParseTree bitsSpecChild = ctx.getChild(j);
670 if (bitsSpecChild instanceof Bits_specificationContext) {
671 long highestPosition = -1;
672 for (int k = 0; k < bitsSpecChild.getChildCount(); k++) {
673 ParseTree bitChild = bitsSpecChild.getChild(k);
674 if (bitChild instanceof Bit_stmtContext) {
675 Bit bit = parseBit((Bit_stmtContext) bitChild,
676 highestPosition, actualPath, namespace,
678 if (bit.getPosition() > highestPosition) {
679 highestPosition = bit.getPosition();
689 private static BitsTypeDefinition.Bit parseBit(final Bit_stmtContext ctx,
690 long highestPosition, List<String> actualPath, final URI namespace,
691 final Date revision, final String prefix) {
692 String name = stringFromNode(ctx);
693 final QName qname = new QName(namespace, revision, prefix, name);
694 Long position = null;
696 String description = null;
697 String reference = null;
698 Status status = Status.CURRENT;
700 Stack<String> bitPath = new Stack<String>();
701 bitPath.addAll(actualPath);
704 SchemaPath schemaPath = createActualSchemaPath(bitPath, namespace,
707 for (int i = 0; i < ctx.getChildCount(); i++) {
708 ParseTree child = ctx.getChild(i);
709 if (child instanceof Position_stmtContext) {
710 String positionStr = stringFromNode(child);
711 position = Long.valueOf(positionStr);
712 } else if (child instanceof Description_stmtContext) {
713 description = stringFromNode(child);
714 } else if (child instanceof Reference_stmtContext) {
715 reference = stringFromNode(child);
716 } else if (child instanceof Status_stmtContext) {
717 status = parseStatus((Status_stmtContext) child);
721 if (position == null) {
722 position = highestPosition + 1;
724 if (position < 0 || position > 4294967295L) {
725 throw new YangParseException(
728 + "': the position value MUST be in the range 0 to 4294967295");
731 final List<UnknownSchemaNode> extensionNodes = Collections.emptyList();
732 return createBit(qname, schemaPath, description, reference, status,
733 extensionNodes, position);
736 private static BitsTypeDefinition.Bit createBit(final QName qname,
737 final SchemaPath schemaPath, final String description,
738 final String reference, final Status status,
739 final List<UnknownSchemaNode> unknownNodes, final Long position) {
740 return new BitsTypeDefinition.Bit() {
743 public QName getQName() {
748 public SchemaPath getPath() {
753 public String getDescription() {
758 public String getReference() {
763 public Status getStatus() {
768 public List<UnknownSchemaNode> getUnknownSchemaNodes() {
773 public Long getPosition() {
778 public String getName() {
779 return qname.getLocalName();
783 public int hashCode() {
784 final int prime = 31;
786 result = prime * result
787 + ((qname == null) ? 0 : qname.hashCode());
788 result = prime * result
789 + ((schemaPath == null) ? 0 : schemaPath.hashCode());
790 result = prime * result
791 + ((position == null) ? 0 : position.hashCode());
794 + ((unknownNodes == null) ? 0 : unknownNodes.hashCode());
799 public boolean equals(Object obj) {
806 if (getClass() != obj.getClass()) {
809 Bit other = (Bit) obj;
811 if (other.getQName() != null) {
814 } else if (!qname.equals(other.getQName())) {
817 if (schemaPath == null) {
818 if (other.getPath() != null) {
821 } else if (!schemaPath.equals(other.getPath())) {
824 if (unknownNodes == null) {
825 if (other.getUnknownSchemaNodes() != null) {
828 } else if (!unknownNodes.equals(other.getUnknownSchemaNodes())) {
831 if (position == null) {
832 if (other.getPosition() != null) {
835 } else if (!position.equals(other.getPosition())) {
842 public String toString() {
843 return Bit.class.getSimpleName() + "[name="
844 + qname.getLocalName() + ", position=" + position + "]";
850 * Parse orderedby statement.
853 * Ordered_by_stmtContext
854 * @return true, if orderedby contains value 'user' or false otherwise
856 public static boolean parseUserOrdered(Ordered_by_stmtContext childNode) {
857 boolean result = false;
858 for (int j = 0; j < childNode.getChildCount(); j++) {
859 ParseTree orderArg = childNode.getChild(j);
860 if (orderArg instanceof Ordered_by_argContext) {
861 String orderStr = stringFromNode(orderArg);
862 if ("system".equals(orderStr)) {
864 } else if ("user".equals(orderStr)) {
867 logger.warn("Invalid 'orderedby' statement.");
875 * Parse given config context and return true if it contains string 'true',
879 * config context to parse.
880 * @return true if given context contains string 'true', false otherwise
882 public static boolean parseConfig(final Config_stmtContext ctx) {
883 boolean result = false;
885 for (int i = 0; i < ctx.getChildCount(); ++i) {
886 final ParseTree configContext = ctx.getChild(i);
887 if (configContext instanceof Config_argContext) {
888 final String value = stringFromNode(configContext);
889 if ("true".equals(value)) {
900 * Parse given type body and creates UnknownType definition.
902 * @param typedefQName
903 * qname of current type
906 * @return UnknownType object with constraints from parsed type body
908 public static TypeDefinition<?> parseUnknownTypeBody(QName typedefQName,
909 Type_body_stmtsContext ctx) {
910 UnknownType.Builder unknownType = new UnknownType.Builder(typedefQName);
913 List<RangeConstraint> rangeStatements = getRangeConstraints(ctx);
914 List<LengthConstraint> lengthStatements = getLengthConstraints(ctx);
915 List<PatternConstraint> patternStatements = getPatternConstraint(ctx);
916 Integer fractionDigits = getFractionDigits(ctx);
918 unknownType.rangeStatements(rangeStatements);
919 unknownType.lengthStatements(lengthStatements);
920 unknownType.patterns(patternStatements);
921 unknownType.fractionDigits(fractionDigits);
924 return unknownType.build();
928 * Create TypeDefinition object based on given type name and type body.
935 * current path in schema
942 * @return TypeDefinition object based on parsed values.
944 public static TypeDefinition<?> parseTypeBody(String typeName,
945 Type_body_stmtsContext typeBody, List<String> actualPath,
946 URI namespace, Date revision, String prefix) {
947 TypeDefinition<?> type = null;
949 List<RangeConstraint> rangeStatements = getRangeConstraints(typeBody);
950 Integer fractionDigits = getFractionDigits(typeBody);
951 List<LengthConstraint> lengthStatements = getLengthConstraints(typeBody);
952 List<PatternConstraint> patternStatements = getPatternConstraint(typeBody);
953 List<EnumTypeDefinition.EnumPair> enumConstants = getEnumConstants(
954 typeBody, actualPath, namespace, revision, prefix);
956 if ("decimal64".equals(typeName)) {
957 type = YangTypesConverter.javaTypeForBaseYangDecimal64Type(
958 rangeStatements, fractionDigits);
959 } else if (typeName.startsWith("int")) {
960 type = YangTypesConverter.javaTypeForBaseYangSignedIntegerType(
961 typeName, rangeStatements);
962 } else if (typeName.startsWith("uint")) {
963 type = YangTypesConverter.javaTypeForBaseYangUnsignedIntegerType(
964 typeName, rangeStatements);
965 } else if ("enumeration".equals(typeName)) {
966 type = new EnumerationType(actualPath, namespace, revision, enumConstants);
967 } else if ("string".equals(typeName)) {
968 type = new StringType(lengthStatements, patternStatements);
969 } else if ("bits".equals(typeName)) {
970 type = new BitsType(getBits(typeBody, actualPath, namespace,
972 } else if ("leafref".equals(typeName)) {
973 final String path = parseLeafrefPath(typeBody);
974 final boolean absolute = path.startsWith("/");
975 RevisionAwareXPath xpath = new RevisionAwareXPathImpl(path,
977 type = new Leafref(actualPath, namespace, revision, xpath);
978 } else if ("binary".equals(typeName)) {
979 List<Byte> bytes = Collections.emptyList();
980 type = new BinaryType(bytes, lengthStatements, null);
981 } else if ("instance-identifier".equals(typeName)) {
982 boolean requireInstance = isRequireInstance(typeBody);
983 type = new InstanceIdentifier(null, requireInstance);
988 private static boolean isRequireInstance(Type_body_stmtsContext ctx) {
989 for (int i = 0; i < ctx.getChildCount(); i++) {
990 ParseTree child = ctx.getChild(i);
991 if (child instanceof Require_instance_stmtContext) {
992 for (int j = 0; j < child.getChildCount(); j++) {
993 ParseTree reqArg = child.getChild(j);
994 if (reqArg instanceof Require_instance_argContext) {
995 return Boolean.valueOf(stringFromNode(reqArg));
1003 private static String parseLeafrefPath(Type_body_stmtsContext ctx) {
1004 for (int i = 0; i < ctx.getChildCount(); i++) {
1005 ParseTree child = ctx.getChild(i);
1006 if (child instanceof Leafref_specificationContext) {
1007 for (int j = 0; j < child.getChildCount(); j++) {
1008 ParseTree leafRefSpec = child.getChild(j);
1009 if (leafRefSpec instanceof Path_stmtContext) {
1010 return stringFromNode(leafRefSpec);
1019 * Internal helper method for parsing Must_stmtContext.
1023 * @return an array of strings with following fields: [0] must text [1]
1024 * description [2] reference
1026 public static String[] parseMust(YangParser.Must_stmtContext ctx) {
1027 String[] params = new String[3];
1029 StringBuilder mustText = new StringBuilder();
1030 String description = null;
1031 String reference = null;
1032 for (int i = 0; i < ctx.getChildCount(); ++i) {
1033 ParseTree child = ctx.getChild(i);
1034 if (child instanceof StringContext) {
1035 final StringContext context = (StringContext) child;
1036 for (int j = 0; j < context.getChildCount(); j++) {
1037 String mustPart = context.getChild(j).getText();
1039 mustText.append(mustPart.substring(0,
1040 mustPart.length() - 1));
1044 mustText.append(mustPart.substring(1));
1047 } else if (child instanceof Description_stmtContext) {
1048 description = stringFromNode(child);
1049 } else if (child instanceof Reference_stmtContext) {
1050 reference = stringFromNode(child);
1053 params[0] = mustText.toString();
1054 params[1] = description;
1055 params[2] = reference;
1061 * Parse given tree and set constraints to given builder.
1064 * Context to search.
1065 * @param constraintsBuilder
1066 * ConstraintsBuilder to fill.
1068 public static void parseConstraints(ParseTree ctx,
1069 ConstraintsBuilder constraintsBuilder) {
1070 for (int i = 0; i < ctx.getChildCount(); ++i) {
1071 final ParseTree childNode = ctx.getChild(i);
1072 if (childNode instanceof Max_elements_stmtContext) {
1073 Integer max = Integer.valueOf(stringFromNode(childNode));
1074 constraintsBuilder.setMinElements(max);
1075 } else if (childNode instanceof Min_elements_stmtContext) {
1076 Integer min = Integer.valueOf(stringFromNode(childNode));
1077 constraintsBuilder.setMinElements(min);
1078 } else if (childNode instanceof Must_stmtContext) {
1079 String[] mustParams = parseMust((Must_stmtContext) childNode);
1080 constraintsBuilder.addMustDefinition(mustParams[0],
1081 mustParams[1], mustParams[2]);
1082 } else if (childNode instanceof Mandatory_stmtContext) {
1083 for (int j = 0; j < childNode.getChildCount(); j++) {
1084 ParseTree mandatoryTree = ctx.getChild(j);
1085 if (mandatoryTree instanceof Mandatory_argContext) {
1086 Boolean mandatory = Boolean
1087 .valueOf(stringFromNode(mandatoryTree));
1088 constraintsBuilder.setMandatory(mandatory);
1091 } else if (childNode instanceof When_stmtContext) {
1092 constraintsBuilder.addWhenCondition(stringFromNode(childNode));
1098 * Parse given context and return yin value.
1102 * @return true if value is 'true', false otherwise
1104 public static boolean parseYinValue(Argument_stmtContext ctx) {
1105 boolean yinValue = false;
1106 outer: for (int j = 0; j < ctx.getChildCount(); j++) {
1107 ParseTree yin = ctx.getChild(j);
1108 if (yin instanceof Yin_element_stmtContext) {
1109 for (int k = 0; k < yin.getChildCount(); k++) {
1110 ParseTree yinArg = yin.getChild(k);
1111 if (yinArg instanceof Yin_element_argContext) {
1112 String yinString = stringFromNode(yinArg);
1113 if ("true".equals(yinString)) {