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 * @deprecated Pre-Beryllium implementation, scheduled for removal.
68 public class ModuleBuilder extends AbstractDocumentedDataNodeContainerBuilder implements DocumentedNodeBuilder {
69 private static final QNameModule EMPTY_QNAME_MODULE = QNameModule.create(null, null).intern();
70 private static final String GROUPING_STR = "Grouping";
71 private static final String TYPEDEF_STR = "typedef";
72 private ModuleImpl instance;
73 private final String name;
74 private final String sourcePath;
75 private static final SchemaPath SCHEMA_PATH = SchemaPath.create(Collections.emptyList(), true);
76 private String prefix;
77 private QNameModule qnameModule = EMPTY_QNAME_MODULE;
79 private final boolean submodule;
80 private String belongsTo;
81 private ModuleBuilder parent;
83 private final Deque<Builder> actualPath = new LinkedList<>();
84 private final Set<TypeAwareBuilder> dirtyNodes = new HashSet<>();
86 final Map<String, ModuleImport> imports = new HashMap<>();
87 final Map<String, ModuleBuilder> importedModules = new HashMap<>();
89 final Set<ModuleBuilder> addedSubmodules = new HashSet<>();
90 final Set<Module> submodules = new HashSet<>();
91 final Map<String, Date> includedModules = new HashMap<>();
93 private final Set<AugmentationSchema> augments = new LinkedHashSet<>();
94 private final List<AugmentationSchemaBuilder> augmentBuilders = new ArrayList<>();
95 private final List<AugmentationSchemaBuilder> allAugments = new ArrayList<>();
97 private final List<GroupingBuilder> allGroupings = new ArrayList<>();
99 private final List<UsesNodeBuilder> allUsesNodes = new ArrayList<>();
101 private final Set<RpcDefinition> rpcs = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
102 private final Set<RpcDefinitionBuilder> addedRpcs = new HashSet<>();
104 private final Set<NotificationDefinition> notifications = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
105 private final Set<NotificationBuilder> addedNotifications = new HashSet<>();
107 private final Set<IdentitySchemaNode> identities = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
108 private final Set<IdentitySchemaNodeBuilder> addedIdentities = new HashSet<>();
110 private final Set<FeatureDefinition> features = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
111 private final Set<FeatureBuilder> addedFeatures = new HashSet<>();
113 private final Set<Deviation> deviations = new HashSet<>();
114 private final Set<DeviationBuilder> deviationBuilders = new HashSet<>();
116 private final List<ExtensionDefinition> extensions = new ArrayList<>();
117 private final List<ExtensionBuilder> addedExtensions = new ArrayList<>();
119 private final List<UnknownSchemaNodeBuilder> allUnknownNodes = new ArrayList<>();
121 private final List<ListSchemaNodeBuilder> allLists = new ArrayList<>();
123 private String source;
124 private String yangVersion;
125 private String organization;
126 private String contact;
128 public ModuleBuilder(final String name, final String sourcePath) {
129 this(name, false, sourcePath);
132 public ModuleBuilder(final String name, final boolean submodule, final String sourcePath) {
133 super(name, 0, null);
135 this.sourcePath = sourcePath;
136 this.submodule = submodule;
137 actualPath.push(this);//FIXME: this escapes constructor
140 public ModuleBuilder(final Module base) {
141 super(base.getName(), 0, QName.create(base.getQNameModule(), base.getName()),
143 this.name = base.getName();
144 this.sourcePath = base.getModuleSourcePath();
147 yangVersion = base.getYangVersion();
148 actualPath.push(this);//FIXME: this escapes constructor
149 prefix = base.getPrefix();
150 qnameModule = base.getQNameModule();
152 augments.addAll(base.getAugmentations());
153 rpcs.addAll(base.getRpcs());
154 notifications.addAll(base.getNotifications());
156 for (IdentitySchemaNode identityNode : base.getIdentities()) {
157 addedIdentities.add(new IdentitySchemaNodeBuilder(name, identityNode));
160 features.addAll(base.getFeatures());
161 deviations.addAll(base.getDeviations());
162 extensions.addAll(base.getExtensionSchemaNodes());
163 unknownNodes.addAll(base.getUnknownSchemaNodes());
164 source = base.getSource();
168 protected String getStatementName() {
173 * Build new Module object based on this builder.
176 public Module build() {
177 if(instance != null) {
184 for (ModuleBuilder submodule : addedSubmodules) {
185 submodules.add(submodule.build());
189 for (FeatureBuilder fb : addedFeatures) {
190 features.add(fb.build());
194 for (NotificationBuilder entry : addedNotifications) {
195 notifications.add(entry.build());
199 for (AugmentationSchemaBuilder builder : augmentBuilders) {
200 augments.add(builder.build());
204 for (RpcDefinitionBuilder rpc : addedRpcs) {
205 rpcs.add(rpc.build());
209 for (DeviationBuilder entry : deviationBuilders) {
210 deviations.add(entry.build());
214 for (ExtensionBuilder eb : addedExtensions) {
215 extensions.add(eb.build());
217 Collections.sort(extensions, Comparators.SCHEMA_NODE_COMP);
221 for (IdentitySchemaNodeBuilder id : addedIdentities) {
222 identities.add(id.build());
226 for (UnknownSchemaNodeBuilder unb : addedUnknownNodes) {
227 unknownNodes.add(unb.build());
229 Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
231 instance = new ModuleImpl(name, sourcePath, this);
235 public String getModuleSourcePath() {
240 public ModuleBuilder getParent() {
244 public void setParent(final ModuleBuilder parent) {
245 this.parent = parent;
249 public void setParent(final Builder parent) {
250 throw new YangParseException(name, 0, "Can not set parent to module");
254 public SchemaPath getPath() {
258 public void enterNode(final Builder node) {
259 actualPath.push(node);
262 public void exitNode() {
266 public Builder getActualNode() {
267 if (actualPath.isEmpty()) {
270 return actualPath.peekFirst();
274 public Set<TypeAwareBuilder> getDirtyNodes() {
278 public Set<AugmentationSchema> getAugments() {
282 public List<AugmentationSchemaBuilder> getAugmentBuilders() {
283 return augmentBuilders;
286 public List<AugmentationSchemaBuilder> getAllAugments() {
290 public Set<IdentitySchemaNode> getIdentities() {
294 public Set<IdentitySchemaNodeBuilder> getAddedIdentities() {
295 return addedIdentities;
298 public Set<FeatureDefinition> getFeatures() {
302 public Set<FeatureBuilder> getAddedFeatures() {
303 return addedFeatures;
306 public List<GroupingBuilder> getAllGroupings() {
310 public List<UsesNodeBuilder> getAllUsesNodes() {
314 public Set<Deviation> getDeviations() {
318 public Set<DeviationBuilder> getDeviationBuilders() {
319 return deviationBuilders;
322 public List<ExtensionDefinition> getExtensions() {
326 public List<ExtensionBuilder> getAddedExtensions() {
327 return addedExtensions;
330 public List<UnknownSchemaNodeBuilder> getAllUnknownNodes() {
331 return allUnknownNodes;
334 public List<ListSchemaNodeBuilder> getAllLists() {
338 public String getName() {
342 public URI getNamespace() {
343 return qnameModule.getNamespace();
346 public QNameModule getQNameModule() {
350 public void setQNameModule(final QNameModule qnameModule) {
351 this.qnameModule = Preconditions.checkNotNull(qnameModule);
354 public void setNamespace(final URI namespace) {
355 this.qnameModule = QNameModule.create(namespace, qnameModule.getRevision()).intern();
358 public String getPrefix() {
362 public Date getRevision() {
363 return qnameModule.getRevision();
366 public ModuleImport getImport(final String prefix) {
367 return imports.get(prefix);
370 public Map<String, ModuleImport> getImports() {
374 public ModuleBuilder getImportedModule(final String prefix) {
375 return importedModules.get(prefix);
378 public void addImportedModule(final String prefix, final ModuleBuilder module) {
380 importedModules.put(prefix, module);
383 public Map<String, Date> getIncludedModules() {
384 return includedModules;
387 public void addInclude(final String name, final Date revision) {
388 includedModules.put(name, revision);
391 public void addSubmodule(final ModuleBuilder submodule) {
392 addedSubmodules.add(submodule);
395 protected String getSource() {
399 public boolean isSubmodule() {
403 public String getBelongsTo() {
407 public void setBelongsTo(final String belongsTo) {
408 this.belongsTo = belongsTo;
411 public void markActualNodeDirty() {
412 final TypeAwareBuilder nodeBuilder = (TypeAwareBuilder) getActualNode();
413 dirtyNodes.add(nodeBuilder);
416 public void setRevision(final Date revision) {
417 this.qnameModule = QNameModule.create(qnameModule.getNamespace(), revision).intern();
420 public void setPrefix(final String prefix) {
421 this.prefix = prefix;
424 public void setYangVersion(final String yangVersion) {
425 this.yangVersion = yangVersion;
428 public void setOrganization(final String organization) {
429 this.organization = organization;
432 public void setContact(final String contact) {
433 this.contact = contact;
436 public void addModuleImport(final String moduleName, final Date revision, final String prefix) {
439 final ModuleImport moduleImport = new ModuleImportImpl(moduleName, revision, prefix);
440 imports.put(prefix, moduleImport);
443 private void checkPrefix(final String prefix) {
444 if (prefix == null || prefix.isEmpty()) {
445 throw new IllegalArgumentException("Cannot add imported module with undefined prefix");
447 if (prefix.equals(this.prefix)) {
448 throw new IllegalArgumentException("Cannot add imported module with prefix equals to module prefix");
452 public ExtensionBuilder addExtension(final QName qname, final int line, final SchemaPath path) {
454 Builder parentBuilder = getActualNode();
455 if (!(parentBuilder.equals(this))) {
456 throw new YangParseException(name, line, "extension can be defined only in module or submodule");
459 final String extName = qname.getLocalName();
460 for (ExtensionBuilder addedExtension : addedExtensions) {
461 if (addedExtension.getQName().getLocalName().equals(extName)) {
462 raiseYangParserException("extension", "node", extName, line, addedExtension.getLine());
465 final ExtensionBuilder builder = new ExtensionBuilderImpl(name, line, qname, path);
466 builder.setParent(parentBuilder);
467 addedExtensions.add(builder);
471 public ContainerSchemaNodeBuilder addContainerNode(final int line, final QName qname, final SchemaPath schemaPath) {
473 final ContainerSchemaNodeBuilder builder = new ContainerSchemaNodeBuilder(name, line, qname, schemaPath);
475 Builder parentBuilder = getActualNode();
476 builder.setParent(parentBuilder);
477 addChildToParent(parentBuilder, builder, qname.getLocalName());
482 public ListSchemaNodeBuilder addListNode(final int line, final QName qname, final SchemaPath schemaPath) {
484 final ListSchemaNodeBuilder builder = new ListSchemaNodeBuilder(name, line, qname, schemaPath);
486 Builder parentBuilder = getActualNode();
487 builder.setParent(parentBuilder);
488 addChildToParent(parentBuilder, builder, qname.getLocalName());
489 allLists.add(builder);
494 public LeafSchemaNodeBuilder addLeafNode(final int line, final QName qname, final SchemaPath schemaPath) {
496 final LeafSchemaNodeBuilder builder = new LeafSchemaNodeBuilder(name, line, qname, schemaPath);
498 Builder parentBuilder = getActualNode();
499 builder.setParent(parentBuilder);
500 addChildToParent(parentBuilder, builder, qname.getLocalName());
505 public LeafListSchemaNodeBuilder addLeafListNode(final int line, final QName qname, final SchemaPath schemaPath) {
507 final LeafListSchemaNodeBuilder builder = new LeafListSchemaNodeBuilder(name, line, qname, schemaPath);
509 Builder parentBuilder = getActualNode();
510 builder.setParent(parentBuilder);
511 addChildToParent(parentBuilder, builder, qname.getLocalName());
516 public GroupingBuilder addGrouping(final int line, final QName qname, final SchemaPath path) {
518 final GroupingBuilder builder = new GroupingBuilderImpl(name, line, qname, path);
520 Builder parentBuilder = getActualNode();
521 builder.setParent(parentBuilder);
523 String groupingName = qname.getLocalName();
524 if (parentBuilder.equals(this)) {
525 for (GroupingBuilder addedGrouping : getGroupingBuilders()) {
526 if (addedGrouping.getQName().getLocalName().equals(groupingName)) {
527 raiseYangParserException("", GROUPING_STR, groupingName, line, addedGrouping.getLine());
530 addGrouping(builder);
532 if (parentBuilder instanceof DataNodeContainerBuilder) {
533 DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parentBuilder;
534 for (GroupingBuilder addedGrouping : parentNode.getGroupingBuilders()) {
535 if (addedGrouping.getQName().getLocalName().equals(groupingName)) {
536 raiseYangParserException("", GROUPING_STR, groupingName, line, addedGrouping.getLine());
539 parentNode.addGrouping(builder);
540 } else if (parentBuilder instanceof RpcDefinitionBuilder) {
541 RpcDefinitionBuilder parentNode = (RpcDefinitionBuilder) parentBuilder;
542 for (GroupingBuilder child : parentNode.getGroupings()) {
543 if (child.getQName().getLocalName().equals(groupingName)) {
544 raiseYangParserException("", GROUPING_STR, groupingName, line, child.getLine());
547 parentNode.addGrouping(builder);
549 throw new YangParseException(name, line, "Unresolved parent of grouping " + groupingName);
553 allGroupings.add(builder);
557 public AugmentationSchemaBuilder addAugment(final int line, final String augmentTargetStr,
558 final SchemaPath targetPath, final int order) {
560 final AugmentationSchemaBuilder builder = new AugmentationSchemaBuilderImpl(name, line, augmentTargetStr,
563 Builder parentBuilder = getActualNode();
564 builder.setParent(parentBuilder);
566 if (parentBuilder.equals(this)) {
567 // augment can be declared only under 'module' ...
568 if (!(augmentTargetStr.startsWith("/"))) {
569 throw new YangParseException(
572 "If the 'augment' statement is on the top level in a module, the absolute form of a schema node identifier MUST be used.");
574 augmentBuilders.add(builder);
576 // ... or 'uses' statement
577 if (parentBuilder instanceof UsesNodeBuilder) {
578 if (augmentTargetStr.startsWith("/")) {
579 throw new YangParseException(name, line,
580 "If 'augment' statement is a substatement to the 'uses' statement, it cannot contain absolute path ("
581 + augmentTargetStr + ")");
583 ((UsesNodeBuilder) parentBuilder).addAugment(builder);
585 throw new YangParseException(name, line, "Augment can be declared only under module or uses statement.");
588 allAugments.add(builder);
593 public UsesNodeBuilder addUsesNode(final int line, final SchemaPath grouping) {
595 final UsesNodeBuilder usesBuilder = new UsesNodeBuilderImpl(name, line, grouping);
597 Builder parentBuilder = getActualNode();
598 usesBuilder.setParent(parentBuilder);
600 if (parentBuilder.equals(this)) {
601 addUsesNode(usesBuilder);
603 if (!(parentBuilder instanceof DataNodeContainerBuilder)) {
604 throw new YangParseException(name, line, "Unresolved parent of uses '" + grouping + "'.");
606 ((DataNodeContainerBuilder) parentBuilder).addUsesNode(usesBuilder);
608 if (parentBuilder instanceof AugmentationSchemaBuilder) {
609 usesBuilder.setAugmenting(true);
612 allUsesNodes.add(usesBuilder);
616 public void addRefine(final RefineHolderImpl refine) {
618 final Builder parentBuilder = getActualNode();
619 if (!(parentBuilder instanceof UsesNodeBuilder)) {
620 throw new YangParseException(name, refine.getLine(), "refine can be defined only in uses statement");
622 ((UsesNodeBuilder) parentBuilder).addRefine(refine);
623 refine.setParent(parentBuilder);
626 public RpcDefinitionBuilder addRpc(final int line, final QName qname, final SchemaPath path) {
628 Builder parentBuilder = getActualNode();
629 if (!(parentBuilder.equals(this))) {
630 throw new YangParseException(name, line, "rpc can be defined only in module or submodule");
633 final RpcDefinitionBuilder rpcBuilder = new RpcDefinitionBuilder(name, line, qname, path);
634 rpcBuilder.setParent(parentBuilder);
636 String rpcName = qname.getLocalName();
637 checkNotConflictingInDataNamespace(rpcName, line);
638 addedRpcs.add(rpcBuilder);
642 private void checkNotConflictingInDataNamespace(final String rpcName, final int line) {
643 for (DataSchemaNodeBuilder addedChild : getChildNodeBuilders()) {
644 if (addedChild.getQName().getLocalName().equals(rpcName)) {
645 raiseYangParserException("rpc", "node", rpcName, line, addedChild.getLine());
648 for (RpcDefinitionBuilder rpc : addedRpcs) {
649 if (rpc.getQName().getLocalName().equals(rpcName)) {
650 raiseYangParserException("", "rpc", rpcName, line, rpc.getLine());
653 for (NotificationBuilder addedNotification : addedNotifications) {
654 if (addedNotification.getQName().getLocalName().equals(rpcName)) {
655 raiseYangParserException("rpc", "notification", rpcName, line, addedNotification.getLine());
660 public ContainerSchemaNodeBuilder addRpcInput(final int line, final QName qname, final SchemaPath schemaPath) {
662 final Builder parentBuilder = getActualNode();
663 if (!(parentBuilder instanceof RpcDefinitionBuilder)) {
664 throw new YangParseException(name, line, "input can be defined only in rpc statement");
666 final RpcDefinitionBuilder rpc = (RpcDefinitionBuilder) parentBuilder;
668 final ContainerSchemaNodeBuilder inputBuilder = new ContainerSchemaNodeBuilder(name, line, qname, schemaPath);
669 inputBuilder.setParent(rpc);
671 rpc.setInput(inputBuilder);
675 public ContainerSchemaNodeBuilder addRpcOutput(final SchemaPath schemaPath, final QName qname, final int line) {
677 final Builder parentBuilder = getActualNode();
678 if (!(parentBuilder instanceof RpcDefinitionBuilder)) {
679 throw new YangParseException(name, line, "output can be defined only in rpc statement");
681 final RpcDefinitionBuilder rpc = (RpcDefinitionBuilder) parentBuilder;
683 final ContainerSchemaNodeBuilder outputBuilder = new ContainerSchemaNodeBuilder(name, line, qname, schemaPath);
684 outputBuilder.setParent(rpc);
686 rpc.setOutput(outputBuilder);
687 return outputBuilder;
690 public void addNotification(final NotificationDefinition notification) {
692 notifications.add(notification);
695 public NotificationBuilder addNotification(final int line, final QName qname, final SchemaPath path) {
697 final Builder parentBuilder = getActualNode();
698 if (!(parentBuilder.equals(this))) {
699 throw new YangParseException(name, line, "notification can be defined only in module or submodule");
702 String notificationName = qname.getLocalName();
703 checkNotConflictingInDataNamespace(notificationName, line);
705 final NotificationBuilder builder = new NotificationBuilder(name, line, qname, path);
706 builder.setParent(parentBuilder);
707 addedNotifications.add(builder);
712 public FeatureBuilder addFeature(final int line, final QName qname, final SchemaPath path) {
713 Builder parentBuilder = getActualNode();
714 if (!(parentBuilder.equals(this))) {
715 throw new YangParseException(name, line, "feature can be defined only in module or submodule");
718 final FeatureBuilder builder = new FeatureBuilder(name, line, qname, path);
719 builder.setParent(parentBuilder);
721 String featureName = qname.getLocalName();
722 for (FeatureBuilder addedFeature : addedFeatures) {
723 if (addedFeature.getQName().getLocalName().equals(featureName)) {
724 raiseYangParserException("", "feature", featureName, line, addedFeature.getLine());
727 addedFeatures.add(builder);
731 public ChoiceBuilder addChoice(final int line, final QName qname, final SchemaPath path) {
732 final ChoiceBuilder builder = new ChoiceBuilder(name, line, qname, path);
734 Builder parentBuilder = getActualNode();
735 builder.setParent(parentBuilder);
736 addChildToParent(parentBuilder, builder, qname.getLocalName());
741 public ChoiceCaseBuilder addCase(final int line, final QName qname, final SchemaPath path) {
742 Builder parentBuilder = getActualNode();
743 if (parentBuilder == null || parentBuilder.equals(this)) {
744 throw new YangParseException(name, line, "'case' parent not found");
747 final ChoiceCaseBuilder builder = new ChoiceCaseBuilder(name, line, qname, path);
748 builder.setParent(parentBuilder);
750 if (parentBuilder instanceof ChoiceBuilder) {
751 ((ChoiceBuilder) parentBuilder).addCase(builder);
752 } else if (parentBuilder instanceof AugmentationSchemaBuilder) {
753 ((AugmentationSchemaBuilder) parentBuilder).addChildNode(builder);
755 throw new YangParseException(name, line, "Unresolved parent of 'case' " + qname.getLocalName());
761 public AnyXmlBuilder addAnyXml(final int line, final QName qname, final SchemaPath schemaPath) {
762 final AnyXmlBuilder builder = new AnyXmlBuilder(name, line, qname, schemaPath);
764 Builder parentBuilder = getActualNode();
765 builder.setParent(parentBuilder);
766 addChildToParent(parentBuilder, builder, qname.getLocalName());
772 public void addTypedef(final TypeDefinitionBuilder typedefBuilder) {
773 String nodeName = typedefBuilder.getQName().getLocalName();
774 for (TypeDefinitionBuilder tdb : getTypeDefinitionBuilders()) {
775 if (tdb.getQName().getLocalName().equals(nodeName)) {
776 raiseYangParserException("", TYPEDEF_STR, nodeName, typedefBuilder.getLine(), tdb.getLine());
779 super.addTypedef(typedefBuilder);
782 public TypeDefinitionBuilderImpl addTypedef(final int line, final QName qname, final SchemaPath path) {
783 final TypeDefinitionBuilderImpl builder = new TypeDefinitionBuilderImpl(name, line, qname, path);
785 Builder parentBuilder = getActualNode();
786 builder.setParent(parentBuilder);
788 String typedefName = qname.getLocalName();
789 if (parentBuilder.equals(this)) {
792 if (parentBuilder instanceof DataNodeContainerBuilder) {
793 DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parentBuilder;
794 for (TypeDefinitionBuilder child : parentNode.getTypeDefinitionBuilders()) {
795 if (child.getQName().getLocalName().equals(typedefName)) {
796 raiseYangParserException("", TYPEDEF_STR, typedefName, line, child.getLine());
799 parentNode.addTypedef(builder);
800 } else if (parentBuilder instanceof RpcDefinitionBuilder) {
801 RpcDefinitionBuilder rpcParent = (RpcDefinitionBuilder) parentBuilder;
802 for (TypeDefinitionBuilder tdb : rpcParent.getTypeDefinitions()) {
803 if (tdb.getQName().getLocalName().equals(builder.getQName().getLocalName())) {
804 raiseYangParserException("", TYPEDEF_STR, typedefName, line, tdb.getLine());
807 rpcParent.addTypedef(builder);
809 throw new YangParseException(name, line, "Unresolved parent of typedef " + typedefName);
816 public void setType(final TypeDefinition<?> type) {
817 Builder parentBuilder = getActualNode();
818 if (!(parentBuilder instanceof TypeAwareBuilder)) {
819 throw new YangParseException("Failed to set type '" + type.getQName().getLocalName()
820 + "'. Invalid parent node: " + parentBuilder);
822 ((TypeAwareBuilder) parentBuilder).setType(type);
825 public UnionTypeBuilder addUnionType(final int line, final QNameModule module) {
826 final Builder parentBuilder = getActualNode();
827 if (parentBuilder == null) {
828 throw new YangParseException(name, line, "Unresolved parent of union type");
830 final UnionTypeBuilder union = new UnionTypeBuilder(name, line);
831 if (parentBuilder instanceof TypeAwareBuilder) {
832 ((TypeAwareBuilder) parentBuilder).setTypedef(union);
835 throw new YangParseException(name, line, "Invalid parent of union type.");
840 public void addIdentityrefType(final int line, final SchemaPath schemaPath, final String baseString) {
841 final IdentityrefTypeBuilder identityref = new IdentityrefTypeBuilder(name, line, baseString, schemaPath);
843 final Builder parentBuilder = getActualNode();
844 if (parentBuilder == null) {
845 throw new YangParseException(name, line, "Unresolved parent of identityref type.");
847 if (parentBuilder instanceof TypeAwareBuilder) {
848 final TypeAwareBuilder typeParent = (TypeAwareBuilder) parentBuilder;
849 typeParent.setTypedef(identityref);
850 dirtyNodes.add(typeParent);
852 throw new YangParseException(name, line, "Invalid parent of identityref type.");
857 public DeviationBuilder addDeviation(final int line, final SchemaPath targetPath) {
858 Builder parentBuilder = getActualNode();
859 if (!(parentBuilder.equals(this))) {
860 throw new YangParseException(name, line, "deviation can be defined only in module or submodule");
863 final DeviationBuilder builder = new DeviationBuilder(name, line, targetPath);
864 builder.setParent(parentBuilder);
865 deviationBuilders.add(builder);
869 public IdentitySchemaNodeBuilder addIdentity(final QName qname, final int line, final SchemaPath path) {
870 Builder parentBuilder = getActualNode();
871 if (!(parentBuilder.equals(this))) {
872 throw new YangParseException(name, line, "identity can be defined only in module or submodule");
874 String identityName = qname.getLocalName();
875 for (IdentitySchemaNodeBuilder idBuilder : addedIdentities) {
876 if (idBuilder.getQName().equals(qname)) {
877 raiseYangParserException("", "identity", identityName, line, idBuilder.getLine());
881 final IdentitySchemaNodeBuilder builder = new IdentitySchemaNodeBuilder(name, line, qname, path);
882 builder.setParent(parentBuilder);
883 addedIdentities.add(builder);
888 public void addUnknownNodeBuilder(final UnknownSchemaNodeBuilder builder) {
889 addedUnknownNodes.add(builder);
890 allUnknownNodes.add(builder);
893 public UnknownSchemaNodeBuilderImpl addUnknownSchemaNode(final int line, final QName qname, final SchemaPath path) {
894 final Builder parentBuilder = getActualNode();
895 final UnknownSchemaNodeBuilderImpl builder = new UnknownSchemaNodeBuilderImpl(name, line, qname, path);
896 builder.setParent(parentBuilder);
897 allUnknownNodes.add(builder);
899 if (parentBuilder.equals(this)) {
900 addedUnknownNodes.add(builder);
902 if (parentBuilder instanceof SchemaNodeBuilder) {
903 parentBuilder.addUnknownNodeBuilder(builder);
904 } else if (parentBuilder instanceof DataNodeContainerBuilder) {
905 parentBuilder.addUnknownNodeBuilder(builder);
906 } else if (parentBuilder instanceof RefineHolderImpl) {
907 parentBuilder.addUnknownNodeBuilder(builder);
909 throw new YangParseException(name, line, "Unresolved parent of unknown node '" + qname.getLocalName()
917 public Set<RpcDefinition> getRpcs() {
921 public Set<RpcDefinitionBuilder> getAddedRpcs() {
925 public Set<NotificationDefinition> getNotifications() {
926 return notifications;
929 public Set<NotificationBuilder> getAddedNotifications() {
930 return addedNotifications;
934 public String toString() {
935 return "module " + name;
938 public void setSource(final ByteSource byteSource) throws IOException {
939 setSource(byteSource.asCharSource(Charsets.UTF_8).read());
942 public void setSource(final String source) {
943 this.source = source;
947 * Add child to parent. Method checks for duplicates and add given child
948 * node to parent. If node with same name is found, throws exception. If
949 * parent is null, child node will be added directly to module.
955 private void addChildToParent(final Builder parent, final DataSchemaNodeBuilder child, final String childName) {
956 final int lineNum = child.getLine();
957 if (parent.equals(this)) {
958 addChildToModule(child, childName, lineNum);
960 addChildToSubnodeOfModule(parent, child, childName, lineNum);
964 public String getYangVersion() {
968 public String getContact() {
972 public String getOrganization() {
977 * Adds child node <code>child</code> to the set of nodes child nodes.
979 * The method reduces the complexity of the method
980 * {@link #addChildToParent(Builder, DataSchemaNodeBuilder, String)
984 * data schema node builder for child node
986 * string with name of child node
988 * line number in YANG file where is the node with the name equal
989 * to <code>childName</code> is defined
991 private void addChildToModule(final DataSchemaNodeBuilder child, final String childName, final int lineNum) {
992 // if parent == null => node is defined under module
993 // All leafs, leaf-lists, lists, containers, choices, rpcs,
994 // notifications, and anyxmls defined within a parent node or at the
995 // top level of the module or its submodules share the same
996 // identifier namespace.
997 for (DataSchemaNodeBuilder childNode : getChildNodeBuilders()) {
998 if (childNode.getQName().getLocalName().equals(childName)) {
999 raiseYangParserException("'" + child + "'", "node", childName, lineNum, childNode.getLine());
1002 for (RpcDefinitionBuilder rpc : addedRpcs) {
1003 if (rpc.getQName().getLocalName().equals(childName)) {
1004 raiseYangParserException("'" + child + "'", "rpc", childName, lineNum, rpc.getLine());
1007 for (NotificationBuilder notification : addedNotifications) {
1008 if (notification.getQName().getLocalName().equals(childName)) {
1009 raiseYangParserException("'" + child + "'", "notification", childName, lineNum, notification.getLine());
1012 addChildNode(child);
1016 * Adds child node <code>child</code> to the group of child nodes of the
1017 * <code>parent</code>
1019 * The method reduces the complexity of the method
1020 * {@link #addChildToParent(Builder, DataSchemaNodeBuilder, String)
1021 * addChildToParent}. *
1024 * builder of node which is parent for <code>child</code>
1026 * data schema node builder for child node
1028 * string with name of child node
1030 * line number in YANG file where is the node with the name equal
1031 * to <code>childName</code> is defined
1033 private void addChildToSubnodeOfModule(final Builder parent, final DataSchemaNodeBuilder child,
1034 final String childName, final int lineNum) {
1035 // no need for checking rpc and notification because they can be
1036 // defined only under module or submodule
1037 if (parent instanceof DataNodeContainerBuilder) {
1038 DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parent;
1039 for (DataSchemaNodeBuilder childNode : parentNode.getChildNodeBuilders()) {
1040 if (childNode.getQName().getLocalName().equals(childName)) {
1041 raiseYangParserException("'" + child + "'", "node", childName, lineNum, childNode.getLine());
1044 parentNode.addChildNode(child);
1045 } else if (parent instanceof ChoiceBuilder) {
1046 ChoiceBuilder parentNode = (ChoiceBuilder) parent;
1047 for (ChoiceCaseBuilder caseBuilder : parentNode.getCases()) {
1048 if (caseBuilder.getQName().getLocalName().equals(childName)) {
1049 raiseYangParserException("'" + child + "'", "node", childName, lineNum, caseBuilder.getLine());
1052 parentNode.addCase(child);
1054 throw new YangParseException(name, lineNum, "Unresolved parent of node '" + childName + "'.");
1058 private void raiseYangParserException(final String cantAddType, final String type, final String name,
1059 final int currentLine, final int duplicateLine) {
1061 StringBuilder msgPrefix = new StringBuilder("");
1062 if (cantAddType != null && !cantAddType.isEmpty()) {
1063 msgPrefix.append("Can not add ");
1064 msgPrefix.append(cantAddType);
1065 msgPrefix.append(": ");
1068 String msg = String.format("%s%s with same name '%s' already declared at line %d.", msgPrefix, type, name,
1070 throw new YangParseException(getModuleName(), currentLine, msg);
1074 public int hashCode() {
1075 final int prime = 31;
1077 result = prime * result + Objects.hashCode(name);
1078 result = prime * result + qnameModule.hashCode();
1079 result = prime * result + Objects.hashCode(prefix);
1085 public boolean equals(final Object obj) {
1092 if (getClass() != obj.getClass()) {
1095 ModuleBuilder other = (ModuleBuilder) obj;
1097 if (other.name != null) {
1100 } else if (!name.equals(other.name)) {
1103 if (!qnameModule.equals(other.qnameModule)) {
1106 if (prefix == null) {
1107 if (other.prefix != null) {
1110 } else if (!prefix.equals(other.prefix)) {
1116 public List<UnknownSchemaNode> getExtensionInstances() {
1117 return unknownNodes;