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.Bit_stmtContext;
20 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Bits_specificationContext;
21 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Config_argContext;
22 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Config_stmtContext;
23 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Decimal64_specificationContext;
24 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Description_stmtContext;
25 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Enum_specificationContext;
26 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Enum_stmtContext;
27 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Fraction_digits_stmtContext;
28 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Leafref_specificationContext;
29 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Length_stmtContext;
30 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Mandatory_argContext;
31 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Mandatory_stmtContext;
32 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Max_elements_stmtContext;
33 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Min_elements_stmtContext;
34 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Must_stmtContext;
35 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Numerical_restrictionsContext;
36 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Ordered_by_argContext;
37 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Ordered_by_stmtContext;
38 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Path_stmtContext;
39 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Pattern_stmtContext;
40 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Position_stmtContext;
41 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Range_stmtContext;
42 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Reference_stmtContext;
43 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Require_instance_argContext;
44 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Require_instance_stmtContext;
45 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_argContext;
46 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Status_stmtContext;
47 import org.opendaylight.controller.antlrv4.code.gen.YangParser.StringContext;
48 import org.opendaylight.controller.antlrv4.code.gen.YangParser.String_restrictionsContext;
49 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Type_body_stmtsContext;
50 import org.opendaylight.controller.antlrv4.code.gen.YangParser.Units_stmtContext;
51 import org.opendaylight.controller.antlrv4.code.gen.YangParser.When_stmtContext;
52 import org.opendaylight.controller.model.api.type.BitsTypeDefinition;
53 import org.opendaylight.controller.model.api.type.BitsTypeDefinition.Bit;
54 import org.opendaylight.controller.model.api.type.EnumTypeDefinition;
55 import org.opendaylight.controller.model.api.type.LengthConstraint;
56 import org.opendaylight.controller.model.api.type.PatternConstraint;
57 import org.opendaylight.controller.model.api.type.RangeConstraint;
58 import org.opendaylight.controller.model.util.BaseConstraints;
59 import org.opendaylight.controller.model.util.BinaryType;
60 import org.opendaylight.controller.model.util.BitsType;
61 import org.opendaylight.controller.model.util.EnumerationType;
62 import org.opendaylight.controller.model.util.InstanceIdentifier;
63 import org.opendaylight.controller.model.util.Leafref;
64 import org.opendaylight.controller.model.util.RevisionAwareXPathImpl;
65 import org.opendaylight.controller.model.util.StringType;
66 import org.opendaylight.controller.model.util.UnknownType;
67 import org.opendaylight.controller.model.util.YangTypesConverter;
68 import org.opendaylight.controller.yang.common.QName;
69 import org.opendaylight.controller.yang.model.api.RevisionAwareXPath;
70 import org.opendaylight.controller.yang.model.api.SchemaPath;
71 import org.opendaylight.controller.yang.model.api.Status;
72 import org.opendaylight.controller.yang.model.api.TypeDefinition;
73 import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
74 import org.opendaylight.controller.yang.model.parser.builder.api.SchemaNodeBuilder;
75 import org.opendaylight.controller.yang.model.parser.builder.impl.ConstraintsBuilder;
76 import org.slf4j.Logger;
77 import org.slf4j.LoggerFactory;
79 public class YangModelBuilderUtil {
81 private static final Logger logger = LoggerFactory
82 .getLogger(YangModelBuilderUtil.class);
85 * Parse given tree and get first string value.
89 * @return first string value from given tree
91 public static String stringFromNode(final ParseTree treeNode) {
92 final String result = "";
93 for (int i = 0; i < treeNode.getChildCount(); ++i) {
94 if (treeNode.getChild(i) instanceof StringContext) {
95 final StringContext context = (StringContext) treeNode
97 if (context != null) {
98 return context.getChild(0).getText().replace("\"", "");
106 * Parse 'description', 'reference' and 'status' statements and fill in
112 * builder to fill in with parsed statements
114 public static void parseSchemaNodeArgs(ParseTree ctx,
115 SchemaNodeBuilder builder) {
116 for (int i = 0; i < ctx.getChildCount(); i++) {
117 ParseTree child = ctx.getChild(i);
118 if (child instanceof Description_stmtContext) {
119 String desc = stringFromNode(child);
120 builder.setDescription(desc);
121 } else if (child instanceof Reference_stmtContext) {
122 String ref = stringFromNode(child);
123 builder.setReference(ref);
124 } else if (child instanceof Status_stmtContext) {
125 Status status = parseStatus((Status_stmtContext) child);
126 builder.setStatus(status);
132 * Parse given context and return its value;
136 * @return value parsed from context
138 public static Status parseStatus(Status_stmtContext ctx) {
139 for (int i = 0; i < ctx.getChildCount(); i++) {
140 ParseTree statusArg = ctx.getChild(i);
141 if (statusArg instanceof Status_argContext) {
142 String statusArgStr = stringFromNode(statusArg);
143 if (statusArgStr.equals("current")) {
144 return Status.CURRENT;
145 } else if (statusArgStr.equals("deprecated")) {
146 return Status.DEPRECATED;
147 } else if (statusArgStr.equals("obsolete")) {
148 return Status.OBSOLETE;
150 logger.warn("Invalid 'status' statement: " + statusArgStr);
158 * Parse given tree and returns units statement as string.
162 * @return value of units statement as string or null if there is no units
165 public static String parseUnits(ParseTree ctx) {
167 for (int i = 0; i < ctx.getChildCount(); i++) {
168 ParseTree child = ctx.getChild(i);
169 if (child instanceof Units_stmtContext) {
170 units = stringFromNode(child);
178 * Create SchemaPath object from given path list with namespace, revision
179 * and prefix based on given values.
185 * @return SchemaPath object.
187 public static SchemaPath createActualSchemaPath(List<String> actualPath,
188 URI namespace, Date revision, String prefix) {
189 final List<QName> path = new ArrayList<QName>();
191 for (String pathElement : actualPath) {
192 qname = new QName(namespace, revision, prefix, pathElement);
195 return new SchemaPath(path, true);
199 * Create SchemaPath from given string.
202 * string representation of path
203 * @return SchemaPath object
205 public static SchemaPath parseAugmentPath(String augmentPath) {
206 boolean absolute = augmentPath.startsWith("/");
207 String[] splittedPath = augmentPath.split("/");
208 List<QName> path = new ArrayList<QName>();
210 for (String pathElement : splittedPath) {
211 if (pathElement.length() > 0) {
212 String[] splittedElement = pathElement.split(":");
213 if (splittedElement.length == 1) {
214 name = new QName(null, null, null, splittedElement[0]);
216 name = new QName(null, null, splittedElement[0],
222 return new SchemaPath(path, absolute);
226 * Create java.util.List of QName objects from given key definition as
229 * @param keyDefinition
230 * key definition as string
237 * @return YANG list key as java.util.List of QName objects
239 public static List<QName> createListKey(String keyDefinition,
240 URI namespace, Date revision, String prefix) {
241 List<QName> key = new ArrayList<QName>();
242 String[] splittedKey = keyDefinition.split(" ");
245 for (String keyElement : splittedKey) {
246 if (keyElement.length() != 0) {
247 qname = new QName(namespace, revision, prefix, keyElement);
254 private static List<EnumTypeDefinition.EnumPair> getEnumConstants(
255 Type_body_stmtsContext ctx, List<String> path, URI namespace,
256 Date revision, String prefix) {
257 List<EnumTypeDefinition.EnumPair> enumConstants = new ArrayList<EnumTypeDefinition.EnumPair>();
259 out: for (int j = 0; j < ctx.getChildCount(); j++) {
260 ParseTree enumSpecChild = ctx.getChild(j);
261 if (enumSpecChild instanceof Enum_specificationContext) {
262 for (int k = 0; k < enumSpecChild.getChildCount(); k++) {
263 ParseTree enumChild = enumSpecChild.getChild(k);
264 if (enumChild instanceof Enum_stmtContext) {
265 enumConstants.add(createEnumPair(
266 (Enum_stmtContext) enumChild, k, path,
267 namespace, revision, prefix));
268 if (k == enumSpecChild.getChildCount() - 1) {
275 return enumConstants;
278 private static EnumTypeDefinition.EnumPair createEnumPair(
279 Enum_stmtContext ctx, final int value, List<String> path,
280 final URI namespace, final Date revision, final String prefix) {
281 final String name = stringFromNode(ctx);
282 final QName qname = new QName(namespace, revision, prefix, name);
283 String description = null;
284 String reference = null;
285 Status status = null;
286 List<String> enumPairPath = new ArrayList<String>(path);
287 enumPairPath.add(name);
289 for (int i = 0; i < ctx.getChildCount(); i++) {
290 ParseTree child = ctx.getChild(i);
291 if (child instanceof Description_stmtContext) {
292 description = stringFromNode(child);
293 } else if (child instanceof Reference_stmtContext) {
294 reference = stringFromNode(child);
295 } else if (child instanceof Status_stmtContext) {
296 status = parseStatus((Status_stmtContext) child);
300 EnumPairImpl result = new EnumPairImpl();
301 result.qname = qname;
302 result.path = createActualSchemaPath(enumPairPath, namespace, revision,
304 result.description = description;
305 result.reference = reference;
306 result.status = status;
307 // TODO: extensionSchemaNodes
309 result.value = value;
313 private static class EnumPairImpl implements EnumTypeDefinition.EnumPair {
316 private SchemaPath path;
317 private String description;
318 private String reference;
319 private Status status;
320 private List<UnknownSchemaNode> extensionSchemaNodes = Collections
323 private Integer value;
326 public QName getQName() {
331 public SchemaPath getPath() {
336 public String getDescription() {
341 public String getReference() {
346 public Status getStatus() {
351 public List<UnknownSchemaNode> getUnknownSchemaNodes() {
352 return extensionSchemaNodes;
356 public String getName() {
361 public Integer getValue() {
366 public int hashCode() {
367 final int prime = 31;
369 result = prime * result + ((qname == null) ? 0 : qname.hashCode());
370 result = prime * result + ((path == null) ? 0 : path.hashCode());
371 result = prime * result
372 + ((description == null) ? 0 : description.hashCode());
373 result = prime * result
374 + ((reference == null) ? 0 : reference.hashCode());
375 result = prime * result
376 + ((status == null) ? 0 : status.hashCode());
379 + ((extensionSchemaNodes == null) ? 0
380 : extensionSchemaNodes.hashCode());
381 result = prime * result + ((name == null) ? 0 : name.hashCode());
382 result = prime * result + ((value == null) ? 0 : value.hashCode());
387 public boolean equals(Object obj) {
394 if (getClass() != obj.getClass()) {
397 EnumPairImpl other = (EnumPairImpl) obj;
399 if (other.qname != null) {
402 } else if (!qname.equals(other.qname)) {
406 if (other.path != null) {
409 } else if (!path.equals(other.path)) {
412 if (description == null) {
413 if (other.description != null) {
416 } else if (!description.equals(other.description)) {
419 if (reference == null) {
420 if (other.reference != null) {
423 } else if (!reference.equals(other.reference)) {
426 if (status == null) {
427 if (other.status != null) {
430 } else if (!status.equals(other.status)) {
433 if (extensionSchemaNodes == null) {
434 if (other.extensionSchemaNodes != null) {
437 } else if (!extensionSchemaNodes.equals(other.extensionSchemaNodes)) {
441 if (other.name != null) {
444 } else if (!name.equals(other.name)) {
448 if (other.value != null) {
451 } else if (!value.equals(other.value)) {
458 public String toString() {
459 return EnumTypeDefinition.EnumPair.class.getSimpleName() + "[name="
460 + name + ", value=" + value + "]";
464 private static List<RangeConstraint> getRangeConstraints(
465 Type_body_stmtsContext ctx) {
466 final List<RangeConstraint> rangeConstraints = new ArrayList<RangeConstraint>();
467 for (int j = 0; j < ctx.getChildCount(); j++) {
468 ParseTree numRestrChild = ctx.getChild(j);
469 if (numRestrChild instanceof Numerical_restrictionsContext) {
470 for (int k = 0; k < numRestrChild.getChildCount(); k++) {
471 ParseTree rangeChild = numRestrChild.getChild(k);
472 if (rangeChild instanceof Range_stmtContext) {
474 .addAll(parseRangeConstraints((Range_stmtContext) rangeChild));
480 return rangeConstraints;
483 private static List<RangeConstraint> parseRangeConstraints(
484 Range_stmtContext ctx) {
485 List<RangeConstraint> rangeConstraints = new ArrayList<RangeConstraint>();
486 String description = null;
487 String reference = null;
489 for (int i = 0; i < ctx.getChildCount(); i++) {
490 ParseTree child = ctx.getChild(i);
491 if (child instanceof Description_stmtContext) {
492 description = stringFromNode(child);
493 } else if (child instanceof Reference_stmtContext) {
494 reference = stringFromNode(child);
498 String rangeStr = stringFromNode(ctx);
499 String trimmed = rangeStr.replace(" ", "");
500 String[] splittedRange = trimmed.split("\\|");
501 for (String rangeDef : splittedRange) {
502 String[] splittedRangeDef = rangeDef.split("\\.\\.");
505 if (splittedRangeDef.length == 1) {
506 min = max = parseRangeValue(splittedRangeDef[0]);
508 min = parseRangeValue(splittedRangeDef[0]);
509 max = parseRangeValue(splittedRangeDef[1]);
511 RangeConstraint range = BaseConstraints.rangeConstraint(min, max,
512 description, reference);
513 rangeConstraints.add(range);
516 return rangeConstraints;
519 private static List<LengthConstraint> getLengthConstraints(
520 Type_body_stmtsContext ctx) {
521 List<LengthConstraint> lengthConstraints = new ArrayList<LengthConstraint>();
522 for (int j = 0; j < ctx.getChildCount(); j++) {
523 ParseTree stringRestrChild = ctx.getChild(j);
524 if (stringRestrChild instanceof String_restrictionsContext) {
525 for (int k = 0; k < stringRestrChild.getChildCount(); k++) {
526 ParseTree lengthChild = stringRestrChild.getChild(k);
527 if (lengthChild instanceof Length_stmtContext) {
529 .addAll(parseLengthConstraints((Length_stmtContext) lengthChild));
534 return lengthConstraints;
537 private static List<LengthConstraint> parseLengthConstraints(
538 Length_stmtContext ctx) {
539 List<LengthConstraint> lengthConstraints = new ArrayList<LengthConstraint>();
540 String description = null;
541 String reference = null;
543 for (int i = 0; i < ctx.getChildCount(); i++) {
544 ParseTree child = ctx.getChild(i);
545 if (child instanceof Description_stmtContext) {
546 description = stringFromNode(child);
547 } else if (child instanceof Reference_stmtContext) {
548 reference = stringFromNode(child);
552 String lengthStr = stringFromNode(ctx);
553 String trimmed = lengthStr.replace(" ", "");
554 String[] splittedRange = trimmed.split("\\|");
555 for (String rangeDef : splittedRange) {
556 String[] splittedRangeDef = rangeDef.split("\\.\\.");
559 if (splittedRangeDef.length == 1) {
560 min = max = parseRangeValue(splittedRangeDef[0]);
562 min = parseRangeValue(splittedRangeDef[0]);
563 max = parseRangeValue(splittedRangeDef[1]);
565 LengthConstraint range = BaseConstraints.lengthConstraint(min, max,
566 description, reference);
567 lengthConstraints.add(range);
570 return lengthConstraints;
573 private static Long parseRangeValue(String value) {
575 if (value.equals("min")) {
576 result = Long.MIN_VALUE;
577 } else if (value.equals("max")) {
578 result = Long.MAX_VALUE;
580 result = Long.valueOf(value);
585 private static List<PatternConstraint> getPatternConstraint(
586 Type_body_stmtsContext ctx) {
587 List<PatternConstraint> patterns = new ArrayList<PatternConstraint>();
589 out: for (int j = 0; j < ctx.getChildCount(); j++) {
590 ParseTree stringRestrChild = ctx.getChild(j);
591 if (stringRestrChild instanceof String_restrictionsContext) {
592 for (int k = 0; k < stringRestrChild.getChildCount(); k++) {
593 ParseTree lengthChild = stringRestrChild.getChild(k);
594 if (lengthChild instanceof Pattern_stmtContext) {
595 patterns.add(parsePatternConstraint((Pattern_stmtContext) lengthChild));
596 if (k == lengthChild.getChildCount() - 1) {
607 * Internal helper method.
611 * @return PatternConstraint object
613 private static PatternConstraint parsePatternConstraint(
614 Pattern_stmtContext ctx) {
615 String description = null;
616 String reference = null;
617 for (int i = 0; i < ctx.getChildCount(); i++) {
618 ParseTree child = ctx.getChild(i);
619 if (child instanceof Description_stmtContext) {
620 description = stringFromNode(child);
621 } else if (child instanceof Reference_stmtContext) {
622 reference = stringFromNode(child);
625 String pattern = stringFromNode(ctx);
626 return BaseConstraints.patternConstraint(pattern, description,
630 private static Integer getFractionDigits(Type_body_stmtsContext ctx) {
631 for (int j = 0; j < ctx.getChildCount(); j++) {
632 ParseTree dec64specChild = ctx.getChild(j);
633 if (dec64specChild instanceof Decimal64_specificationContext) {
634 return parseFractionDigits((Decimal64_specificationContext) dec64specChild);
640 private static Integer parseFractionDigits(
641 Decimal64_specificationContext ctx) {
642 for (int k = 0; k < ctx.getChildCount(); k++) {
643 ParseTree fdChild = ctx.getChild(k);
644 if (fdChild instanceof Fraction_digits_stmtContext) {
645 return Integer.valueOf(stringFromNode(fdChild));
651 private static List<BitsTypeDefinition.Bit> getBits(
652 Type_body_stmtsContext ctx, List<String> actualPath, URI namespace,
653 Date revision, String prefix) {
654 List<BitsTypeDefinition.Bit> bits = new ArrayList<BitsTypeDefinition.Bit>();
655 for (int j = 0; j < ctx.getChildCount(); j++) {
656 ParseTree bitsSpecChild = ctx.getChild(j);
657 if (bitsSpecChild instanceof Bits_specificationContext) {
658 for (int k = 0; k < bitsSpecChild.getChildCount(); k++) {
659 ParseTree bitChild = bitsSpecChild.getChild(k);
660 if (bitChild instanceof Bit_stmtContext) {
661 bits.add(parseBit((Bit_stmtContext) bitChild,
662 actualPath, namespace, revision, prefix));
670 private static boolean isRequireInstance(Type_body_stmtsContext ctx) {
671 for (int i = 0; i < ctx.getChildCount(); i++) {
672 ParseTree child = ctx.getChild(i);
673 if (child instanceof Require_instance_stmtContext) {
674 for (int j = 0; j < child.getChildCount(); j++) {
675 ParseTree reqArg = child.getChild(j);
676 if (reqArg instanceof Require_instance_argContext) {
677 return Boolean.valueOf(stringFromNode(reqArg));
685 private static BitsTypeDefinition.Bit parseBit(final Bit_stmtContext ctx,
686 List<String> actualPath, final URI namespace, final Date revision,
687 final String prefix) {
688 String name = stringFromNode(ctx);
689 final QName qname = new QName(namespace, revision, prefix, name);
690 Long position = null;
692 String description = null;
693 String reference = null;
694 Status status = Status.CURRENT;
696 Stack<String> bitPath = new Stack<String>();
697 bitPath.addAll(actualPath);
700 SchemaPath schemaPath = createActualSchemaPath(bitPath, namespace,
703 for (int i = 0; i < ctx.getChildCount(); i++) {
704 ParseTree child = ctx.getChild(i);
705 if (child instanceof Position_stmtContext) {
706 String positionStr = stringFromNode(child);
707 position = Long.valueOf(positionStr);
708 if (position < 0 || position > 4294967295L) {
709 throw new IllegalArgumentException(
710 "position value MUST be in the range 0 to 4294967295, but was: "
713 } else if (child instanceof Description_stmtContext) {
714 description = stringFromNode(child);
715 } else if (child instanceof Reference_stmtContext) {
716 reference = stringFromNode(child);
717 } else if (child instanceof Status_stmtContext) {
718 status = parseStatus((Status_stmtContext) child);
722 // TODO: extensionDefinitions
723 return createBit(qname, schemaPath, description, reference, status,
727 private static BitsTypeDefinition.Bit createBit(final QName qname,
728 final SchemaPath schemaPath, final String description,
729 final String reference, final Status status,
730 final List<UnknownSchemaNode> extensionDefinitions,
731 final Long position) {
732 return new BitsTypeDefinition.Bit() {
735 public QName getQName() {
740 public SchemaPath getPath() {
745 public String getDescription() {
750 public String getReference() {
755 public Status getStatus() {
760 public List<UnknownSchemaNode> getUnknownSchemaNodes() {
761 return extensionDefinitions;
765 public Long getPosition() {
770 public String getName() {
771 return qname.getLocalName();
775 public int hashCode() {
776 final int prime = 31;
778 result = prime * result
779 + ((qname == null) ? 0 : qname.hashCode());
780 result = prime * result
781 + ((schemaPath == null) ? 0 : schemaPath.hashCode());
782 result = prime * result
783 + ((description == null) ? 0 : description.hashCode());
784 result = prime * result
785 + ((reference == null) ? 0 : reference.hashCode());
786 result = prime * result
787 + ((status == null) ? 0 : status.hashCode());
788 result = prime * result
789 + ((position == null) ? 0 : position.hashCode());
792 + ((extensionDefinitions == null) ? 0
793 : extensionDefinitions.hashCode());
798 public boolean equals(Object obj) {
805 if (getClass() != obj.getClass()) {
808 Bit other = (Bit) obj;
810 if (other.getQName() != null) {
813 } else if (!qname.equals(other.getQName())) {
816 if (schemaPath == null) {
817 if (other.getPath() != null) {
820 } else if (!schemaPath.equals(other.getPath())) {
823 if (description == null) {
824 if (other.getDescription() != null) {
827 } else if (!description.equals(other.getDescription())) {
830 if (reference == null) {
831 if (other.getReference() != null) {
834 } else if (!reference.equals(other.getReference())) {
837 if (status == null) {
838 if (other.getStatus() != null) {
841 } else if (!status.equals(other.getStatus())) {
844 if (extensionDefinitions == null) {
845 if (other.getUnknownSchemaNodes() != null) {
848 } else if (!extensionDefinitions.equals(other
849 .getUnknownSchemaNodes())) {
852 if (position == null) {
853 if (other.getPosition() != null) {
856 } else if (!position.equals(other.getPosition())) {
863 public String toString() {
864 return Bit.class.getSimpleName() + "[name="
865 + qname.getLocalName() + ", position=" + position + "]";
871 * Parse orderedby statement.
874 * Ordered_by_stmtContext
875 * @return true, if orderedby contains value 'user' or false otherwise
877 public static boolean parseUserOrdered(Ordered_by_stmtContext childNode) {
878 boolean result = false;
879 for (int j = 0; j < childNode.getChildCount(); j++) {
880 ParseTree orderArg = childNode.getChild(j);
881 if (orderArg instanceof Ordered_by_argContext) {
882 String orderStr = stringFromNode(orderArg);
883 if (orderStr.equals("system")) {
885 } else if (orderStr.equals("user")) {
888 logger.warn("Invalid 'orderedby' statement.");
896 * Parse given config context and return true if it contains string 'true',
900 * config context to parse.
901 * @return true if given context contains string 'true', false otherwise
903 public static boolean parseConfig(final Config_stmtContext ctx) {
905 for (int i = 0; i < ctx.getChildCount(); ++i) {
906 final ParseTree configContext = ctx.getChild(i);
907 if (configContext instanceof Config_argContext) {
908 final String value = stringFromNode(configContext);
909 if (value.equals("true")) {
919 * Parse given type body and creates UnknownType definition.
921 * @param typedefQName
922 * qname of current type
925 * @return UnknownType object with constraints from parsed type body
927 public static TypeDefinition<?> parseUnknownTypeBody(QName typedefQName,
928 Type_body_stmtsContext ctx) {
929 UnknownType.Builder ut = new UnknownType.Builder(typedefQName);
932 List<RangeConstraint> rangeStatements = getRangeConstraints(ctx);
933 List<LengthConstraint> lengthStatements = getLengthConstraints(ctx);
934 List<PatternConstraint> patternStatements = getPatternConstraint(ctx);
935 Integer fractionDigits = getFractionDigits(ctx);
937 ut.rangeStatements(rangeStatements);
938 ut.lengthStatements(lengthStatements);
939 ut.patterns(patternStatements);
940 ut.fractionDigits(fractionDigits);
947 * Create TypeDefinition object based on given type name and type body.
954 * current path in schema
961 * @return TypeDefinition object based on parsed values.
963 public static TypeDefinition<?> parseTypeBody(String typeName,
964 Type_body_stmtsContext typeBody, List<String> actualPath,
965 URI namespace, Date revision, String prefix) {
966 TypeDefinition<?> type = null;
968 List<RangeConstraint> rangeStatements = getRangeConstraints(typeBody);
969 Integer fractionDigits = getFractionDigits(typeBody);
970 List<LengthConstraint> lengthStatements = getLengthConstraints(typeBody);
971 List<PatternConstraint> patternStatements = getPatternConstraint(typeBody);
972 List<EnumTypeDefinition.EnumPair> enumConstants = getEnumConstants(typeBody, actualPath, namespace, revision, prefix);
974 if (typeName.equals("decimal64")) {
975 type = YangTypesConverter.javaTypeForBaseYangDecimal64Type(
976 rangeStatements, fractionDigits);
977 } else if (typeName.startsWith("int") || typeName.startsWith("uint")) {
978 type = YangTypesConverter.javaTypeForBaseYangSignedIntegerType(typeName,
980 } else if(typeName.startsWith("uint")) {
981 type = YangTypesConverter.javaTypeForBaseYangUnsignedIntegerType(typeName,
983 } else if (typeName.equals("enumeration")) {
984 type = new EnumerationType(enumConstants);
985 } else if (typeName.equals("string")) {
986 type = new StringType(lengthStatements, patternStatements);
987 } else if (typeName.equals("bits")) {
988 type = new BitsType(getBits(typeBody, actualPath, namespace,
990 } else if (typeName.equals("leafref")) {
991 final String path = parseLeafrefPath(typeBody);
992 final boolean absolute = path.startsWith("/");
993 RevisionAwareXPath xpath = new RevisionAwareXPathImpl(path,
995 type = new Leafref(xpath);
996 } else if (typeName.equals("binary")) {
997 type = new BinaryType(null, lengthStatements, null);
998 } else if (typeName.equals("instance-identifier")) {
999 boolean requireInstance = isRequireInstance(typeBody);
1000 type = new InstanceIdentifier(null, requireInstance);
1005 private static String parseLeafrefPath(Type_body_stmtsContext ctx) {
1006 for (int i = 0; i < ctx.getChildCount(); i++) {
1007 ParseTree child = ctx.getChild(i);
1008 if (child instanceof Leafref_specificationContext) {
1009 for (int j = 0; j < child.getChildCount(); j++) {
1010 ParseTree leafRefSpec = child.getChild(j);
1011 if (leafRefSpec instanceof Path_stmtContext) {
1012 return stringFromNode(leafRefSpec);
1021 * Internal helper method for parsing Must_stmtContext.
1025 * @return an array of strings with following fields: [0] must text [1]
1026 * description [2] reference
1028 public static String[] parseMust(YangParser.Must_stmtContext ctx) {
1029 String[] params = new String[3];
1031 String mustText = "";
1032 String description = null;
1033 String reference = null;
1034 for (int i = 0; i < ctx.getChildCount(); ++i) {
1035 ParseTree child = ctx.getChild(i);
1036 if (child instanceof StringContext) {
1037 final StringContext context = (StringContext) child;
1038 for (int j = 0; j < context.getChildCount(); j++) {
1039 String mustPart = context.getChild(j).getText();
1041 mustText += mustPart
1042 .substring(0, mustPart.length() - 1);
1046 mustText += mustPart.substring(1);
1049 } else if (child instanceof Description_stmtContext) {
1050 description = stringFromNode(child);
1051 } else if (child instanceof Reference_stmtContext) {
1052 reference = stringFromNode(child);
1055 params[0] = mustText;
1056 params[1] = description;
1057 params[2] = reference;
1063 * Parse given tree and set constraints to given builder.
1066 * Context to search.
1067 * @param constraintsBuilder
1068 * ConstraintsBuilder to fill.
1070 public static void parseConstraints(ParseTree ctx,
1071 ConstraintsBuilder constraintsBuilder) {
1072 for (int i = 0; i < ctx.getChildCount(); ++i) {
1073 final ParseTree childNode = ctx.getChild(i);
1074 if (childNode instanceof Max_elements_stmtContext) {
1075 Integer max = Integer.valueOf(stringFromNode(childNode));
1076 constraintsBuilder.setMinElements(max);
1077 } else if (childNode instanceof Min_elements_stmtContext) {
1078 Integer min = Integer.valueOf(stringFromNode(childNode));
1079 constraintsBuilder.setMinElements(min);
1080 } else if (childNode instanceof Must_stmtContext) {
1081 String[] mustParams = parseMust((Must_stmtContext) childNode);
1082 constraintsBuilder.addMustDefinition(mustParams[0],
1083 mustParams[1], mustParams[2]);
1084 } else if (childNode instanceof Mandatory_stmtContext) {
1085 for (int j = 0; j < childNode.getChildCount(); j++) {
1086 ParseTree mandatoryTree = ctx.getChild(j);
1087 if (mandatoryTree instanceof Mandatory_argContext) {
1088 Boolean mandatory = Boolean
1089 .valueOf(stringFromNode(mandatoryTree));
1090 constraintsBuilder.setMandatory(mandatory);
1093 } else if (childNode instanceof When_stmtContext) {
1094 constraintsBuilder.addWhenCondition(stringFromNode(childNode));