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/epl-v10.html
8 package org.opendaylight.yangtools.yang.parser.builder.impl;
13 import org.opendaylight.yangtools.yang.common.QName;
14 import org.opendaylight.yangtools.yang.model.api.*;
15 import org.opendaylight.yangtools.yang.parser.builder.api.*;
16 import org.opendaylight.yangtools.yang.parser.util.Comparators;
17 import org.opendaylight.yangtools.yang.parser.util.ModuleImportImpl;
18 import org.opendaylight.yangtools.yang.parser.util.RefineHolder;
19 import org.opendaylight.yangtools.yang.parser.util.YangParseException;
22 * Builder of Module object. If this module is dependent on external
23 * module/modules, these dependencies must be resolved before module is built,
24 * otherwise result may not be valid.
26 public class ModuleBuilder extends AbstractDataNodeContainerBuilder {
28 private final ModuleImpl instance;
29 private final String name;
30 private final String sourcePath;
31 private final SchemaPath schemaPath;
32 private URI namespace;
33 private String prefix;
34 private Date revision;
36 private final boolean submodule;
37 private String belongsTo;
38 private ModuleBuilder parent;
40 public ModuleBuilder getParent() {
44 public void setParent(ModuleBuilder parent) {
48 private final Deque<Builder> actualPath = new LinkedList<>();
49 private final Set<TypeAwareBuilder> dirtyNodes = new HashSet<>();
51 private final Set<ModuleImport> imports = new HashSet<ModuleImport>();
53 private final Set<AugmentationSchema> augments = new HashSet<>();
54 private final List<AugmentationSchemaBuilder> augmentBuilders = new ArrayList<>();
55 private final List<AugmentationSchemaBuilder> allAugments = new ArrayList<>();
57 private final List<GroupingBuilder> allGroupings = new ArrayList<>();
59 private final List<UsesNodeBuilder> allUsesNodes = new ArrayList<>();
61 private final Set<RpcDefinition> rpcs = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
62 private final Set<RpcDefinitionBuilder> addedRpcs = new HashSet<>();
64 private final Set<NotificationDefinition> notifications = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
65 private final Set<NotificationBuilder> addedNotifications = new HashSet<>();
67 private final Set<IdentitySchemaNode> identities = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
68 private final Set<IdentitySchemaNodeBuilder> addedIdentities = new HashSet<>();
70 private final Set<FeatureDefinition> features = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
71 private final Set<FeatureBuilder> addedFeatures = new HashSet<>();
73 private final Set<Deviation> deviations = new HashSet<>();
74 private final Set<DeviationBuilder> deviationBuilders = new HashSet<>();
76 private final List<ExtensionDefinition> extensions = new ArrayList<>();
77 private final List<ExtensionBuilder> addedExtensions = new ArrayList<>();
79 private final List<UnknownSchemaNodeBuilder> allUnknownNodes = new ArrayList<UnknownSchemaNodeBuilder>();
81 private final List<ListSchemaNodeBuilder> allLists = new ArrayList<ListSchemaNodeBuilder>();
83 public ModuleBuilder(final String name, final String sourcePath) {
84 this(name, false, sourcePath);
87 public ModuleBuilder(final String name, final boolean submodule, final String sourcePath) {
90 this.sourcePath = sourcePath;
91 schemaPath = new SchemaPath(Collections.<QName> emptyList(), true);
92 this.submodule = submodule;
93 instance = new ModuleImpl(name, sourcePath);
94 actualPath.push(this);
97 public ModuleBuilder(Module base) {
98 super(base.getName(), 0, null);
99 this.name = base.getName();
100 this.sourcePath = base.getModuleSourcePath();
101 schemaPath = new SchemaPath(Collections.<QName> emptyList(), true);
103 instance = new ModuleImpl(base.getName(), base.getModuleSourcePath());
104 actualPath.push(this);
105 namespace = base.getNamespace();
106 prefix = base.getPrefix();
107 revision = base.getRevision();
109 for (DataSchemaNode childNode : base.getChildNodes()) {
110 childNodes.add(childNode);
113 typedefs.addAll(base.getTypeDefinitions());
114 groupings.addAll(base.getGroupings());
115 usesNodes.addAll(base.getUses());
116 augments.addAll(base.getAugmentations());
117 rpcs.addAll(base.getRpcs());
118 notifications.addAll(base.getNotifications());
119 identities.addAll(base.getIdentities());
120 features.addAll(base.getFeatures());
121 deviations.addAll(base.getDeviations());
122 extensions.addAll(base.getExtensionSchemaNodes());
123 unknownNodes.addAll(base.getUnknownSchemaNodes());
127 * Build new Module object based on this builder.
130 public Module build() {
131 instance.setPrefix(prefix);
132 instance.setRevision(revision);
133 instance.setImports(imports);
134 instance.setNamespace(namespace);
137 for (TypeDefinitionBuilder tdb : addedTypedefs) {
138 typedefs.add(tdb.build());
140 instance.setTypeDefinitions(typedefs);
143 for (DataSchemaNodeBuilder child : addedChildNodes) {
144 childNodes.add(child.build());
146 instance.addChildNodes(childNodes);
149 for (GroupingBuilder gb : addedGroupings) {
150 groupings.add(gb.build());
152 instance.setGroupings(groupings);
155 for (UsesNodeBuilder unb : addedUsesNodes) {
156 usesNodes.add(unb.build());
158 instance.setUses(usesNodes);
161 for (FeatureBuilder fb : addedFeatures) {
162 features.add(fb.build());
164 instance.setFeatures(features);
167 for (NotificationBuilder entry : addedNotifications) {
168 notifications.add(entry.build());
170 instance.setNotifications(notifications);
173 for (AugmentationSchemaBuilder builder : augmentBuilders) {
174 augments.add(builder.build());
176 instance.setAugmentations(augments);
179 for (RpcDefinitionBuilder rpc : addedRpcs) {
180 rpcs.add(rpc.build());
182 instance.setRpcs(rpcs);
185 for (DeviationBuilder entry : deviationBuilders) {
186 deviations.add(entry.build());
188 instance.setDeviations(deviations);
191 for (ExtensionBuilder eb : addedExtensions) {
192 extensions.add(eb.build());
194 Collections.sort(extensions, Comparators.SCHEMA_NODE_COMP);
195 instance.setExtensionSchemaNodes(extensions);
198 for (IdentitySchemaNodeBuilder id : addedIdentities) {
199 identities.add(id.build());
201 instance.setIdentities(identities);
204 for (UnknownSchemaNodeBuilder unb : addedUnknownNodes) {
205 unknownNodes.add(unb.build());
207 Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
208 instance.setUnknownSchemaNodes(unknownNodes);
213 public String getModuleSourcePath() {
218 public void setParent(Builder parent) {
219 throw new YangParseException(name, 0, "Can not set parent to module");
223 public SchemaPath getPath() {
228 public Set<TypeDefinitionBuilder> getTypeDefinitionBuilders() {
229 return addedTypedefs;
232 public void enterNode(final Builder node) {
233 actualPath.push(node);
236 public void exitNode() {
240 public Builder getActualNode() {
241 if (actualPath.isEmpty()) {
244 return actualPath.peekFirst();
248 public Builder getActualParent() {
249 if (actualPath.size() < 2) {
252 Builder builderChild = actualPath.removeFirst();
253 Builder builderParent = actualPath.peekFirst();
254 actualPath.addFirst(builderChild);
255 return builderParent;
259 public Set<TypeAwareBuilder> getDirtyNodes() {
263 public Set<AugmentationSchema> getAugments() {
267 public List<AugmentationSchemaBuilder> getAugmentBuilders() {
268 return augmentBuilders;
271 public List<AugmentationSchemaBuilder> getAllAugments() {
275 public Set<IdentitySchemaNode> getIdentities() {
279 public Set<IdentitySchemaNodeBuilder> getAddedIdentities() {
280 return addedIdentities;
283 public Set<FeatureDefinition> getFeatures() {
287 public Set<FeatureBuilder> getAddedFeatures() {
288 return addedFeatures;
291 public List<GroupingBuilder> getAllGroupings() {
295 public List<UsesNodeBuilder> getAllUsesNodes() {
299 public Set<Deviation> getDeviations() {
303 public Set<DeviationBuilder> getDeviationBuilders() {
304 return deviationBuilders;
307 public List<ExtensionDefinition> getExtensions() {
311 public List<ExtensionBuilder> getAddedExtensions() {
312 return addedExtensions;
315 public List<UnknownSchemaNodeBuilder> getAllUnknownNodes() {
316 return allUnknownNodes;
319 public List<ListSchemaNodeBuilder> getAllLists() {
323 public String getName() {
327 public URI getNamespace() {
331 public void setNamespace(final URI namespace) {
332 this.namespace = namespace;
335 public String getPrefix() {
339 public Date getRevision() {
343 public boolean isSubmodule() {
347 public String getBelongsTo() {
351 public void setBelongsTo(String belongsTo) {
352 this.belongsTo = belongsTo;
355 public void markActualNodeDirty() {
356 final TypeAwareBuilder nodeBuilder = (TypeAwareBuilder) getActualNode();
357 dirtyNodes.add(nodeBuilder);
360 public void setRevision(final Date revision) {
361 this.revision = revision;
364 public void setPrefix(final String prefix) {
365 this.prefix = prefix;
368 public void setYangVersion(final String yangVersion) {
369 instance.setYangVersion(yangVersion);
372 public void setDescription(final String description) {
373 instance.setDescription(description);
376 public void setReference(final String reference) {
377 instance.setReference(reference);
380 public void setOrganization(final String organization) {
381 instance.setOrganization(organization);
384 public void setContact(final String contact) {
385 instance.setContact(contact);
388 public boolean addModuleImport(final String moduleName, final Date revision, final String prefix) {
389 final ModuleImport moduleImport = createModuleImport(moduleName, revision, prefix);
390 return imports.add(moduleImport);
393 public Set<ModuleImport> getModuleImports() {
397 public ExtensionBuilder addExtension(final QName qname, final int line, final SchemaPath path) {
398 Builder parent = getActualNode();
399 if (!(parent.equals(this))) {
400 throw new YangParseException(name, line, "extension can be defined only in module or submodule");
403 final String extName = qname.getLocalName();
404 for (ExtensionBuilder addedExtension : addedExtensions) {
405 if (addedExtension.getQName().getLocalName().equals(extName)) {
406 raiseYangParserException("extension", "node", extName, line, addedExtension.getLine());
409 final ExtensionBuilder builder = new ExtensionBuilder(name, line, qname, path);
410 builder.setParent(parent);
411 addedExtensions.add(builder);
415 public ContainerSchemaNodeBuilder addContainerNode(final int line, final QName qname, final SchemaPath schemaPath) {
416 final ContainerSchemaNodeBuilder builder = new ContainerSchemaNodeBuilder(name, line, qname, schemaPath);
418 Builder parent = getActualNode();
419 builder.setParent(parent);
420 addChildToParent(parent, builder, qname.getLocalName());
425 public ListSchemaNodeBuilder addListNode(final int line, final QName qname, final SchemaPath schemaPath) {
426 final ListSchemaNodeBuilder builder = new ListSchemaNodeBuilder(name, line, qname, schemaPath);
428 Builder parent = getActualNode();
429 builder.setParent(parent);
430 addChildToParent(parent, builder, qname.getLocalName());
431 allLists.add(builder);
436 public LeafSchemaNodeBuilder addLeafNode(final int line, final QName qname, final SchemaPath schemaPath) {
437 final LeafSchemaNodeBuilder builder = new LeafSchemaNodeBuilder(name, line, qname, schemaPath);
439 Builder parent = getActualNode();
440 builder.setParent(parent);
441 addChildToParent(parent, builder, qname.getLocalName());
446 public LeafListSchemaNodeBuilder addLeafListNode(final int line, final QName qname, final SchemaPath schemaPath) {
447 final LeafListSchemaNodeBuilder builder = new LeafListSchemaNodeBuilder(name, line, qname, schemaPath);
449 Builder parent = getActualNode();
450 builder.setParent(parent);
451 addChildToParent(parent, builder, qname.getLocalName());
456 public GroupingBuilder addGrouping(final int line, final QName qname, final SchemaPath path) {
457 final GroupingBuilder builder = new GroupingBuilderImpl(name, line, qname, path);
459 Builder parent = getActualNode();
460 builder.setParent(parent);
462 String groupingName = qname.getLocalName();
463 if (parent.equals(this)) {
464 for (GroupingBuilder addedGrouping : addedGroupings) {
465 if (addedGrouping.getQName().getLocalName().equals(groupingName)) {
466 raiseYangParserException("", "Grouping", groupingName, line, addedGrouping.getLine());
469 addedGroupings.add(builder);
471 if (parent instanceof DataNodeContainerBuilder) {
472 DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parent;
473 for (GroupingBuilder addedGrouping : parentNode.getGroupingBuilders()) {
474 if (addedGrouping.getQName().getLocalName().equals(groupingName)) {
475 raiseYangParserException("", "Grouping", groupingName, line, addedGrouping.getLine());
478 parentNode.addGrouping(builder);
479 } else if (parent instanceof RpcDefinitionBuilder) {
480 RpcDefinitionBuilder parentNode = (RpcDefinitionBuilder) parent;
481 for (GroupingBuilder child : parentNode.getGroupings()) {
482 if (child.getQName().getLocalName().equals(groupingName)) {
483 raiseYangParserException("", "Grouping", groupingName, line, child.getLine());
486 parentNode.addGrouping(builder);
488 throw new YangParseException(name, line, "Unresolved parent of grouping " + groupingName);
492 allGroupings.add(builder);
496 public AugmentationSchemaBuilder addAugment(final int line, final String augmentTargetStr) {
497 final AugmentationSchemaBuilder builder = new AugmentationSchemaBuilderImpl(name, line, augmentTargetStr);
499 Builder parent = getActualNode();
500 builder.setParent(parent);
502 if (parent.equals(this)) {
503 // augment can be declared only under 'module' ...
504 if (!(augmentTargetStr.startsWith("/"))) {
505 throw new YangParseException(
508 "If the 'augment' statement is on the top level in a module, the absolute form of a schema node identifier MUST be used.");
510 augmentBuilders.add(builder);
512 // ... or 'uses' statement
513 if (parent instanceof UsesNodeBuilder) {
514 if (augmentTargetStr.startsWith("/")) {
515 throw new YangParseException(name, line,
516 "If 'augment' statement is a substatement to the 'uses' statement, it cannot contain absolute path ("
517 + augmentTargetStr + ")");
519 ((UsesNodeBuilder) parent).addAugment(builder);
521 throw new YangParseException(name, line, "Augment can be declared only under module or uses statement.");
524 allAugments.add(builder);
530 public void addUsesNode(UsesNodeBuilder usesBuilder) {
531 addedUsesNodes.add(usesBuilder);
532 allUsesNodes.add(usesBuilder);
535 public UsesNodeBuilder addUsesNode(final int line, final String groupingPathStr) {
536 final UsesNodeBuilder usesBuilder = new UsesNodeBuilderImpl(name, line, groupingPathStr);
538 Builder parent = getActualNode();
539 usesBuilder.setParent(parent);
541 if (parent.equals(this)) {
542 addedUsesNodes.add(usesBuilder);
544 if (!(parent instanceof DataNodeContainerBuilder)) {
545 throw new YangParseException(name, line, "Unresolved parent of uses '" + groupingPathStr + "'.");
547 ((DataNodeContainerBuilder) parent).addUsesNode(usesBuilder);
549 if (parent instanceof AugmentationSchemaBuilder) {
550 usesBuilder.setAugmenting(true);
553 allUsesNodes.add(usesBuilder);
557 public void addRefine(final RefineHolder refine) {
558 final Builder parent = getActualNode();
559 if (!(parent instanceof UsesNodeBuilder)) {
560 throw new YangParseException(name, refine.getLine(), "refine can be defined only in uses statement");
562 ((UsesNodeBuilder) parent).addRefine(refine);
563 refine.setParent(parent);
566 public RpcDefinitionBuilder addRpc(final int line, final QName qname, final SchemaPath path) {
567 Builder parent = getActualNode();
568 if (!(parent.equals(this))) {
569 throw new YangParseException(name, line, "rpc can be defined only in module or submodule");
572 final RpcDefinitionBuilder rpcBuilder = new RpcDefinitionBuilder(name, line, qname, path);
573 rpcBuilder.setParent(parent);
575 String rpcName = qname.getLocalName();
576 for (RpcDefinitionBuilder rpc : addedRpcs) {
577 if (rpc.getQName().getLocalName().equals(rpcName)) {
578 raiseYangParserException("", "rpc", rpcName, line, rpc.getLine());
581 for (DataSchemaNodeBuilder addedChild : addedChildNodes) {
582 if (addedChild.getQName().getLocalName().equals(rpcName)) {
583 raiseYangParserException("rpc", "node", rpcName, line, addedChild.getLine());
586 for (NotificationBuilder addedNotification : addedNotifications) {
587 if (addedNotification.getQName().getLocalName().equals(rpcName)) {
588 raiseYangParserException("rpc", "notification", rpcName, line, addedNotification.getLine());
591 addedRpcs.add(rpcBuilder);
595 public ContainerSchemaNodeBuilder addRpcInput(final int line, final QName qname, final SchemaPath schemaPath) {
596 final Builder parent = getActualNode();
597 if (!(parent instanceof RpcDefinitionBuilder)) {
598 throw new YangParseException(name, line, "input can be defined only in rpc statement");
600 final RpcDefinitionBuilder rpc = (RpcDefinitionBuilder) parent;
602 final ContainerSchemaNodeBuilder inputBuilder = new ContainerSchemaNodeBuilder(name, line, qname, schemaPath);
603 inputBuilder.setParent(rpc);
605 rpc.setInput(inputBuilder);
609 public ContainerSchemaNodeBuilder addRpcOutput(final SchemaPath schemaPath, final QName qname, final int line) {
610 final Builder parent = getActualNode();
611 if (!(parent instanceof RpcDefinitionBuilder)) {
612 throw new YangParseException(name, line, "output can be defined only in rpc statement");
614 final RpcDefinitionBuilder rpc = (RpcDefinitionBuilder) parent;
616 final ContainerSchemaNodeBuilder outputBuilder = new ContainerSchemaNodeBuilder(name, line, qname, schemaPath);
617 outputBuilder.setParent(rpc);
619 rpc.setOutput(outputBuilder);
620 return outputBuilder;
623 public void addNotification(NotificationDefinition notification) {
624 notifications.add(notification);
627 public NotificationBuilder addNotification(final int line, final QName qname, final SchemaPath path) {
628 final Builder parent = getActualNode();
629 if (!(parent.equals(this))) {
630 throw new YangParseException(name, line, "notification can be defined only in module or submodule");
633 String notificationName = qname.getLocalName();
634 for (NotificationBuilder nb : addedNotifications) {
635 if (nb.getQName().equals(qname)) {
636 raiseYangParserException("", "notification", notificationName, line, nb.getLine());
639 for (RpcDefinitionBuilder rpc : addedRpcs) {
640 if (rpc.getQName().getLocalName().equals(notificationName)) {
641 raiseYangParserException("notification", "rpc", notificationName, line, rpc.getLine());
644 for (DataSchemaNodeBuilder addedChild : addedChildNodes) {
645 if (addedChild.getQName().getLocalName().equals(notificationName)) {
646 raiseYangParserException("notification", "node", notificationName, line, addedChild.getLine());
650 final NotificationBuilder builder = new NotificationBuilder(name, line, qname, path);
651 builder.setParent(parent);
652 addedNotifications.add(builder);
657 public FeatureBuilder addFeature(final int line, final QName qname, final SchemaPath path) {
658 Builder parent = getActualNode();
659 if (!(parent.equals(this))) {
660 throw new YangParseException(name, line, "feature can be defined only in module or submodule");
663 final FeatureBuilder builder = new FeatureBuilder(name, line, qname, path);
664 builder.setParent(parent);
666 String featureName = qname.getLocalName();
667 for (FeatureBuilder addedFeature : addedFeatures) {
668 if (addedFeature.getQName().getLocalName().equals(featureName)) {
669 raiseYangParserException("", "feature", featureName, line, addedFeature.getLine());
672 addedFeatures.add(builder);
676 public ChoiceBuilder addChoice(final int line, final QName qname, final SchemaPath path) {
677 final ChoiceBuilder builder = new ChoiceBuilder(name, line, qname, path);
679 Builder parent = getActualNode();
680 builder.setParent(parent);
681 addChildToParent(parent, builder, qname.getLocalName());
686 public ChoiceCaseBuilder addCase(final int line, final QName qname, final SchemaPath path) {
687 Builder parent = getActualNode();
688 if (parent == null || parent.equals(this)) {
689 throw new YangParseException(name, line, "'case' parent not found");
692 final ChoiceCaseBuilder builder = new ChoiceCaseBuilder(name, line, qname, path);
693 builder.setParent(parent);
695 if (parent instanceof ChoiceBuilder) {
696 ((ChoiceBuilder) parent).addCase(builder);
697 } else if (parent instanceof AugmentationSchemaBuilder) {
698 ((AugmentationSchemaBuilder) parent).addChildNode(builder);
700 throw new YangParseException(name, line, "Unresolved parent of 'case' " + qname.getLocalName());
706 public AnyXmlBuilder addAnyXml(final int line, final QName qname, final SchemaPath schemaPath) {
707 final AnyXmlBuilder builder = new AnyXmlBuilder(name, line, qname, schemaPath);
709 Builder parent = getActualNode();
710 builder.setParent(parent);
711 addChildToParent(parent, builder, qname.getLocalName());
717 public void addTypedef(TypeDefinitionBuilder typedefBuilder) {
718 String nodeName = typedefBuilder.getQName().getLocalName();
719 for (TypeDefinitionBuilder tdb : addedTypedefs) {
720 if (tdb.getQName().getLocalName().equals(nodeName)) {
721 raiseYangParserException("", "typedef", nodeName, typedefBuilder.getLine(), tdb.getLine());
724 addedTypedefs.add(typedefBuilder);
727 public TypeDefinitionBuilderImpl addTypedef(final int line, final QName qname, final SchemaPath path) {
728 final TypeDefinitionBuilderImpl builder = new TypeDefinitionBuilderImpl(name, line, qname, path);
730 Builder parent = getActualNode();
731 builder.setParent(parent);
733 String typedefName = qname.getLocalName();
734 if (parent.equals(this)) {
735 for (TypeDefinitionBuilder tdb : addedTypedefs) {
736 if (tdb.getQName().getLocalName().equals(typedefName)) {
737 raiseYangParserException("", "typedef", typedefName, line, tdb.getLine());
740 addedTypedefs.add(builder);
742 if (parent instanceof DataNodeContainerBuilder) {
743 DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parent;
744 for (TypeDefinitionBuilder child : parentNode.getTypeDefinitionBuilders()) {
745 if (child.getQName().getLocalName().equals(typedefName)) {
746 raiseYangParserException("", "typedef", typedefName, line, child.getLine());
749 parentNode.addTypedef(builder);
750 } else if (parent instanceof RpcDefinitionBuilder) {
751 RpcDefinitionBuilder rpcParent = (RpcDefinitionBuilder) parent;
752 for (TypeDefinitionBuilder tdb : rpcParent.getTypeDefinitions()) {
753 if (tdb.getQName().getLocalName().equals(builder.getQName().getLocalName())) {
754 raiseYangParserException("", "typedef", typedefName, line, tdb.getLine());
757 rpcParent.addTypedef(builder);
759 throw new YangParseException(name, line, "Unresolved parent of typedef " + typedefName);
766 public void setType(final TypeDefinition<?> type) {
767 Builder parent = getActualNode();
768 if (!(parent instanceof TypeAwareBuilder)) {
769 throw new YangParseException("Failed to set type '" + type.getQName().getLocalName()
770 + "'. Invalid parent node: " + parent);
772 ((TypeAwareBuilder) parent).setType(type);
775 public UnionTypeBuilder addUnionType(final int line, final URI namespace, final Date revision) {
776 final Builder parent = getActualNode();
777 if (parent == null) {
778 throw new YangParseException(name, line, "Unresolved parent of union type");
780 final UnionTypeBuilder union = new UnionTypeBuilder(name, line);
781 if (parent instanceof TypeAwareBuilder) {
782 ((TypeAwareBuilder) parent).setTypedef(union);
785 throw new YangParseException(name, line, "Invalid parent of union type.");
790 public void addIdentityrefType(final int line, final SchemaPath schemaPath, final String baseString) {
791 final IdentityrefTypeBuilder identityref = new IdentityrefTypeBuilder(name, line, baseString, schemaPath);
793 final Builder parent = getActualNode();
794 if (parent == null) {
795 throw new YangParseException(name, line, "Unresolved parent of identityref type.");
797 if (parent instanceof TypeAwareBuilder) {
798 final TypeAwareBuilder typeParent = (TypeAwareBuilder) parent;
799 typeParent.setTypedef(identityref);
800 dirtyNodes.add(typeParent);
802 throw new YangParseException(name, line, "Invalid parent of identityref type.");
807 public DeviationBuilder addDeviation(final int line, final String targetPath) {
808 Builder parent = getActualNode();
809 if (!(parent.equals(this))) {
810 throw new YangParseException(name, line, "deviation can be defined only in module or submodule");
813 final DeviationBuilder builder = new DeviationBuilder(name, line, targetPath);
814 builder.setParent(parent);
815 deviationBuilders.add(builder);
819 public IdentitySchemaNodeBuilder addIdentity(final QName qname, final int line, final SchemaPath path) {
820 Builder parent = getActualNode();
821 if (!(parent.equals(this))) {
822 throw new YangParseException(name, line, "identity can be defined only in module or submodule");
824 String identityName = qname.getLocalName();
825 for (IdentitySchemaNodeBuilder idBuilder : addedIdentities) {
826 if (idBuilder.getQName().equals(qname)) {
827 raiseYangParserException("", "identity", identityName, line, idBuilder.getLine());
831 final IdentitySchemaNodeBuilder builder = new IdentitySchemaNodeBuilder(name, line, qname, path);
832 builder.setParent(parent);
833 addedIdentities.add(builder);
838 public void addUnknownNodeBuilder(final UnknownSchemaNodeBuilder builder) {
839 addedUnknownNodes.add(builder);
840 allUnknownNodes.add(builder);
843 public UnknownSchemaNodeBuilder addUnknownSchemaNode(final int line, final QName qname, final SchemaPath path) {
844 final Builder parent = getActualNode();
845 final UnknownSchemaNodeBuilder builder = new UnknownSchemaNodeBuilder(name, line, qname, path);
846 builder.setParent(parent);
847 allUnknownNodes.add(builder);
849 if (parent.equals(this)) {
850 addedUnknownNodes.add(builder);
852 if (parent instanceof SchemaNodeBuilder) {
853 ((SchemaNodeBuilder) parent).addUnknownNodeBuilder(builder);
854 } else if (parent instanceof DataNodeContainerBuilder) {
855 ((DataNodeContainerBuilder) parent).addUnknownNodeBuilder(builder);
856 } else if (parent instanceof RefineHolder) {
857 ((RefineHolder) parent).addUnknownNodeBuilder(builder);
859 throw new YangParseException(name, line, "Unresolved parent of unknown node '" + qname.getLocalName()
867 public Set<RpcDefinition> getRpcs() {
871 public Set<RpcDefinitionBuilder> getAddedRpcs() {
875 public Set<NotificationDefinition> getNotifications() {
876 return notifications;
879 public Set<NotificationBuilder> getAddedNotifications() {
880 return addedNotifications;
884 public String toString() {
885 return "module " + name;
888 private final class ModuleImpl implements Module {
889 private URI namespace;
890 private final String name;
891 private final String sourcePath;
892 private Date revision;
893 private String prefix;
894 private String yangVersion;
895 private String description;
896 private String reference;
897 private String organization;
898 private String contact;
899 private final Set<ModuleImport> imports = new HashSet<>();
900 private final Set<FeatureDefinition> features = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
901 private final Set<TypeDefinition<?>> typeDefinitions = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
902 private final Set<NotificationDefinition> notifications = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
903 private final Set<AugmentationSchema> augmentations = new HashSet<>();
904 private final Set<RpcDefinition> rpcs = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
905 private final Set<Deviation> deviations = new HashSet<>();
906 private final Set<DataSchemaNode> childNodes = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
907 private final Set<GroupingDefinition> groupings = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
908 private final Set<UsesNode> uses = new HashSet<>();
909 private final List<ExtensionDefinition> extensionNodes = new ArrayList<>();
910 private final Set<IdentitySchemaNode> identities = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
911 private final List<UnknownSchemaNode> unknownNodes = new ArrayList<>();
913 private ModuleImpl(String name, String sourcePath) {
915 this.sourcePath = sourcePath;
919 public String getModuleSourcePath() {
924 public URI getNamespace() {
928 private void setNamespace(URI namespace) {
929 this.namespace = namespace;
933 public String getName() {
938 public Date getRevision() {
942 private void setRevision(Date revision) {
943 this.revision = revision;
947 public String getPrefix() {
951 private void setPrefix(String prefix) {
952 this.prefix = prefix;
956 public String getYangVersion() {
960 private void setYangVersion(String yangVersion) {
961 this.yangVersion = yangVersion;
965 public String getDescription() {
969 private void setDescription(String description) {
970 this.description = description;
974 public String getReference() {
978 private void setReference(String reference) {
979 this.reference = reference;
983 public String getOrganization() {
987 private void setOrganization(String organization) {
988 this.organization = organization;
992 public String getContact() {
996 private void setContact(String contact) {
997 this.contact = contact;
1001 public Set<ModuleImport> getImports() {
1005 private void setImports(Set<ModuleImport> imports) {
1006 if (imports != null) {
1007 this.imports.addAll(imports);
1012 public Set<FeatureDefinition> getFeatures() {
1016 private void setFeatures(Set<FeatureDefinition> features) {
1017 if (features != null) {
1018 this.features.addAll(features);
1023 public Set<TypeDefinition<?>> getTypeDefinitions() {
1024 return typeDefinitions;
1027 private void setTypeDefinitions(Set<TypeDefinition<?>> typeDefinitions) {
1028 if (typeDefinitions != null) {
1029 this.typeDefinitions.addAll(typeDefinitions);
1034 public Set<NotificationDefinition> getNotifications() {
1035 return notifications;
1038 private void setNotifications(Set<NotificationDefinition> notifications) {
1039 if (notifications != null) {
1040 this.notifications.addAll(notifications);
1045 public Set<AugmentationSchema> getAugmentations() {
1046 return augmentations;
1049 private void setAugmentations(Set<AugmentationSchema> augmentations) {
1050 if (augmentations != null) {
1051 this.augmentations.addAll(augmentations);
1056 public Set<RpcDefinition> getRpcs() {
1060 private void setRpcs(Set<RpcDefinition> rpcs) {
1062 this.rpcs.addAll(rpcs);
1067 public Set<Deviation> getDeviations() {
1071 private void setDeviations(Set<Deviation> deviations) {
1072 if (deviations != null) {
1073 this.deviations.addAll(deviations);
1078 public Set<DataSchemaNode> getChildNodes() {
1079 return Collections.unmodifiableSet(childNodes);
1082 private void addChildNodes(Set<DataSchemaNode> childNodes) {
1083 if (childNodes != null) {
1084 this.childNodes.addAll(childNodes);
1089 public Set<GroupingDefinition> getGroupings() {
1093 private void setGroupings(Set<GroupingDefinition> groupings) {
1094 if (groupings != null) {
1095 this.groupings.addAll(groupings);
1100 public Set<UsesNode> getUses() {
1104 private void setUses(Set<UsesNode> uses) {
1106 this.uses.addAll(uses);
1111 public List<ExtensionDefinition> getExtensionSchemaNodes() {
1112 Collections.sort(extensionNodes, Comparators.SCHEMA_NODE_COMP);
1113 return extensionNodes;
1116 private void setExtensionSchemaNodes(final List<ExtensionDefinition> extensionNodes) {
1117 if (extensionNodes != null) {
1118 this.extensionNodes.addAll(extensionNodes);
1123 public Set<IdentitySchemaNode> getIdentities() {
1127 private void setIdentities(final Set<IdentitySchemaNode> identities) {
1128 if (identities != null) {
1129 this.identities.addAll(identities);
1134 public List<UnknownSchemaNode> getUnknownSchemaNodes() {
1135 return unknownNodes;
1138 private void setUnknownSchemaNodes(final List<UnknownSchemaNode> unknownNodes) {
1139 if (unknownNodes != null) {
1140 this.unknownNodes.addAll(unknownNodes);
1145 public DataSchemaNode getDataChildByName(QName name) {
1146 return getChildNode(childNodes, name);
1150 public DataSchemaNode getDataChildByName(String name) {
1151 return getChildNode(childNodes, name);
1155 public int hashCode() {
1156 final int prime = 31;
1158 result = prime * result + ((namespace == null) ? 0 : namespace.hashCode());
1159 result = prime * result + ((name == null) ? 0 : name.hashCode());
1160 result = prime * result + ((revision == null) ? 0 : revision.hashCode());
1161 result = prime * result + ((prefix == null) ? 0 : prefix.hashCode());
1162 result = prime * result + ((yangVersion == null) ? 0 : yangVersion.hashCode());
1167 public boolean equals(Object obj) {
1174 if (getClass() != obj.getClass()) {
1177 ModuleImpl other = (ModuleImpl) obj;
1178 if (namespace == null) {
1179 if (other.namespace != null) {
1182 } else if (!namespace.equals(other.namespace)) {
1186 if (other.name != null) {
1189 } else if (!name.equals(other.name)) {
1192 if (revision == null) {
1193 if (other.revision != null) {
1196 } else if (!revision.equals(other.revision)) {
1199 if (prefix == null) {
1200 if (other.prefix != null) {
1203 } else if (!prefix.equals(other.prefix)) {
1206 if (yangVersion == null) {
1207 if (other.yangVersion != null) {
1210 } else if (!yangVersion.equals(other.yangVersion)) {
1217 public String toString() {
1218 StringBuilder sb = new StringBuilder(ModuleImpl.class.getSimpleName());
1220 sb.append("name=" + name);
1221 sb.append(", namespace=" + namespace);
1222 sb.append(", revision=" + revision);
1223 sb.append(", prefix=" + prefix);
1224 sb.append(", yangVersion=" + yangVersion);
1226 return sb.toString();
1231 * Add child to parent. Method checks for duplicates and add given child
1232 * node to parent. If node with same name is found, throws exception. If
1233 * parent is null, child node will be added directly to module.
1239 private void addChildToParent(final Builder parent, final DataSchemaNodeBuilder child, final String childName) {
1240 final int lineNum = child.getLine();
1241 if (parent.equals(this)) {
1242 addChildToModule(child, childName, lineNum);
1244 addChildToSubnodeOfModule(parent, child, childName, lineNum);
1249 * Adds child node <code>child</code> to the set of nodes child nodes.
1251 * The method reduces the complexity of the method
1252 * {@link #addChildToParent(Builder, DataSchemaNodeBuilder, String)
1253 * addChildToParent}.
1256 * data schema node builder for child node
1258 * string with name of child node
1260 * line number in YANG file where is the node with the name equal
1261 * to <code>childName</code> is defined
1263 private void addChildToModule(final DataSchemaNodeBuilder child, final String childName, final int lineNum) {
1264 // if parent == null => node is defined under module
1265 // All leafs, leaf-lists, lists, containers, choices, rpcs,
1266 // notifications, and anyxmls defined within a parent node or at the
1267 // top level of the module or its submodules share the same
1268 // identifier namespace.
1269 for (DataSchemaNodeBuilder childNode : addedChildNodes) {
1270 if (childNode.getQName().getLocalName().equals(childName)) {
1271 raiseYangParserException("'" + child + "'", "node", childName, lineNum, childNode.getLine());
1274 for (RpcDefinitionBuilder rpc : addedRpcs) {
1275 if (rpc.getQName().getLocalName().equals(childName)) {
1276 raiseYangParserException("'" + child + "'", "rpc", childName, lineNum, rpc.getLine());
1279 for (NotificationBuilder notification : addedNotifications) {
1280 if (notification.getQName().getLocalName().equals(childName)) {
1281 raiseYangParserException("'" + child + "'", "notification", childName, lineNum, notification.getLine());
1284 addedChildNodes.add(child);
1288 * Adds child node <code>child</code> to the group of child nodes of the
1289 * <code>parent</code>
1291 * The method reduces the complexity of the method
1292 * {@link #addChildToParent(Builder, DataSchemaNodeBuilder, String)
1293 * addChildToParent}. *
1296 * builder of node which is parent for <code>child</code>
1298 * data schema node builder for child node
1300 * string with name of child node
1302 * line number in YANG file where is the node with the name equal
1303 * to <code>childName</code> is defined
1305 private void addChildToSubnodeOfModule(final Builder parent, final DataSchemaNodeBuilder child,
1306 final String childName, final int lineNum) {
1307 // no need for checking rpc and notification because they can be
1308 // defined only under module or submodule
1309 if (parent instanceof DataNodeContainerBuilder) {
1310 DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parent;
1311 for (DataSchemaNodeBuilder childNode : parentNode.getChildNodeBuilders()) {
1312 if (childNode.getQName().getLocalName().equals(childName)) {
1313 raiseYangParserException("'" + child + "'", "node", childName, lineNum, childNode.getLine());
1316 parentNode.addChildNode(child);
1317 } else if (parent instanceof ChoiceBuilder) {
1318 ChoiceBuilder parentNode = (ChoiceBuilder) parent;
1319 for (ChoiceCaseBuilder caseBuilder : parentNode.getCases()) {
1320 if (caseBuilder.getQName().getLocalName().equals(childName)) {
1321 raiseYangParserException("'" + child + "'", "node", childName, lineNum, caseBuilder.getLine());
1324 parentNode.addCase(child);
1326 throw new YangParseException(name, lineNum, "Unresolved parent of node '" + childName + "'.");
1330 private ModuleImport createModuleImport(final String moduleName, final Date revision, final String prefix) {
1331 final ModuleImport moduleImport = new ModuleImportImpl(moduleName, revision, prefix);
1332 return moduleImport;
1335 private void raiseYangParserException(final String cantAddType, final String type, final String name,
1336 final int currentLine, final int duplicateLine) {
1338 StringBuilder msgPrefix = new StringBuilder("");
1339 if (cantAddType != null && !cantAddType.isEmpty()) {
1340 msgPrefix.append("Can not add ");
1341 msgPrefix.append(cantAddType);
1342 msgPrefix.append(": ");
1345 String msg = String.format("%s%s with same name '%s' already declared at line %d.", msgPrefix, type, name,
1347 throw new YangParseException(moduleName, currentLine, msg);
1351 public int hashCode() {
1352 final int prime = 31;
1354 result = prime * result + ((name == null) ? 0 : name.hashCode());
1355 result = prime * result + ((namespace == null) ? 0 : namespace.hashCode());
1356 result = prime * result + ((revision == null) ? 0 : revision.hashCode());
1357 result = prime * result + ((prefix == null) ? 0 : prefix.hashCode());
1363 public boolean equals(Object obj) {
1370 if (getClass() != obj.getClass()) {
1373 ModuleBuilder other = (ModuleBuilder) obj;
1375 if (other.name != null) {
1378 } else if (!name.equals(other.name)) {
1381 if (namespace == null) {
1382 if (other.namespace != null) {
1385 } else if (!namespace.equals(other.namespace)) {
1388 if (prefix == null) {
1389 if (other.prefix != null) {
1392 } else if (!prefix.equals(other.prefix)) {
1395 if (revision == null) {
1396 if (other.revision != null) {
1399 } else if (!revision.equals(other.revision)) {