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 SchemaPath schemaPath;
31 private URI namespace;
32 private String prefix;
33 private Date revision;
35 private final boolean submodule;
36 private String belongsTo;
37 private ModuleBuilder parent;
39 public ModuleBuilder getParent() {
43 public void setParent(ModuleBuilder parent) {
47 private final Deque<Builder> actualPath = new LinkedList<>();
48 private final Set<TypeAwareBuilder> dirtyNodes = new HashSet<>();
50 private final Set<ModuleImport> imports = new HashSet<ModuleImport>();
52 private final Set<AugmentationSchema> augments = new HashSet<>();
53 private final List<AugmentationSchemaBuilder> augmentBuilders = new ArrayList<>();
54 private final List<AugmentationSchemaBuilder> allAugments = new ArrayList<>();
56 private final List<GroupingBuilder> allGroupings = new ArrayList<>();
58 private final List<UsesNodeBuilder> allUsesNodes = new ArrayList<>();
60 private final Set<RpcDefinition> rpcs = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
61 private final Set<RpcDefinitionBuilder> addedRpcs = new HashSet<>();
63 private final Set<NotificationDefinition> notifications = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
64 private final Set<NotificationBuilder> addedNotifications = new HashSet<>();
66 private final Set<IdentitySchemaNode> identities = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
67 private final Set<IdentitySchemaNodeBuilder> addedIdentities = new HashSet<>();
69 private final Set<FeatureDefinition> features = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
70 private final Set<FeatureBuilder> addedFeatures = new HashSet<>();
72 private final Set<Deviation> deviations = new HashSet<>();
73 private final Set<DeviationBuilder> deviationBuilders = new HashSet<>();
75 private final List<ExtensionDefinition> extensions = new ArrayList<>();
76 private final List<ExtensionBuilder> addedExtensions = new ArrayList<>();
78 private final List<UnknownSchemaNodeBuilder> allUnknownNodes = new ArrayList<UnknownSchemaNodeBuilder>();
80 public ModuleBuilder(final String name) {
84 public ModuleBuilder(final String name, final boolean submodule) {
87 schemaPath = new SchemaPath(Collections.<QName> emptyList(), true);
88 instance = new ModuleImpl(name);
89 this.submodule = submodule;
90 actualPath.push(this);
93 public ModuleBuilder(Module base) {
94 super(base.getName(), 0, null);
95 this.name = base.getName();
96 schemaPath = new SchemaPath(Collections.<QName> emptyList(), true);
97 instance = new ModuleImpl(base.getName());
99 actualPath.push(this);
101 namespace = base.getNamespace();
102 prefix = base.getPrefix();
103 revision = base.getRevision();
105 for (DataSchemaNode childNode : base.getChildNodes()) {
106 childNodes.add(childNode);
109 typedefs.addAll(base.getTypeDefinitions());
110 groupings.addAll(base.getGroupings());
111 usesNodes.addAll(base.getUses());
112 augments.addAll(base.getAugmentations());
113 rpcs.addAll(base.getRpcs());
114 notifications.addAll(base.getNotifications());
115 identities.addAll(base.getIdentities());
116 features.addAll(base.getFeatures());
117 deviations.addAll(base.getDeviations());
118 extensions.addAll(base.getExtensionSchemaNodes());
119 unknownNodes.addAll(base.getUnknownSchemaNodes());
123 * Build new Module object based on this builder.
126 public Module build() {
127 instance.setPrefix(prefix);
128 instance.setRevision(revision);
129 instance.setImports(imports);
130 instance.setNamespace(namespace);
133 for (TypeDefinitionBuilder tdb : addedTypedefs) {
134 typedefs.add(tdb.build());
136 instance.setTypeDefinitions(typedefs);
139 for (DataSchemaNodeBuilder child : addedChildNodes) {
140 childNodes.add(child.build());
142 instance.addChildNodes(childNodes);
145 for (GroupingBuilder gb : addedGroupings) {
146 groupings.add(gb.build());
148 instance.setGroupings(groupings);
151 for (UsesNodeBuilder unb : addedUsesNodes) {
152 usesNodes.add(unb.build());
154 instance.setUses(usesNodes);
157 for (FeatureBuilder fb : addedFeatures) {
158 features.add(fb.build());
160 instance.setFeatures(features);
163 for (NotificationBuilder entry : addedNotifications) {
164 notifications.add(entry.build());
166 instance.setNotifications(notifications);
169 for (AugmentationSchemaBuilder builder : augmentBuilders) {
170 augments.add(builder.build());
172 instance.setAugmentations(augments);
175 for (RpcDefinitionBuilder rpc : addedRpcs) {
176 rpcs.add(rpc.build());
178 instance.setRpcs(rpcs);
181 for (DeviationBuilder entry : deviationBuilders) {
182 deviations.add(entry.build());
184 instance.setDeviations(deviations);
187 for (ExtensionBuilder eb : addedExtensions) {
188 extensions.add(eb.build());
190 Collections.sort(extensions, Comparators.SCHEMA_NODE_COMP);
191 instance.setExtensionSchemaNodes(extensions);
194 for (IdentitySchemaNodeBuilder id : addedIdentities) {
195 identities.add(id.build());
197 instance.setIdentities(identities);
200 for (UnknownSchemaNodeBuilder unb : addedUnknownNodes) {
201 unknownNodes.add(unb.build());
203 Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
204 instance.setUnknownSchemaNodes(unknownNodes);
210 public void setParent(Builder parent) {
211 throw new YangParseException(name, 0, "Can not set parent to module");
215 public SchemaPath getPath() {
220 public Set<TypeDefinitionBuilder> getTypeDefinitionBuilders() {
221 return addedTypedefs;
224 public void enterNode(final Builder node) {
225 actualPath.push(node);
228 public void exitNode() {
232 public Builder getActualNode() {
233 if (actualPath.isEmpty()) {
236 return actualPath.peekFirst();
240 public Builder getActualParent() {
241 if (actualPath.size() < 2) {
244 Builder builderChild = actualPath.removeFirst();
245 Builder builderParent = actualPath.peekFirst();
246 actualPath.addFirst(builderChild);
247 return builderParent;
251 public Set<TypeAwareBuilder> getDirtyNodes() {
255 public Set<AugmentationSchema> getAugments() {
259 public List<AugmentationSchemaBuilder> getAugmentBuilders() {
260 return augmentBuilders;
263 public List<AugmentationSchemaBuilder> getAllAugments() {
267 public Set<IdentitySchemaNode> getIdentities() {
271 public Set<IdentitySchemaNodeBuilder> getAddedIdentities() {
272 return addedIdentities;
275 public Set<FeatureDefinition> getFeatures() {
279 public Set<FeatureBuilder> getAddedFeatures() {
280 return addedFeatures;
283 public List<GroupingBuilder> getAllGroupings() {
287 public List<UsesNodeBuilder> getAllUsesNodes() {
291 public Set<Deviation> getDeviations() {
295 public Set<DeviationBuilder> getDeviationBuilders() {
296 return deviationBuilders;
299 public List<ExtensionDefinition> getExtensions() {
303 public List<ExtensionBuilder> getAddedExtensions() {
304 return addedExtensions;
307 public List<UnknownSchemaNodeBuilder> getAllUnknownNodes() {
308 return allUnknownNodes;
311 public String getName() {
315 public URI getNamespace() {
319 public void setNamespace(final URI namespace) {
320 this.namespace = namespace;
323 public String getPrefix() {
327 public Date getRevision() {
331 public boolean isSubmodule() {
335 public String getBelongsTo() {
339 public void setBelongsTo(String belongsTo) {
340 this.belongsTo = belongsTo;
343 public void markActualNodeDirty() {
344 final TypeAwareBuilder nodeBuilder = (TypeAwareBuilder) getActualNode();
345 dirtyNodes.add(nodeBuilder);
348 public void setRevision(final Date revision) {
349 this.revision = revision;
352 public void setPrefix(final String prefix) {
353 this.prefix = prefix;
356 public void setYangVersion(final String yangVersion) {
357 instance.setYangVersion(yangVersion);
360 public void setDescription(final String description) {
361 instance.setDescription(description);
364 public void setReference(final String reference) {
365 instance.setReference(reference);
368 public void setOrganization(final String organization) {
369 instance.setOrganization(organization);
372 public void setContact(final String contact) {
373 instance.setContact(contact);
376 public boolean addModuleImport(final String moduleName, final Date revision, final String prefix) {
377 final ModuleImport moduleImport = createModuleImport(moduleName, revision, prefix);
378 return imports.add(moduleImport);
381 public Set<ModuleImport> getModuleImports() {
385 public ExtensionBuilder addExtension(final QName qname, final int line, final SchemaPath path) {
386 Builder parent = getActualNode();
387 if (!(parent.equals(this))) {
388 throw new YangParseException(name, line, "extension can be defined only in module or submodule");
391 final String extName = qname.getLocalName();
392 for (ExtensionBuilder addedExtension : addedExtensions) {
393 if (addedExtension.getQName().getLocalName().equals(extName)) {
394 raiseYangParserException("extension", "node", extName, line, addedExtension.getLine());
397 final ExtensionBuilder builder = new ExtensionBuilder(name, line, qname, path);
398 builder.setParent(parent);
399 addedExtensions.add(builder);
403 public ContainerSchemaNodeBuilder addContainerNode(final int line, final QName qname, final SchemaPath schemaPath) {
404 final ContainerSchemaNodeBuilder builder = new ContainerSchemaNodeBuilder(name, line, qname, schemaPath);
406 Builder parent = getActualNode();
407 builder.setParent(parent);
408 addChildToParent(parent, builder, qname.getLocalName());
413 public ListSchemaNodeBuilder addListNode(final int line, final QName qname, final SchemaPath schemaPath) {
414 final ListSchemaNodeBuilder builder = new ListSchemaNodeBuilder(name, line, qname, schemaPath);
416 Builder parent = getActualNode();
417 builder.setParent(parent);
418 addChildToParent(parent, builder, qname.getLocalName());
423 public LeafSchemaNodeBuilder addLeafNode(final int line, final QName qname, final SchemaPath schemaPath) {
424 final LeafSchemaNodeBuilder builder = new LeafSchemaNodeBuilder(name, line, qname, schemaPath);
426 Builder parent = getActualNode();
427 builder.setParent(parent);
428 addChildToParent(parent, builder, qname.getLocalName());
433 public LeafListSchemaNodeBuilder addLeafListNode(final int line, final QName qname, final SchemaPath schemaPath) {
434 final LeafListSchemaNodeBuilder builder = new LeafListSchemaNodeBuilder(name, line, qname, schemaPath);
436 Builder parent = getActualNode();
437 builder.setParent(parent);
438 addChildToParent(parent, builder, qname.getLocalName());
443 public GroupingBuilder addGrouping(final int line, final QName qname, final SchemaPath path) {
444 final GroupingBuilder builder = new GroupingBuilderImpl(name, line, qname, path);
446 Builder parent = getActualNode();
447 builder.setParent(parent);
449 String groupingName = qname.getLocalName();
450 if (parent.equals(this)) {
451 for (GroupingBuilder addedGrouping : addedGroupings) {
452 if (addedGrouping.getQName().getLocalName().equals(groupingName)) {
453 raiseYangParserException("", "Grouping", groupingName, line, addedGrouping.getLine());
456 addedGroupings.add(builder);
458 if (parent instanceof DataNodeContainerBuilder) {
459 DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parent;
460 for (GroupingBuilder addedGrouping : parentNode.getGroupingBuilders()) {
461 if (addedGrouping.getQName().getLocalName().equals(groupingName)) {
462 raiseYangParserException("", "Grouping", groupingName, line, addedGrouping.getLine());
465 parentNode.addGrouping(builder);
466 } else if (parent instanceof RpcDefinitionBuilder) {
467 RpcDefinitionBuilder parentNode = (RpcDefinitionBuilder) parent;
468 for (GroupingBuilder child : parentNode.getGroupings()) {
469 if (child.getQName().getLocalName().equals(groupingName)) {
470 raiseYangParserException("", "Grouping", groupingName, line, child.getLine());
473 parentNode.addGrouping(builder);
475 throw new YangParseException(name, line, "Unresolved parent of grouping " + groupingName);
479 allGroupings.add(builder);
483 public AugmentationSchemaBuilder addAugment(final int line, final String augmentTargetStr) {
484 final AugmentationSchemaBuilder builder = new AugmentationSchemaBuilderImpl(name, line, augmentTargetStr);
486 Builder parent = getActualNode();
487 builder.setParent(parent);
489 if (parent.equals(this)) {
490 // augment can be declared only under 'module' ...
491 if (!(augmentTargetStr.startsWith("/"))) {
492 throw new YangParseException(
495 "If the 'augment' statement is on the top level in a module, the absolute form of a schema node identifier MUST be used.");
497 augmentBuilders.add(builder);
499 // ... or 'uses' statement
500 if (parent instanceof UsesNodeBuilder) {
501 if (augmentTargetStr.startsWith("/")) {
502 throw new YangParseException(name, line,
503 "If 'augment' statement is a substatement to the 'uses' statement, it cannot contain absolute path ("
504 + augmentTargetStr + ")");
506 ((UsesNodeBuilder) parent).addAugment(builder);
508 throw new YangParseException(name, line, "Augment can be declared only under module or uses statement.");
511 allAugments.add(builder);
517 public void addUsesNode(UsesNodeBuilder usesBuilder) {
518 addedUsesNodes.add(usesBuilder);
519 allUsesNodes.add(usesBuilder);
522 public UsesNodeBuilder addUsesNode(final int line, final String groupingPathStr) {
523 final UsesNodeBuilder usesBuilder = new UsesNodeBuilderImpl(name, line, groupingPathStr);
525 Builder parent = getActualNode();
526 usesBuilder.setParent(parent);
528 if (parent.equals(this)) {
529 addedUsesNodes.add(usesBuilder);
531 if (!(parent instanceof DataNodeContainerBuilder)) {
532 throw new YangParseException(name, line, "Unresolved parent of uses '" + groupingPathStr + "'.");
534 ((DataNodeContainerBuilder) parent).addUsesNode(usesBuilder);
536 if (parent instanceof AugmentationSchemaBuilder) {
537 usesBuilder.setAugmenting(true);
540 allUsesNodes.add(usesBuilder);
544 public void addRefine(final RefineHolder refine) {
545 final Builder parent = getActualNode();
546 if (!(parent instanceof UsesNodeBuilder)) {
547 throw new YangParseException(name, refine.getLine(), "refine can be defined only in uses statement");
549 ((UsesNodeBuilder) parent).addRefine(refine);
550 refine.setParent(parent);
553 public RpcDefinitionBuilder addRpc(final int line, final QName qname, final SchemaPath path) {
554 Builder parent = getActualNode();
555 if (!(parent.equals(this))) {
556 throw new YangParseException(name, line, "rpc can be defined only in module or submodule");
559 final RpcDefinitionBuilder rpcBuilder = new RpcDefinitionBuilder(name, line, qname, path);
560 rpcBuilder.setParent(parent);
562 String rpcName = qname.getLocalName();
563 for (RpcDefinitionBuilder rpc : addedRpcs) {
564 if (rpc.getQName().getLocalName().equals(rpcName)) {
565 raiseYangParserException("", "rpc", rpcName, line, rpc.getLine());
568 for (DataSchemaNodeBuilder addedChild : addedChildNodes) {
569 if (addedChild.getQName().getLocalName().equals(rpcName)) {
570 raiseYangParserException("rpc", "node", rpcName, line, addedChild.getLine());
573 for (NotificationBuilder addedNotification : addedNotifications) {
574 if (addedNotification.getQName().getLocalName().equals(rpcName)) {
575 raiseYangParserException("rpc", "notification", rpcName, line, addedNotification.getLine());
578 addedRpcs.add(rpcBuilder);
582 public ContainerSchemaNodeBuilder addRpcInput(final int line, final QName qname, final SchemaPath schemaPath) {
583 final Builder parent = getActualNode();
584 if (!(parent instanceof RpcDefinitionBuilder)) {
585 throw new YangParseException(name, line, "input can be defined only in rpc statement");
587 final RpcDefinitionBuilder rpc = (RpcDefinitionBuilder) parent;
589 final ContainerSchemaNodeBuilder inputBuilder = new ContainerSchemaNodeBuilder(name, line, qname, schemaPath);
590 inputBuilder.setParent(rpc);
592 rpc.setInput(inputBuilder);
596 public ContainerSchemaNodeBuilder addRpcOutput(final SchemaPath schemaPath, final QName qname, final int line) {
597 final Builder parent = getActualNode();
598 if (!(parent instanceof RpcDefinitionBuilder)) {
599 throw new YangParseException(name, line, "output can be defined only in rpc statement");
601 final RpcDefinitionBuilder rpc = (RpcDefinitionBuilder) parent;
603 final ContainerSchemaNodeBuilder outputBuilder = new ContainerSchemaNodeBuilder(name, line, qname, schemaPath);
604 outputBuilder.setParent(rpc);
606 rpc.setOutput(outputBuilder);
607 return outputBuilder;
610 public void addNotification(NotificationDefinition notification) {
611 notifications.add(notification);
614 public NotificationBuilder addNotification(final int line, final QName qname, final SchemaPath path) {
615 final Builder parent = getActualNode();
616 if (!(parent.equals(this))) {
617 throw new YangParseException(name, line, "notification can be defined only in module or submodule");
620 String notificationName = qname.getLocalName();
621 for (NotificationBuilder nb : addedNotifications) {
622 if (nb.getQName().equals(qname)) {
623 raiseYangParserException("", "notification", notificationName, line, nb.getLine());
626 for (RpcDefinitionBuilder rpc : addedRpcs) {
627 if (rpc.getQName().getLocalName().equals(notificationName)) {
628 raiseYangParserException("notification", "rpc", notificationName, line, rpc.getLine());
631 for (DataSchemaNodeBuilder addedChild : addedChildNodes) {
632 if (addedChild.getQName().getLocalName().equals(notificationName)) {
633 raiseYangParserException("notification", "node", notificationName, line, addedChild.getLine());
637 final NotificationBuilder builder = new NotificationBuilder(name, line, qname, path);
638 builder.setParent(parent);
639 addedNotifications.add(builder);
644 public FeatureBuilder addFeature(final int line, final QName qname, final SchemaPath path) {
645 Builder parent = getActualNode();
646 if (!(parent.equals(this))) {
647 throw new YangParseException(name, line, "feature can be defined only in module or submodule");
650 final FeatureBuilder builder = new FeatureBuilder(name, line, qname, path);
651 builder.setParent(parent);
653 String featureName = qname.getLocalName();
654 for (FeatureBuilder addedFeature : addedFeatures) {
655 if (addedFeature.getQName().getLocalName().equals(featureName)) {
656 raiseYangParserException("", "feature", featureName, line, addedFeature.getLine());
659 addedFeatures.add(builder);
663 public ChoiceBuilder addChoice(final int line, final QName qname, final SchemaPath path) {
664 final ChoiceBuilder builder = new ChoiceBuilder(name, line, qname, path);
666 Builder parent = getActualNode();
667 builder.setParent(parent);
668 addChildToParent(parent, builder, qname.getLocalName());
673 public ChoiceCaseBuilder addCase(final int line, final QName qname, final SchemaPath path) {
674 Builder parent = getActualNode();
675 if (parent == null || parent.equals(this)) {
676 throw new YangParseException(name, line, "'case' parent not found");
679 final ChoiceCaseBuilder builder = new ChoiceCaseBuilder(name, line, qname, path);
680 builder.setParent(parent);
682 if (parent instanceof ChoiceBuilder) {
683 ((ChoiceBuilder) parent).addCase(builder);
684 } else if (parent instanceof AugmentationSchemaBuilder) {
685 ((AugmentationSchemaBuilder) parent).addChildNode(builder);
687 throw new YangParseException(name, line, "Unresolved parent of 'case' " + qname.getLocalName());
693 public AnyXmlBuilder addAnyXml(final int line, final QName qname, final SchemaPath schemaPath) {
694 final AnyXmlBuilder builder = new AnyXmlBuilder(name, line, qname, schemaPath);
696 Builder parent = getActualNode();
697 builder.setParent(parent);
698 addChildToParent(parent, builder, qname.getLocalName());
704 public void addTypedef(TypeDefinitionBuilder typedefBuilder) {
705 String nodeName = typedefBuilder.getQName().getLocalName();
706 for (TypeDefinitionBuilder tdb : addedTypedefs) {
707 if (tdb.getQName().getLocalName().equals(nodeName)) {
708 raiseYangParserException("", "typedef", nodeName, typedefBuilder.getLine(), tdb.getLine());
711 addedTypedefs.add(typedefBuilder);
714 public TypeDefinitionBuilderImpl addTypedef(final int line, final QName qname, final SchemaPath path) {
715 final TypeDefinitionBuilderImpl builder = new TypeDefinitionBuilderImpl(name, line, qname, path);
717 Builder parent = getActualNode();
718 builder.setParent(parent);
720 String typedefName = qname.getLocalName();
721 if (parent.equals(this)) {
722 for (TypeDefinitionBuilder tdb : addedTypedefs) {
723 if (tdb.getQName().getLocalName().equals(typedefName)) {
724 raiseYangParserException("", "typedef", typedefName, line, tdb.getLine());
727 addedTypedefs.add(builder);
729 if (parent instanceof DataNodeContainerBuilder) {
730 DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parent;
731 for (TypeDefinitionBuilder child : parentNode.getTypeDefinitionBuilders()) {
732 if (child.getQName().getLocalName().equals(typedefName)) {
733 raiseYangParserException("", "typedef", typedefName, line, child.getLine());
736 parentNode.addTypedef(builder);
737 } else if (parent instanceof RpcDefinitionBuilder) {
738 RpcDefinitionBuilder rpcParent = (RpcDefinitionBuilder) parent;
739 for (TypeDefinitionBuilder tdb : rpcParent.getTypeDefinitions()) {
740 if (tdb.getQName().getLocalName().equals(builder.getQName().getLocalName())) {
741 raiseYangParserException("", "typedef", typedefName, line, tdb.getLine());
744 rpcParent.addTypedef(builder);
746 throw new YangParseException(name, line, "Unresolved parent of typedef " + typedefName);
753 public void setType(final TypeDefinition<?> type) {
754 Builder parent = getActualNode();
755 if (!(parent instanceof TypeAwareBuilder)) {
756 throw new YangParseException("Failed to set type '" + type.getQName().getLocalName()
757 + "'. Invalid parent node: " + parent);
759 ((TypeAwareBuilder) parent).setType(type);
762 public UnionTypeBuilder addUnionType(final int line, final URI namespace, final Date revision) {
763 final Builder parent = getActualNode();
764 if (parent == null) {
765 throw new YangParseException(name, line, "Unresolved parent of union type");
767 final UnionTypeBuilder union = new UnionTypeBuilder(name, line);
768 if (parent instanceof TypeAwareBuilder) {
769 ((TypeAwareBuilder) parent).setTypedef(union);
772 throw new YangParseException(name, line, "Invalid parent of union type.");
777 public void addIdentityrefType(final int line, final SchemaPath schemaPath, final String baseString) {
778 final IdentityrefTypeBuilder identityref = new IdentityrefTypeBuilder(name, line, baseString, schemaPath);
780 final Builder parent = getActualNode();
781 if (parent == null) {
782 throw new YangParseException(name, line, "Unresolved parent of identityref type.");
784 if (parent instanceof TypeAwareBuilder) {
785 final TypeAwareBuilder typeParent = (TypeAwareBuilder) parent;
786 typeParent.setTypedef(identityref);
787 dirtyNodes.add(typeParent);
789 throw new YangParseException(name, line, "Invalid parent of identityref type.");
794 public DeviationBuilder addDeviation(final int line, final String targetPath) {
795 Builder parent = getActualNode();
796 if (!(parent.equals(this))) {
797 throw new YangParseException(name, line, "deviation can be defined only in module or submodule");
800 final DeviationBuilder builder = new DeviationBuilder(name, line, targetPath);
801 builder.setParent(parent);
802 deviationBuilders.add(builder);
806 public IdentitySchemaNodeBuilder addIdentity(final QName qname, final int line, final SchemaPath path) {
807 Builder parent = getActualNode();
808 if (!(parent.equals(this))) {
809 throw new YangParseException(name, line, "identity can be defined only in module or submodule");
811 String identityName = qname.getLocalName();
812 for (IdentitySchemaNodeBuilder idBuilder : addedIdentities) {
813 if (idBuilder.getQName().equals(qname)) {
814 raiseYangParserException("", "identity", identityName, line, idBuilder.getLine());
818 final IdentitySchemaNodeBuilder builder = new IdentitySchemaNodeBuilder(name, line, qname, path);
819 builder.setParent(parent);
820 addedIdentities.add(builder);
825 public void addUnknownNodeBuilder(final UnknownSchemaNodeBuilder builder) {
826 addedUnknownNodes.add(builder);
827 allUnknownNodes.add(builder);
830 public UnknownSchemaNodeBuilder addUnknownSchemaNode(final int line, final QName qname, final SchemaPath path) {
831 final Builder parent = getActualNode();
832 final UnknownSchemaNodeBuilder builder = new UnknownSchemaNodeBuilder(name, line, qname, path);
833 builder.setParent(parent);
834 allUnknownNodes.add(builder);
836 if (parent.equals(this)) {
837 addedUnknownNodes.add(builder);
839 if (parent instanceof SchemaNodeBuilder) {
840 ((SchemaNodeBuilder) parent).addUnknownNodeBuilder(builder);
841 } else if (parent instanceof DataNodeContainerBuilder) {
842 ((DataNodeContainerBuilder) parent).addUnknownNodeBuilder(builder);
843 } else if (parent instanceof RefineHolder) {
844 ((RefineHolder) parent).addUnknownNodeBuilder(builder);
846 throw new YangParseException(name, line, "Unresolved parent of unknown node '" + qname.getLocalName()
854 public Set<RpcDefinition> getRpcs() {
858 public Set<RpcDefinitionBuilder> getAddedRpcs() {
862 public Set<NotificationDefinition> getNotifications() {
863 return notifications;
866 public Set<NotificationBuilder> getAddedNotifications() {
867 return addedNotifications;
871 public String toString() {
872 return "module " + name;
875 private final class ModuleImpl implements Module {
876 private URI namespace;
877 private final String name;
878 private Date revision;
879 private String prefix;
880 private String yangVersion;
881 private String description;
882 private String reference;
883 private String organization;
884 private String contact;
885 private final Set<ModuleImport> imports = new HashSet<>();
886 private final Set<FeatureDefinition> features = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
887 private final Set<TypeDefinition<?>> typeDefinitions = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
888 private final Set<NotificationDefinition> notifications = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
889 private final Set<AugmentationSchema> augmentations = new HashSet<>();
890 private final Set<RpcDefinition> rpcs = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
891 private final Set<Deviation> deviations = new HashSet<>();
892 private final Set<DataSchemaNode> childNodes = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
893 private final Set<GroupingDefinition> groupings = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
894 private final Set<UsesNode> uses = new HashSet<>();
895 private final List<ExtensionDefinition> extensionNodes = new ArrayList<>();
896 private final Set<IdentitySchemaNode> identities = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
897 private final List<UnknownSchemaNode> unknownNodes = new ArrayList<>();
899 private ModuleImpl(String name) {
904 public URI getNamespace() {
908 private void setNamespace(URI namespace) {
909 this.namespace = namespace;
913 public String getName() {
918 public Date getRevision() {
922 private void setRevision(Date revision) {
923 this.revision = revision;
927 public String getPrefix() {
931 private void setPrefix(String prefix) {
932 this.prefix = prefix;
936 public String getYangVersion() {
940 private void setYangVersion(String yangVersion) {
941 this.yangVersion = yangVersion;
945 public String getDescription() {
949 private void setDescription(String description) {
950 this.description = description;
954 public String getReference() {
958 private void setReference(String reference) {
959 this.reference = reference;
963 public String getOrganization() {
967 private void setOrganization(String organization) {
968 this.organization = organization;
972 public String getContact() {
976 private void setContact(String contact) {
977 this.contact = contact;
981 public Set<ModuleImport> getImports() {
985 private void setImports(Set<ModuleImport> imports) {
986 if (imports != null) {
987 this.imports.addAll(imports);
992 public Set<FeatureDefinition> getFeatures() {
996 private void setFeatures(Set<FeatureDefinition> features) {
997 if (features != null) {
998 this.features.addAll(features);
1003 public Set<TypeDefinition<?>> getTypeDefinitions() {
1004 return typeDefinitions;
1007 private void setTypeDefinitions(Set<TypeDefinition<?>> typeDefinitions) {
1008 if (typeDefinitions != null) {
1009 this.typeDefinitions.addAll(typeDefinitions);
1014 public Set<NotificationDefinition> getNotifications() {
1015 return notifications;
1018 private void setNotifications(Set<NotificationDefinition> notifications) {
1019 if (notifications != null) {
1020 this.notifications.addAll(notifications);
1025 public Set<AugmentationSchema> getAugmentations() {
1026 return augmentations;
1029 private void setAugmentations(Set<AugmentationSchema> augmentations) {
1030 if (augmentations != null) {
1031 this.augmentations.addAll(augmentations);
1036 public Set<RpcDefinition> getRpcs() {
1040 private void setRpcs(Set<RpcDefinition> rpcs) {
1042 this.rpcs.addAll(rpcs);
1047 public Set<Deviation> getDeviations() {
1051 private void setDeviations(Set<Deviation> deviations) {
1052 if (deviations != null) {
1053 this.deviations.addAll(deviations);
1058 public Set<DataSchemaNode> getChildNodes() {
1059 return Collections.unmodifiableSet(childNodes);
1062 private void addChildNodes(Set<DataSchemaNode> childNodes) {
1063 if (childNodes != null) {
1064 this.childNodes.addAll(childNodes);
1069 public Set<GroupingDefinition> getGroupings() {
1073 private void setGroupings(Set<GroupingDefinition> groupings) {
1074 if (groupings != null) {
1075 this.groupings.addAll(groupings);
1080 public Set<UsesNode> getUses() {
1084 private void setUses(Set<UsesNode> uses) {
1086 this.uses.addAll(uses);
1091 public List<ExtensionDefinition> getExtensionSchemaNodes() {
1092 Collections.sort(extensionNodes, Comparators.SCHEMA_NODE_COMP);
1093 return extensionNodes;
1096 private void setExtensionSchemaNodes(final List<ExtensionDefinition> extensionNodes) {
1097 if (extensionNodes != null) {
1098 this.extensionNodes.addAll(extensionNodes);
1103 public Set<IdentitySchemaNode> getIdentities() {
1107 private void setIdentities(final Set<IdentitySchemaNode> identities) {
1108 if (identities != null) {
1109 this.identities.addAll(identities);
1114 public List<UnknownSchemaNode> getUnknownSchemaNodes() {
1115 return unknownNodes;
1118 private void setUnknownSchemaNodes(final List<UnknownSchemaNode> unknownNodes) {
1119 if (unknownNodes != null) {
1120 this.unknownNodes.addAll(unknownNodes);
1125 public DataSchemaNode getDataChildByName(QName name) {
1126 return getChildNode(childNodes, name);
1130 public DataSchemaNode getDataChildByName(String name) {
1131 return getChildNode(childNodes, name);
1135 public int hashCode() {
1136 final int prime = 31;
1138 result = prime * result + ((namespace == null) ? 0 : namespace.hashCode());
1139 result = prime * result + ((name == null) ? 0 : name.hashCode());
1140 result = prime * result + ((revision == null) ? 0 : revision.hashCode());
1141 result = prime * result + ((prefix == null) ? 0 : prefix.hashCode());
1142 result = prime * result + ((yangVersion == null) ? 0 : yangVersion.hashCode());
1147 public boolean equals(Object obj) {
1154 if (getClass() != obj.getClass()) {
1157 ModuleImpl other = (ModuleImpl) obj;
1158 if (namespace == null) {
1159 if (other.namespace != null) {
1162 } else if (!namespace.equals(other.namespace)) {
1166 if (other.name != null) {
1169 } else if (!name.equals(other.name)) {
1172 if (revision == null) {
1173 if (other.revision != null) {
1176 } else if (!revision.equals(other.revision)) {
1179 if (prefix == null) {
1180 if (other.prefix != null) {
1183 } else if (!prefix.equals(other.prefix)) {
1186 if (yangVersion == null) {
1187 if (other.yangVersion != null) {
1190 } else if (!yangVersion.equals(other.yangVersion)) {
1197 public String toString() {
1198 StringBuilder sb = new StringBuilder(ModuleImpl.class.getSimpleName());
1200 sb.append("name=" + name);
1201 sb.append(", namespace=" + namespace);
1202 sb.append(", revision=" + revision);
1203 sb.append(", prefix=" + prefix);
1204 sb.append(", yangVersion=" + yangVersion);
1206 return sb.toString();
1211 * Add child to parent. Method checks for duplicates and add given child
1212 * node to parent. If node with same name is found, throws exception. If
1213 * parent is null, child node will be added directly to module.
1219 private void addChildToParent(final Builder parent, final DataSchemaNodeBuilder child, final String childName) {
1220 final int lineNum = child.getLine();
1221 if (parent.equals(this)) {
1222 addChildToModule(child, childName, lineNum);
1224 addChildToSubnodeOfModule(parent, child, childName, lineNum);
1229 * Adds child node <code>child</code> to the set of nodes child nodes.
1231 * The method reduces the complexity of the method
1232 * {@link #addChildToParent(Builder, DataSchemaNodeBuilder, String)
1233 * addChildToParent}.
1236 * data schema node builder for child node
1238 * string with name of child node
1240 * line number in YANG file where is the node with the name equal
1241 * to <code>childName</code> is defined
1243 private void addChildToModule(final DataSchemaNodeBuilder child, final String childName, final int lineNum) {
1244 // if parent == null => node is defined under module
1245 // All leafs, leaf-lists, lists, containers, choices, rpcs,
1246 // notifications, and anyxmls defined within a parent node or at the
1247 // top level of the module or its submodules share the same
1248 // identifier namespace.
1249 for (DataSchemaNodeBuilder childNode : addedChildNodes) {
1250 if (childNode.getQName().getLocalName().equals(childName)) {
1251 raiseYangParserException("'" + child + "'", "node", childName, lineNum, childNode.getLine());
1254 for (RpcDefinitionBuilder rpc : addedRpcs) {
1255 if (rpc.getQName().getLocalName().equals(childName)) {
1256 raiseYangParserException("'" + child + "'", "rpc", childName, lineNum, rpc.getLine());
1259 for (NotificationBuilder notification : addedNotifications) {
1260 if (notification.getQName().getLocalName().equals(childName)) {
1261 raiseYangParserException("'" + child + "'", "notification", childName, lineNum, notification.getLine());
1264 addedChildNodes.add(child);
1268 * Adds child node <code>child</code> to the group of child nodes of the
1269 * <code>parent</code>
1271 * The method reduces the complexity of the method
1272 * {@link #addChildToParent(Builder, DataSchemaNodeBuilder, String)
1273 * addChildToParent}. *
1276 * builder of node which is parent for <code>child</code>
1278 * data schema node builder for child node
1280 * string with name of child node
1282 * line number in YANG file where is the node with the name equal
1283 * to <code>childName</code> is defined
1285 private void addChildToSubnodeOfModule(final Builder parent, final DataSchemaNodeBuilder child,
1286 final String childName, final int lineNum) {
1287 // no need for checking rpc and notification because they can be
1288 // defined only under module or submodule
1289 if (parent instanceof DataNodeContainerBuilder) {
1290 DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parent;
1291 for (DataSchemaNodeBuilder childNode : parentNode.getChildNodeBuilders()) {
1292 if (childNode.getQName().getLocalName().equals(childName)) {
1293 raiseYangParserException("'" + child + "'", "node", childName, lineNum, childNode.getLine());
1296 parentNode.addChildNode(child);
1297 } else if (parent instanceof ChoiceBuilder) {
1298 ChoiceBuilder parentNode = (ChoiceBuilder) parent;
1299 for (ChoiceCaseBuilder caseBuilder : parentNode.getCases()) {
1300 if (caseBuilder.getQName().getLocalName().equals(childName)) {
1301 raiseYangParserException("'" + child + "'", "node", childName, lineNum, caseBuilder.getLine());
1304 parentNode.addCase(child);
1306 throw new YangParseException(name, lineNum, "Unresolved parent of node '" + childName + "'.");
1310 private ModuleImport createModuleImport(final String moduleName, final Date revision, final String prefix) {
1311 final ModuleImport moduleImport = new ModuleImportImpl(moduleName, revision, prefix);
1312 return moduleImport;
1315 private void raiseYangParserException(final String cantAddType, final String type, final String name,
1316 final int currentLine, final int duplicateLine) {
1318 StringBuilder msgPrefix = new StringBuilder("");
1319 if (cantAddType != null && !cantAddType.isEmpty()) {
1320 msgPrefix.append("Can not add ");
1321 msgPrefix.append(cantAddType);
1322 msgPrefix.append(": ");
1325 String msg = String.format("%s%s with same name '%s' already declared at line %d.", msgPrefix, type, name,
1327 throw new YangParseException(moduleName, currentLine, msg);
1331 public int hashCode() {
1332 final int prime = 31;
1334 result = prime * result + ((name == null) ? 0 : name.hashCode());
1335 result = prime * result + ((namespace == null) ? 0 : namespace.hashCode());
1336 result = prime * result + ((revision == null) ? 0 : revision.hashCode());
1337 result = prime * result + ((prefix == null) ? 0 : prefix.hashCode());
1343 public boolean equals(Object obj) {
1350 if (getClass() != obj.getClass()) {
1353 ModuleBuilder other = (ModuleBuilder) obj;
1355 if (other.name != null) {
1358 } else if (!name.equals(other.name)) {
1361 if (namespace == null) {
1362 if (other.namespace != null) {
1365 } else if (!namespace.equals(other.namespace)) {
1368 if (prefix == null) {
1369 if (other.prefix != null) {
1372 } else if (!prefix.equals(other.prefix)) {
1375 if (revision == null) {
1376 if (other.revision != null) {
1379 } else if (!revision.equals(other.revision)) {