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
9 package org.opendaylight.yangtools.yang.parser.builder.impl;
11 import com.google.common.base.Charsets;
12 import com.google.common.base.Preconditions;
13 import com.google.common.io.ByteSource;
14 import java.io.IOException;
16 import java.util.ArrayList;
17 import java.util.Collections;
18 import java.util.Date;
19 import java.util.Deque;
20 import java.util.HashMap;
21 import java.util.HashSet;
22 import java.util.LinkedHashSet;
23 import java.util.LinkedList;
24 import java.util.List;
26 import java.util.Objects;
28 import java.util.TreeSet;
29 import org.opendaylight.yangtools.yang.common.QName;
30 import org.opendaylight.yangtools.yang.common.QNameModule;
31 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
32 import org.opendaylight.yangtools.yang.model.api.Deviation;
33 import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition;
34 import org.opendaylight.yangtools.yang.model.api.FeatureDefinition;
35 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
36 import org.opendaylight.yangtools.yang.model.api.Module;
37 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
38 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
39 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
40 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
41 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
42 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
43 import org.opendaylight.yangtools.yang.model.util.ModuleImportImpl;
44 import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationSchemaBuilder;
45 import org.opendaylight.yangtools.yang.parser.builder.api.Builder;
46 import org.opendaylight.yangtools.yang.parser.builder.api.DataNodeContainerBuilder;
47 import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
48 import org.opendaylight.yangtools.yang.parser.builder.api.DocumentedNodeBuilder;
49 import org.opendaylight.yangtools.yang.parser.builder.api.ExtensionBuilder;
50 import org.opendaylight.yangtools.yang.parser.builder.api.GroupingBuilder;
51 import org.opendaylight.yangtools.yang.parser.builder.api.SchemaNodeBuilder;
52 import org.opendaylight.yangtools.yang.parser.builder.api.TypeAwareBuilder;
53 import org.opendaylight.yangtools.yang.parser.builder.api.TypeDefinitionBuilder;
54 import org.opendaylight.yangtools.yang.parser.builder.api.UnknownSchemaNodeBuilder;
55 import org.opendaylight.yangtools.yang.parser.builder.api.UsesNodeBuilder;
56 import org.opendaylight.yangtools.yang.parser.builder.util.AbstractDocumentedDataNodeContainerBuilder;
57 import org.opendaylight.yangtools.yang.parser.builder.util.Comparators;
58 import org.opendaylight.yangtools.yang.parser.util.YangParseException;
61 * Builder of Module object. If this module is dependent on external
62 * module/modules, these dependencies must be resolved before module is built,
63 * otherwise result may not be valid.
65 public class ModuleBuilder extends AbstractDocumentedDataNodeContainerBuilder implements DocumentedNodeBuilder {
66 private static final QNameModule EMPTY_QNAME_MODULE = QNameModule.cachedReference(QNameModule.create(null, null));
67 private static final String GROUPING_STR = "Grouping";
68 private static final String TYPEDEF_STR = "typedef";
69 private ModuleImpl instance;
70 private final String name;
71 private final String sourcePath;
72 private static final SchemaPath SCHEMA_PATH = SchemaPath.create(Collections.<QName> emptyList(), true);
73 private String prefix;
74 private QNameModule qnameModule = EMPTY_QNAME_MODULE;
76 private final boolean submodule;
77 private String belongsTo;
78 private ModuleBuilder parent;
80 private final Deque<Builder> actualPath = new LinkedList<>();
81 private final Set<TypeAwareBuilder> dirtyNodes = new HashSet<>();
83 final Map<String, ModuleImport> imports = new HashMap<>();
84 final Map<String, ModuleBuilder> importedModules = new HashMap<>();
86 final Set<ModuleBuilder> addedSubmodules = new HashSet<>();
87 final Set<Module> submodules = new HashSet<>();
88 final Map<String, Date> includedModules = new HashMap<>();
90 private final Set<AugmentationSchema> augments = new LinkedHashSet<>();
91 private final List<AugmentationSchemaBuilder> augmentBuilders = new ArrayList<>();
92 private final List<AugmentationSchemaBuilder> allAugments = new ArrayList<>();
94 private final List<GroupingBuilder> allGroupings = new ArrayList<>();
96 private final List<UsesNodeBuilder> allUsesNodes = new ArrayList<>();
98 private final Set<RpcDefinition> rpcs = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
99 private final Set<RpcDefinitionBuilder> addedRpcs = new HashSet<>();
101 private final Set<NotificationDefinition> notifications = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
102 private final Set<NotificationBuilder> addedNotifications = new HashSet<>();
104 private final Set<IdentitySchemaNode> identities = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
105 private final Set<IdentitySchemaNodeBuilder> addedIdentities = new HashSet<>();
107 private final Set<FeatureDefinition> features = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
108 private final Set<FeatureBuilder> addedFeatures = new HashSet<>();
110 private final Set<Deviation> deviations = new HashSet<>();
111 private final Set<DeviationBuilder> deviationBuilders = new HashSet<>();
113 private final List<ExtensionDefinition> extensions = new ArrayList<>();
114 private final List<ExtensionBuilder> addedExtensions = new ArrayList<>();
116 private final List<UnknownSchemaNodeBuilder> allUnknownNodes = new ArrayList<>();
118 private final List<ListSchemaNodeBuilder> allLists = new ArrayList<>();
120 private String source;
121 private String yangVersion;
122 private String organization;
123 private String contact;
125 public ModuleBuilder(final String name, final String sourcePath) {
126 this(name, false, sourcePath);
129 public ModuleBuilder(final String name, final boolean submodule, final String sourcePath) {
130 super(name, 0, null);
132 this.sourcePath = sourcePath;
133 this.submodule = submodule;
134 actualPath.push(this);//FIXME: this escapes constructor
137 public ModuleBuilder(final Module base) {
138 super(base.getName(), 0, QName.create(base.getQNameModule(), base.getName()),
140 this.name = base.getName();
141 this.sourcePath = base.getModuleSourcePath();
144 yangVersion = base.getYangVersion();
145 actualPath.push(this);//FIXME: this escapes constructor
146 prefix = base.getPrefix();
147 qnameModule = base.getQNameModule();
149 augments.addAll(base.getAugmentations());
150 rpcs.addAll(base.getRpcs());
151 notifications.addAll(base.getNotifications());
153 for (IdentitySchemaNode identityNode : base.getIdentities()) {
154 addedIdentities.add(new IdentitySchemaNodeBuilder(name, identityNode));
157 features.addAll(base.getFeatures());
158 deviations.addAll(base.getDeviations());
159 extensions.addAll(base.getExtensionSchemaNodes());
160 unknownNodes.addAll(base.getUnknownSchemaNodes());
161 source = base.getSource();
165 protected String getStatementName() {
170 * Build new Module object based on this builder.
173 public Module build() {
174 if(instance != null) {
181 for (ModuleBuilder submodule : addedSubmodules) {
182 submodules.add(submodule.build());
186 for (FeatureBuilder fb : addedFeatures) {
187 features.add(fb.build());
191 for (NotificationBuilder entry : addedNotifications) {
192 notifications.add(entry.build());
196 for (AugmentationSchemaBuilder builder : augmentBuilders) {
197 augments.add(builder.build());
201 for (RpcDefinitionBuilder rpc : addedRpcs) {
202 rpcs.add(rpc.build());
206 for (DeviationBuilder entry : deviationBuilders) {
207 deviations.add(entry.build());
211 for (ExtensionBuilder eb : addedExtensions) {
212 extensions.add(eb.build());
214 Collections.sort(extensions, Comparators.SCHEMA_NODE_COMP);
218 for (IdentitySchemaNodeBuilder id : addedIdentities) {
219 identities.add(id.build());
223 for (UnknownSchemaNodeBuilder unb : addedUnknownNodes) {
224 unknownNodes.add(unb.build());
226 Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
228 instance = new ModuleImpl(name, sourcePath, this);
232 public String getModuleSourcePath() {
237 public ModuleBuilder getParent() {
241 public void setParent(final ModuleBuilder parent) {
242 this.parent = parent;
246 public void setParent(final Builder parent) {
247 throw new YangParseException(name, 0, "Can not set parent to module");
251 public SchemaPath getPath() {
255 public void enterNode(final Builder node) {
256 actualPath.push(node);
259 public void exitNode() {
263 public Builder getActualNode() {
264 if (actualPath.isEmpty()) {
267 return actualPath.peekFirst();
271 public Set<TypeAwareBuilder> getDirtyNodes() {
275 public Set<AugmentationSchema> getAugments() {
279 public List<AugmentationSchemaBuilder> getAugmentBuilders() {
280 return augmentBuilders;
283 public List<AugmentationSchemaBuilder> getAllAugments() {
287 public Set<IdentitySchemaNode> getIdentities() {
291 public Set<IdentitySchemaNodeBuilder> getAddedIdentities() {
292 return addedIdentities;
295 public Set<FeatureDefinition> getFeatures() {
299 public Set<FeatureBuilder> getAddedFeatures() {
300 return addedFeatures;
303 public List<GroupingBuilder> getAllGroupings() {
307 public List<UsesNodeBuilder> getAllUsesNodes() {
311 public Set<Deviation> getDeviations() {
315 public Set<DeviationBuilder> getDeviationBuilders() {
316 return deviationBuilders;
319 public List<ExtensionDefinition> getExtensions() {
323 public List<ExtensionBuilder> getAddedExtensions() {
324 return addedExtensions;
327 public List<UnknownSchemaNodeBuilder> getAllUnknownNodes() {
328 return allUnknownNodes;
331 public List<ListSchemaNodeBuilder> getAllLists() {
335 public String getName() {
339 public URI getNamespace() {
340 return qnameModule.getNamespace();
343 public QNameModule getQNameModule() {
347 public void setQNameModule(final QNameModule qnameModule) {
348 this.qnameModule = Preconditions.checkNotNull(qnameModule);
351 public void setNamespace(final URI namespace) {
352 this.qnameModule = QNameModule.cachedReference(QNameModule.create(namespace, qnameModule.getRevision()));
355 public String getPrefix() {
359 public Date getRevision() {
360 return qnameModule.getRevision();
363 public ModuleImport getImport(final String prefix) {
364 return imports.get(prefix);
367 public Map<String, ModuleImport> getImports() {
371 public ModuleBuilder getImportedModule(final String prefix) {
372 return importedModules.get(prefix);
375 public void addImportedModule(final String prefix, final ModuleBuilder module) {
377 importedModules.put(prefix, module);
380 public Map<String, Date> getIncludedModules() {
381 return includedModules;
384 public void addInclude(final String name, final Date revision) {
385 includedModules.put(name, revision);
388 public void addSubmodule(final ModuleBuilder submodule) {
389 addedSubmodules.add(submodule);
392 protected String getSource() {
396 public boolean isSubmodule() {
400 public String getBelongsTo() {
404 public void setBelongsTo(final String belongsTo) {
405 this.belongsTo = belongsTo;
408 public void markActualNodeDirty() {
409 final TypeAwareBuilder nodeBuilder = (TypeAwareBuilder) getActualNode();
410 dirtyNodes.add(nodeBuilder);
413 public void setRevision(final Date revision) {
414 this.qnameModule = QNameModule.cachedReference(QNameModule.create(qnameModule.getNamespace(), revision));
417 public void setPrefix(final String prefix) {
418 this.prefix = prefix;
421 public void setYangVersion(final String yangVersion) {
422 this.yangVersion = yangVersion;
425 public void setOrganization(final String organization) {
426 this.organization = organization;
429 public void setContact(final String contact) {
430 this.contact = contact;
433 public void addModuleImport(final String moduleName, final Date revision, final String prefix) {
436 final ModuleImport moduleImport = new ModuleImportImpl(moduleName, revision, prefix);
437 imports.put(prefix, moduleImport);
440 private void checkPrefix(final String prefix) {
441 if (prefix == null || prefix.isEmpty()) {
442 throw new IllegalArgumentException("Cannot add imported module with undefined prefix");
444 if (prefix.equals(this.prefix)) {
445 throw new IllegalArgumentException("Cannot add imported module with prefix equals to module prefix");
449 public ExtensionBuilder addExtension(final QName qname, final int line, final SchemaPath path) {
451 Builder parentBuilder = getActualNode();
452 if (!(parentBuilder.equals(this))) {
453 throw new YangParseException(name, line, "extension can be defined only in module or submodule");
456 final String extName = qname.getLocalName();
457 for (ExtensionBuilder addedExtension : addedExtensions) {
458 if (addedExtension.getQName().getLocalName().equals(extName)) {
459 raiseYangParserException("extension", "node", extName, line, addedExtension.getLine());
462 final ExtensionBuilder builder = new ExtensionBuilderImpl(name, line, qname, path);
463 builder.setParent(parentBuilder);
464 addedExtensions.add(builder);
468 public ContainerSchemaNodeBuilder addContainerNode(final int line, final QName qname, final SchemaPath schemaPath) {
470 final ContainerSchemaNodeBuilder builder = new ContainerSchemaNodeBuilder(name, line, qname, schemaPath);
472 Builder parentBuilder = getActualNode();
473 builder.setParent(parentBuilder);
474 addChildToParent(parentBuilder, builder, qname.getLocalName());
479 public ListSchemaNodeBuilder addListNode(final int line, final QName qname, final SchemaPath schemaPath) {
481 final ListSchemaNodeBuilder builder = new ListSchemaNodeBuilder(name, line, qname, schemaPath);
483 Builder parentBuilder = getActualNode();
484 builder.setParent(parentBuilder);
485 addChildToParent(parentBuilder, builder, qname.getLocalName());
486 allLists.add(builder);
491 public LeafSchemaNodeBuilder addLeafNode(final int line, final QName qname, final SchemaPath schemaPath) {
493 final LeafSchemaNodeBuilder builder = new LeafSchemaNodeBuilder(name, line, qname, schemaPath);
495 Builder parentBuilder = getActualNode();
496 builder.setParent(parentBuilder);
497 addChildToParent(parentBuilder, builder, qname.getLocalName());
502 public LeafListSchemaNodeBuilder addLeafListNode(final int line, final QName qname, final SchemaPath schemaPath) {
504 final LeafListSchemaNodeBuilder builder = new LeafListSchemaNodeBuilder(name, line, qname, schemaPath);
506 Builder parentBuilder = getActualNode();
507 builder.setParent(parentBuilder);
508 addChildToParent(parentBuilder, builder, qname.getLocalName());
513 public GroupingBuilder addGrouping(final int line, final QName qname, final SchemaPath path) {
515 final GroupingBuilder builder = new GroupingBuilderImpl(name, line, qname, path);
517 Builder parentBuilder = getActualNode();
518 builder.setParent(parentBuilder);
520 String groupingName = qname.getLocalName();
521 if (parentBuilder.equals(this)) {
522 for (GroupingBuilder addedGrouping : getGroupingBuilders()) {
523 if (addedGrouping.getQName().getLocalName().equals(groupingName)) {
524 raiseYangParserException("", GROUPING_STR, groupingName, line, addedGrouping.getLine());
527 addGrouping(builder);
529 if (parentBuilder instanceof DataNodeContainerBuilder) {
530 DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parentBuilder;
531 for (GroupingBuilder addedGrouping : parentNode.getGroupingBuilders()) {
532 if (addedGrouping.getQName().getLocalName().equals(groupingName)) {
533 raiseYangParserException("", GROUPING_STR, groupingName, line, addedGrouping.getLine());
536 parentNode.addGrouping(builder);
537 } else if (parentBuilder instanceof RpcDefinitionBuilder) {
538 RpcDefinitionBuilder parentNode = (RpcDefinitionBuilder) parentBuilder;
539 for (GroupingBuilder child : parentNode.getGroupings()) {
540 if (child.getQName().getLocalName().equals(groupingName)) {
541 raiseYangParserException("", GROUPING_STR, groupingName, line, child.getLine());
544 parentNode.addGrouping(builder);
546 throw new YangParseException(name, line, "Unresolved parent of grouping " + groupingName);
550 allGroupings.add(builder);
554 public AugmentationSchemaBuilder addAugment(final int line, final String augmentTargetStr,
555 final SchemaPath targetPath, final int order) {
557 final AugmentationSchemaBuilder builder = new AugmentationSchemaBuilderImpl(name, line, augmentTargetStr,
560 Builder parentBuilder = getActualNode();
561 builder.setParent(parentBuilder);
563 if (parentBuilder.equals(this)) {
564 // augment can be declared only under 'module' ...
565 if (!(augmentTargetStr.startsWith("/"))) {
566 throw new YangParseException(
569 "If the 'augment' statement is on the top level in a module, the absolute form of a schema node identifier MUST be used.");
571 augmentBuilders.add(builder);
573 // ... or 'uses' statement
574 if (parentBuilder instanceof UsesNodeBuilder) {
575 if (augmentTargetStr.startsWith("/")) {
576 throw new YangParseException(name, line,
577 "If 'augment' statement is a substatement to the 'uses' statement, it cannot contain absolute path ("
578 + augmentTargetStr + ")");
580 ((UsesNodeBuilder) parentBuilder).addAugment(builder);
582 throw new YangParseException(name, line, "Augment can be declared only under module or uses statement.");
585 allAugments.add(builder);
590 public UsesNodeBuilder addUsesNode(final int line, final SchemaPath grouping) {
592 final UsesNodeBuilder usesBuilder = new UsesNodeBuilderImpl(name, line, grouping);
594 Builder parentBuilder = getActualNode();
595 usesBuilder.setParent(parentBuilder);
597 if (parentBuilder.equals(this)) {
598 addUsesNode(usesBuilder);
600 if (!(parentBuilder instanceof DataNodeContainerBuilder)) {
601 throw new YangParseException(name, line, "Unresolved parent of uses '" + grouping + "'.");
603 ((DataNodeContainerBuilder) parentBuilder).addUsesNode(usesBuilder);
605 if (parentBuilder instanceof AugmentationSchemaBuilder) {
606 usesBuilder.setAugmenting(true);
609 allUsesNodes.add(usesBuilder);
613 public void addRefine(final RefineHolderImpl refine) {
615 final Builder parentBuilder = getActualNode();
616 if (!(parentBuilder instanceof UsesNodeBuilder)) {
617 throw new YangParseException(name, refine.getLine(), "refine can be defined only in uses statement");
619 ((UsesNodeBuilder) parentBuilder).addRefine(refine);
620 refine.setParent(parentBuilder);
623 public RpcDefinitionBuilder addRpc(final int line, final QName qname, final SchemaPath path) {
625 Builder parentBuilder = getActualNode();
626 if (!(parentBuilder.equals(this))) {
627 throw new YangParseException(name, line, "rpc can be defined only in module or submodule");
630 final RpcDefinitionBuilder rpcBuilder = new RpcDefinitionBuilder(name, line, qname, path);
631 rpcBuilder.setParent(parentBuilder);
633 String rpcName = qname.getLocalName();
634 checkNotConflictingInDataNamespace(rpcName, line);
635 addedRpcs.add(rpcBuilder);
639 private void checkNotConflictingInDataNamespace(final String rpcName, final int line) {
640 for (DataSchemaNodeBuilder addedChild : getChildNodeBuilders()) {
641 if (addedChild.getQName().getLocalName().equals(rpcName)) {
642 raiseYangParserException("rpc", "node", rpcName, line, addedChild.getLine());
645 for (RpcDefinitionBuilder rpc : addedRpcs) {
646 if (rpc.getQName().getLocalName().equals(rpcName)) {
647 raiseYangParserException("", "rpc", rpcName, line, rpc.getLine());
650 for (NotificationBuilder addedNotification : addedNotifications) {
651 if (addedNotification.getQName().getLocalName().equals(rpcName)) {
652 raiseYangParserException("rpc", "notification", rpcName, line, addedNotification.getLine());
657 public ContainerSchemaNodeBuilder addRpcInput(final int line, final QName qname, final SchemaPath schemaPath) {
659 final Builder parentBuilder = getActualNode();
660 if (!(parentBuilder instanceof RpcDefinitionBuilder)) {
661 throw new YangParseException(name, line, "input can be defined only in rpc statement");
663 final RpcDefinitionBuilder rpc = (RpcDefinitionBuilder) parentBuilder;
665 final ContainerSchemaNodeBuilder inputBuilder = new ContainerSchemaNodeBuilder(name, line, qname, schemaPath);
666 inputBuilder.setParent(rpc);
668 rpc.setInput(inputBuilder);
672 public ContainerSchemaNodeBuilder addRpcOutput(final SchemaPath schemaPath, final QName qname, final int line) {
674 final Builder parentBuilder = getActualNode();
675 if (!(parentBuilder instanceof RpcDefinitionBuilder)) {
676 throw new YangParseException(name, line, "output can be defined only in rpc statement");
678 final RpcDefinitionBuilder rpc = (RpcDefinitionBuilder) parentBuilder;
680 final ContainerSchemaNodeBuilder outputBuilder = new ContainerSchemaNodeBuilder(name, line, qname, schemaPath);
681 outputBuilder.setParent(rpc);
683 rpc.setOutput(outputBuilder);
684 return outputBuilder;
687 public void addNotification(final NotificationDefinition notification) {
689 notifications.add(notification);
692 public NotificationBuilder addNotification(final int line, final QName qname, final SchemaPath path) {
694 final Builder parentBuilder = getActualNode();
695 if (!(parentBuilder.equals(this))) {
696 throw new YangParseException(name, line, "notification can be defined only in module or submodule");
699 String notificationName = qname.getLocalName();
700 checkNotConflictingInDataNamespace(notificationName, line);
702 final NotificationBuilder builder = new NotificationBuilder(name, line, qname, path);
703 builder.setParent(parentBuilder);
704 addedNotifications.add(builder);
709 public FeatureBuilder addFeature(final int line, final QName qname, final SchemaPath path) {
710 Builder parentBuilder = getActualNode();
711 if (!(parentBuilder.equals(this))) {
712 throw new YangParseException(name, line, "feature can be defined only in module or submodule");
715 final FeatureBuilder builder = new FeatureBuilder(name, line, qname, path);
716 builder.setParent(parentBuilder);
718 String featureName = qname.getLocalName();
719 for (FeatureBuilder addedFeature : addedFeatures) {
720 if (addedFeature.getQName().getLocalName().equals(featureName)) {
721 raiseYangParserException("", "feature", featureName, line, addedFeature.getLine());
724 addedFeatures.add(builder);
728 public ChoiceBuilder addChoice(final int line, final QName qname, final SchemaPath path) {
729 final ChoiceBuilder builder = new ChoiceBuilder(name, line, qname, path);
731 Builder parentBuilder = getActualNode();
732 builder.setParent(parentBuilder);
733 addChildToParent(parentBuilder, builder, qname.getLocalName());
738 public ChoiceCaseBuilder addCase(final int line, final QName qname, final SchemaPath path) {
739 Builder parentBuilder = getActualNode();
740 if (parentBuilder == null || parentBuilder.equals(this)) {
741 throw new YangParseException(name, line, "'case' parent not found");
744 final ChoiceCaseBuilder builder = new ChoiceCaseBuilder(name, line, qname, path);
745 builder.setParent(parentBuilder);
747 if (parentBuilder instanceof ChoiceBuilder) {
748 ((ChoiceBuilder) parentBuilder).addCase(builder);
749 } else if (parentBuilder instanceof AugmentationSchemaBuilder) {
750 ((AugmentationSchemaBuilder) parentBuilder).addChildNode(builder);
752 throw new YangParseException(name, line, "Unresolved parent of 'case' " + qname.getLocalName());
758 public AnyXmlBuilder addAnyXml(final int line, final QName qname, final SchemaPath schemaPath) {
759 final AnyXmlBuilder builder = new AnyXmlBuilder(name, line, qname, schemaPath);
761 Builder parentBuilder = getActualNode();
762 builder.setParent(parentBuilder);
763 addChildToParent(parentBuilder, builder, qname.getLocalName());
769 public void addTypedef(final TypeDefinitionBuilder typedefBuilder) {
770 String nodeName = typedefBuilder.getQName().getLocalName();
771 for (TypeDefinitionBuilder tdb : getTypeDefinitionBuilders()) {
772 if (tdb.getQName().getLocalName().equals(nodeName)) {
773 raiseYangParserException("", TYPEDEF_STR, nodeName, typedefBuilder.getLine(), tdb.getLine());
776 super.addTypedef(typedefBuilder);
779 public TypeDefinitionBuilderImpl addTypedef(final int line, final QName qname, final SchemaPath path) {
780 final TypeDefinitionBuilderImpl builder = new TypeDefinitionBuilderImpl(name, line, qname, path);
782 Builder parentBuilder = getActualNode();
783 builder.setParent(parentBuilder);
785 String typedefName = qname.getLocalName();
786 if (parentBuilder.equals(this)) {
789 if (parentBuilder instanceof DataNodeContainerBuilder) {
790 DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parentBuilder;
791 for (TypeDefinitionBuilder child : parentNode.getTypeDefinitionBuilders()) {
792 if (child.getQName().getLocalName().equals(typedefName)) {
793 raiseYangParserException("", TYPEDEF_STR, typedefName, line, child.getLine());
796 parentNode.addTypedef(builder);
797 } else if (parentBuilder instanceof RpcDefinitionBuilder) {
798 RpcDefinitionBuilder rpcParent = (RpcDefinitionBuilder) parentBuilder;
799 for (TypeDefinitionBuilder tdb : rpcParent.getTypeDefinitions()) {
800 if (tdb.getQName().getLocalName().equals(builder.getQName().getLocalName())) {
801 raiseYangParserException("", TYPEDEF_STR, typedefName, line, tdb.getLine());
804 rpcParent.addTypedef(builder);
806 throw new YangParseException(name, line, "Unresolved parent of typedef " + typedefName);
813 public void setType(final TypeDefinition<?> type) {
814 Builder parentBuilder = getActualNode();
815 if (!(parentBuilder instanceof TypeAwareBuilder)) {
816 throw new YangParseException("Failed to set type '" + type.getQName().getLocalName()
817 + "'. Invalid parent node: " + parentBuilder);
819 ((TypeAwareBuilder) parentBuilder).setType(type);
822 public UnionTypeBuilder addUnionType(final int line, final QNameModule module) {
823 final Builder parentBuilder = getActualNode();
824 if (parentBuilder == null) {
825 throw new YangParseException(name, line, "Unresolved parent of union type");
827 final UnionTypeBuilder union = new UnionTypeBuilder(name, line);
828 if (parentBuilder instanceof TypeAwareBuilder) {
829 ((TypeAwareBuilder) parentBuilder).setTypedef(union);
832 throw new YangParseException(name, line, "Invalid parent of union type.");
837 public void addIdentityrefType(final int line, final SchemaPath schemaPath, final String baseString) {
838 final IdentityrefTypeBuilder identityref = new IdentityrefTypeBuilder(name, line, baseString, schemaPath);
840 final Builder parentBuilder = getActualNode();
841 if (parentBuilder == null) {
842 throw new YangParseException(name, line, "Unresolved parent of identityref type.");
844 if (parentBuilder instanceof TypeAwareBuilder) {
845 final TypeAwareBuilder typeParent = (TypeAwareBuilder) parentBuilder;
846 typeParent.setTypedef(identityref);
847 dirtyNodes.add(typeParent);
849 throw new YangParseException(name, line, "Invalid parent of identityref type.");
854 public DeviationBuilder addDeviation(final int line, final SchemaPath targetPath) {
855 Builder parentBuilder = getActualNode();
856 if (!(parentBuilder.equals(this))) {
857 throw new YangParseException(name, line, "deviation can be defined only in module or submodule");
860 final DeviationBuilder builder = new DeviationBuilder(name, line, targetPath);
861 builder.setParent(parentBuilder);
862 deviationBuilders.add(builder);
866 public IdentitySchemaNodeBuilder addIdentity(final QName qname, final int line, final SchemaPath path) {
867 Builder parentBuilder = getActualNode();
868 if (!(parentBuilder.equals(this))) {
869 throw new YangParseException(name, line, "identity can be defined only in module or submodule");
871 String identityName = qname.getLocalName();
872 for (IdentitySchemaNodeBuilder idBuilder : addedIdentities) {
873 if (idBuilder.getQName().equals(qname)) {
874 raiseYangParserException("", "identity", identityName, line, idBuilder.getLine());
878 final IdentitySchemaNodeBuilder builder = new IdentitySchemaNodeBuilder(name, line, qname, path);
879 builder.setParent(parentBuilder);
880 addedIdentities.add(builder);
885 public void addUnknownNodeBuilder(final UnknownSchemaNodeBuilder builder) {
886 addedUnknownNodes.add(builder);
887 allUnknownNodes.add(builder);
890 public UnknownSchemaNodeBuilderImpl addUnknownSchemaNode(final int line, final QName qname, final SchemaPath path) {
891 final Builder parentBuilder = getActualNode();
892 final UnknownSchemaNodeBuilderImpl builder = new UnknownSchemaNodeBuilderImpl(name, line, qname, path);
893 builder.setParent(parentBuilder);
894 allUnknownNodes.add(builder);
896 if (parentBuilder.equals(this)) {
897 addedUnknownNodes.add(builder);
899 if (parentBuilder instanceof SchemaNodeBuilder) {
900 parentBuilder.addUnknownNodeBuilder(builder);
901 } else if (parentBuilder instanceof DataNodeContainerBuilder) {
902 parentBuilder.addUnknownNodeBuilder(builder);
903 } else if (parentBuilder instanceof RefineHolderImpl) {
904 parentBuilder.addUnknownNodeBuilder(builder);
906 throw new YangParseException(name, line, "Unresolved parent of unknown node '" + qname.getLocalName()
914 public Set<RpcDefinition> getRpcs() {
918 public Set<RpcDefinitionBuilder> getAddedRpcs() {
922 public Set<NotificationDefinition> getNotifications() {
923 return notifications;
926 public Set<NotificationBuilder> getAddedNotifications() {
927 return addedNotifications;
931 public String toString() {
932 return "module " + name;
935 public void setSource(final ByteSource byteSource) throws IOException {
936 setSource(byteSource.asCharSource(Charsets.UTF_8).read());
939 public void setSource(final String source) {
940 this.source = source;
944 * Add child to parent. Method checks for duplicates and add given child
945 * node to parent. If node with same name is found, throws exception. If
946 * parent is null, child node will be added directly to module.
952 private void addChildToParent(final Builder parent, final DataSchemaNodeBuilder child, final String childName) {
953 final int lineNum = child.getLine();
954 if (parent.equals(this)) {
955 addChildToModule(child, childName, lineNum);
957 addChildToSubnodeOfModule(parent, child, childName, lineNum);
961 public String getYangVersion() {
965 public String getContact() {
969 public String getOrganization() {
974 * Adds child node <code>child</code> to the set of nodes child nodes.
976 * The method reduces the complexity of the method
977 * {@link #addChildToParent(Builder, DataSchemaNodeBuilder, String)
981 * data schema node builder for child node
983 * string with name of child node
985 * line number in YANG file where is the node with the name equal
986 * to <code>childName</code> is defined
988 private void addChildToModule(final DataSchemaNodeBuilder child, final String childName, final int lineNum) {
989 // if parent == null => node is defined under module
990 // All leafs, leaf-lists, lists, containers, choices, rpcs,
991 // notifications, and anyxmls defined within a parent node or at the
992 // top level of the module or its submodules share the same
993 // identifier namespace.
994 for (DataSchemaNodeBuilder childNode : getChildNodeBuilders()) {
995 if (childNode.getQName().getLocalName().equals(childName)) {
996 raiseYangParserException("'" + child + "'", "node", childName, lineNum, childNode.getLine());
999 for (RpcDefinitionBuilder rpc : addedRpcs) {
1000 if (rpc.getQName().getLocalName().equals(childName)) {
1001 raiseYangParserException("'" + child + "'", "rpc", childName, lineNum, rpc.getLine());
1004 for (NotificationBuilder notification : addedNotifications) {
1005 if (notification.getQName().getLocalName().equals(childName)) {
1006 raiseYangParserException("'" + child + "'", "notification", childName, lineNum, notification.getLine());
1009 addChildNode(child);
1013 * Adds child node <code>child</code> to the group of child nodes of the
1014 * <code>parent</code>
1016 * The method reduces the complexity of the method
1017 * {@link #addChildToParent(Builder, DataSchemaNodeBuilder, String)
1018 * addChildToParent}. *
1021 * builder of node which is parent for <code>child</code>
1023 * data schema node builder for child node
1025 * string with name of child node
1027 * line number in YANG file where is the node with the name equal
1028 * to <code>childName</code> is defined
1030 private void addChildToSubnodeOfModule(final Builder parent, final DataSchemaNodeBuilder child,
1031 final String childName, final int lineNum) {
1032 // no need for checking rpc and notification because they can be
1033 // defined only under module or submodule
1034 if (parent instanceof DataNodeContainerBuilder) {
1035 DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parent;
1036 for (DataSchemaNodeBuilder childNode : parentNode.getChildNodeBuilders()) {
1037 if (childNode.getQName().getLocalName().equals(childName)) {
1038 raiseYangParserException("'" + child + "'", "node", childName, lineNum, childNode.getLine());
1041 parentNode.addChildNode(child);
1042 } else if (parent instanceof ChoiceBuilder) {
1043 ChoiceBuilder parentNode = (ChoiceBuilder) parent;
1044 for (ChoiceCaseBuilder caseBuilder : parentNode.getCases()) {
1045 if (caseBuilder.getQName().getLocalName().equals(childName)) {
1046 raiseYangParserException("'" + child + "'", "node", childName, lineNum, caseBuilder.getLine());
1049 parentNode.addCase(child);
1051 throw new YangParseException(name, lineNum, "Unresolved parent of node '" + childName + "'.");
1055 private void raiseYangParserException(final String cantAddType, final String type, final String name,
1056 final int currentLine, final int duplicateLine) {
1058 StringBuilder msgPrefix = new StringBuilder("");
1059 if (cantAddType != null && !cantAddType.isEmpty()) {
1060 msgPrefix.append("Can not add ");
1061 msgPrefix.append(cantAddType);
1062 msgPrefix.append(": ");
1065 String msg = String.format("%s%s with same name '%s' already declared at line %d.", msgPrefix, type, name,
1067 throw new YangParseException(getModuleName(), currentLine, msg);
1071 public int hashCode() {
1072 final int prime = 31;
1074 result = prime * result + Objects.hashCode(name);
1075 result = prime * result + qnameModule.hashCode();
1076 result = prime * result + Objects.hashCode(prefix);
1082 public boolean equals(final Object obj) {
1089 if (getClass() != obj.getClass()) {
1092 ModuleBuilder other = (ModuleBuilder) obj;
1094 if (other.name != null) {
1097 } else if (!name.equals(other.name)) {
1100 if (!qnameModule.equals(other.qnameModule)) {
1103 if (prefix == null) {
1104 if (other.prefix != null) {
1107 } else if (!prefix.equals(other.prefix)) {
1113 public List<UnknownSchemaNode> getExtensionInstances() {
1114 return unknownNodes;