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;
27 import java.util.TreeSet;
28 import org.opendaylight.yangtools.yang.common.QName;
29 import org.opendaylight.yangtools.yang.common.QNameModule;
30 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
31 import org.opendaylight.yangtools.yang.model.api.Deviation;
32 import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition;
33 import org.opendaylight.yangtools.yang.model.api.FeatureDefinition;
34 import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
35 import org.opendaylight.yangtools.yang.model.api.Module;
36 import org.opendaylight.yangtools.yang.model.api.ModuleImport;
37 import org.opendaylight.yangtools.yang.model.api.NotificationDefinition;
38 import org.opendaylight.yangtools.yang.model.api.RpcDefinition;
39 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
40 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
41 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
42 import org.opendaylight.yangtools.yang.model.util.ModuleImportImpl;
43 import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationSchemaBuilder;
44 import org.opendaylight.yangtools.yang.parser.builder.api.Builder;
45 import org.opendaylight.yangtools.yang.parser.builder.api.DataNodeContainerBuilder;
46 import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
47 import org.opendaylight.yangtools.yang.parser.builder.api.DocumentedNodeBuilder;
48 import org.opendaylight.yangtools.yang.parser.builder.api.ExtensionBuilder;
49 import org.opendaylight.yangtools.yang.parser.builder.api.GroupingBuilder;
50 import org.opendaylight.yangtools.yang.parser.builder.api.SchemaNodeBuilder;
51 import org.opendaylight.yangtools.yang.parser.builder.api.TypeAwareBuilder;
52 import org.opendaylight.yangtools.yang.parser.builder.api.TypeDefinitionBuilder;
53 import org.opendaylight.yangtools.yang.parser.builder.api.UnknownSchemaNodeBuilder;
54 import org.opendaylight.yangtools.yang.parser.builder.api.UsesNodeBuilder;
55 import org.opendaylight.yangtools.yang.parser.builder.util.AbstractDocumentedDataNodeContainerBuilder;
56 import org.opendaylight.yangtools.yang.parser.builder.util.Comparators;
57 import org.opendaylight.yangtools.yang.parser.util.YangParseException;
60 * Builder of Module object. If this module is dependent on external
61 * module/modules, these dependencies must be resolved before module is built,
62 * otherwise result may not be valid.
64 public class ModuleBuilder extends AbstractDocumentedDataNodeContainerBuilder implements DocumentedNodeBuilder {
65 private static final QNameModule EMPTY_QNAME_MODULE = QNameModule.cachedReference(QNameModule.create(null, null));
66 private static final String GROUPING_STR = "Grouping";
67 private static final String TYPEDEF_STR = "typedef";
68 private ModuleImpl instance;
69 private final String name;
70 private final String sourcePath;
71 private static final SchemaPath SCHEMA_PATH = SchemaPath.create(Collections.<QName> emptyList(), true);
72 private String prefix;
73 private QNameModule qnameModule = EMPTY_QNAME_MODULE;
75 private final boolean submodule;
76 private String belongsTo;
77 private ModuleBuilder parent;
79 private final Deque<Builder> actualPath = new LinkedList<>();
80 private final Set<TypeAwareBuilder> dirtyNodes = new HashSet<>();
82 final Map<String, ModuleImport> imports = new HashMap<>();
83 final Map<String, ModuleBuilder> importedModules = new HashMap<>();
85 final Set<ModuleBuilder> addedSubmodules = new HashSet<>();
86 final Set<Module> submodules = new HashSet<>();
87 final Map<String, Date> includedModules = new HashMap<>();
89 private final Set<AugmentationSchema> augments = new LinkedHashSet<>();
90 private final List<AugmentationSchemaBuilder> augmentBuilders = new ArrayList<>();
91 private final List<AugmentationSchemaBuilder> allAugments = new ArrayList<>();
93 private final List<GroupingBuilder> allGroupings = new ArrayList<>();
95 private final List<UsesNodeBuilder> allUsesNodes = new ArrayList<>();
97 private final Set<RpcDefinition> rpcs = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
98 private final Set<RpcDefinitionBuilder> addedRpcs = new HashSet<>();
100 private final Set<NotificationDefinition> notifications = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
101 private final Set<NotificationBuilder> addedNotifications = new HashSet<>();
103 private final Set<IdentitySchemaNode> identities = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
104 private final Set<IdentitySchemaNodeBuilder> addedIdentities = new HashSet<>();
106 private final Set<FeatureDefinition> features = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
107 private final Set<FeatureBuilder> addedFeatures = new HashSet<>();
109 private final Set<Deviation> deviations = new HashSet<>();
110 private final Set<DeviationBuilder> deviationBuilders = new HashSet<>();
112 private final List<ExtensionDefinition> extensions = new ArrayList<>();
113 private final List<ExtensionBuilder> addedExtensions = new ArrayList<>();
115 private final List<UnknownSchemaNodeBuilder> allUnknownNodes = new ArrayList<>();
117 private final List<ListSchemaNodeBuilder> allLists = new ArrayList<>();
119 private String source;
120 private String yangVersion;
121 private String organization;
122 private String contact;
124 public ModuleBuilder(final String name, final String sourcePath) {
125 this(name, false, sourcePath);
128 public ModuleBuilder(final String name, final boolean submodule, final String sourcePath) {
129 super(name, 0, null);
131 this.sourcePath = sourcePath;
132 this.submodule = submodule;
133 actualPath.push(this);//FIXME: this escapes constructor
136 public ModuleBuilder(final Module base) {
137 super(base.getName(), 0, QName.create(base.getQNameModule(), base.getName()),
139 this.name = base.getName();
140 this.sourcePath = base.getModuleSourcePath();
143 yangVersion = base.getYangVersion();
144 actualPath.push(this);//FIXME: this escapes constructor
145 prefix = base.getPrefix();
146 qnameModule = base.getQNameModule();
148 augments.addAll(base.getAugmentations());
149 rpcs.addAll(base.getRpcs());
150 notifications.addAll(base.getNotifications());
152 for (IdentitySchemaNode identityNode : base.getIdentities()) {
153 addedIdentities.add(new IdentitySchemaNodeBuilder(name, identityNode));
156 features.addAll(base.getFeatures());
157 deviations.addAll(base.getDeviations());
158 extensions.addAll(base.getExtensionSchemaNodes());
159 unknownNodes.addAll(base.getUnknownSchemaNodes());
160 source = base.getSource();
164 protected String getStatementName() {
169 * Build new Module object based on this builder.
172 public Module build() {
173 if(instance != null) {
180 for (ModuleBuilder submodule : addedSubmodules) {
181 submodules.add(submodule.build());
185 for (FeatureBuilder fb : addedFeatures) {
186 features.add(fb.build());
190 for (NotificationBuilder entry : addedNotifications) {
191 notifications.add(entry.build());
195 for (AugmentationSchemaBuilder builder : augmentBuilders) {
196 augments.add(builder.build());
200 for (RpcDefinitionBuilder rpc : addedRpcs) {
201 rpcs.add(rpc.build());
205 for (DeviationBuilder entry : deviationBuilders) {
206 deviations.add(entry.build());
210 for (ExtensionBuilder eb : addedExtensions) {
211 extensions.add(eb.build());
213 Collections.sort(extensions, Comparators.SCHEMA_NODE_COMP);
217 for (IdentitySchemaNodeBuilder id : addedIdentities) {
218 identities.add(id.build());
222 for (UnknownSchemaNodeBuilder unb : addedUnknownNodes) {
223 unknownNodes.add(unb.build());
225 Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
227 instance = new ModuleImpl(name, sourcePath, this);
231 public String getModuleSourcePath() {
236 public ModuleBuilder getParent() {
240 public void setParent(final ModuleBuilder parent) {
241 this.parent = parent;
245 public void setParent(final Builder parent) {
246 throw new YangParseException(name, 0, "Can not set parent to module");
250 public SchemaPath getPath() {
254 public void enterNode(final Builder node) {
255 actualPath.push(node);
258 public void exitNode() {
262 public Builder getActualNode() {
263 if (actualPath.isEmpty()) {
266 return actualPath.peekFirst();
270 public Set<TypeAwareBuilder> getDirtyNodes() {
274 public Set<AugmentationSchema> getAugments() {
278 public List<AugmentationSchemaBuilder> getAugmentBuilders() {
279 return augmentBuilders;
282 public List<AugmentationSchemaBuilder> getAllAugments() {
286 public Set<IdentitySchemaNode> getIdentities() {
290 public Set<IdentitySchemaNodeBuilder> getAddedIdentities() {
291 return addedIdentities;
294 public Set<FeatureDefinition> getFeatures() {
298 public Set<FeatureBuilder> getAddedFeatures() {
299 return addedFeatures;
302 public List<GroupingBuilder> getAllGroupings() {
306 public List<UsesNodeBuilder> getAllUsesNodes() {
310 public Set<Deviation> getDeviations() {
314 public Set<DeviationBuilder> getDeviationBuilders() {
315 return deviationBuilders;
318 public List<ExtensionDefinition> getExtensions() {
322 public List<ExtensionBuilder> getAddedExtensions() {
323 return addedExtensions;
326 public List<UnknownSchemaNodeBuilder> getAllUnknownNodes() {
327 return allUnknownNodes;
330 public List<ListSchemaNodeBuilder> getAllLists() {
334 public String getName() {
338 public URI getNamespace() {
339 return qnameModule.getNamespace();
342 public QNameModule getQNameModule() {
346 public void setQNameModule(final QNameModule qnameModule) {
347 this.qnameModule = Preconditions.checkNotNull(qnameModule);
350 public void setNamespace(final URI namespace) {
351 this.qnameModule = QNameModule.cachedReference(QNameModule.create(namespace, qnameModule.getRevision()));
354 public String getPrefix() {
358 public Date getRevision() {
359 return qnameModule.getRevision();
362 public ModuleImport getImport(final String prefix) {
363 return imports.get(prefix);
366 public Map<String, ModuleImport> getImports() {
370 public ModuleBuilder getImportedModule(final String prefix) {
371 return importedModules.get(prefix);
374 public void addImportedModule(final String prefix, final ModuleBuilder module) {
376 importedModules.put(prefix, module);
379 public Map<String, Date> getIncludedModules() {
380 return includedModules;
383 public void addInclude(final String name, final Date revision) {
384 includedModules.put(name, revision);
387 public void addSubmodule(final ModuleBuilder submodule) {
388 addedSubmodules.add(submodule);
391 protected String getSource() {
395 public boolean isSubmodule() {
399 public String getBelongsTo() {
403 public void setBelongsTo(final String belongsTo) {
404 this.belongsTo = belongsTo;
407 public void markActualNodeDirty() {
408 final TypeAwareBuilder nodeBuilder = (TypeAwareBuilder) getActualNode();
409 dirtyNodes.add(nodeBuilder);
412 public void setRevision(final Date revision) {
413 this.qnameModule = QNameModule.cachedReference(QNameModule.create(qnameModule.getNamespace(), revision));
416 public void setPrefix(final String prefix) {
417 this.prefix = prefix;
420 public void setYangVersion(final String yangVersion) {
421 this.yangVersion = yangVersion;
424 public void setOrganization(final String organization) {
425 this.organization = organization;
428 public void setContact(final String contact) {
429 this.contact = contact;
432 public void addModuleImport(final String moduleName, final Date revision, final String prefix) {
435 final ModuleImport moduleImport = new ModuleImportImpl(moduleName, revision, prefix);
436 imports.put(prefix, moduleImport);
439 private void checkPrefix(final String prefix) {
440 if (prefix == null || prefix.isEmpty()) {
441 throw new IllegalArgumentException("Cannot add imported module with undefined prefix");
443 if (prefix.equals(this.prefix)) {
444 throw new IllegalArgumentException("Cannot add imported module with prefix equals to module prefix");
448 public ExtensionBuilder addExtension(final QName qname, final int line, final SchemaPath path) {
450 Builder parentBuilder = getActualNode();
451 if (!(parentBuilder.equals(this))) {
452 throw new YangParseException(name, line, "extension can be defined only in module or submodule");
455 final String extName = qname.getLocalName();
456 for (ExtensionBuilder addedExtension : addedExtensions) {
457 if (addedExtension.getQName().getLocalName().equals(extName)) {
458 raiseYangParserException("extension", "node", extName, line, addedExtension.getLine());
461 final ExtensionBuilder builder = new ExtensionBuilderImpl(name, line, qname, path);
462 builder.setParent(parentBuilder);
463 addedExtensions.add(builder);
467 public ContainerSchemaNodeBuilder addContainerNode(final int line, final QName qname, final SchemaPath schemaPath) {
469 final ContainerSchemaNodeBuilder builder = new ContainerSchemaNodeBuilder(name, line, qname, schemaPath);
471 Builder parentBuilder = getActualNode();
472 builder.setParent(parentBuilder);
473 addChildToParent(parentBuilder, builder, qname.getLocalName());
478 public ListSchemaNodeBuilder addListNode(final int line, final QName qname, final SchemaPath schemaPath) {
480 final ListSchemaNodeBuilder builder = new ListSchemaNodeBuilder(name, line, qname, schemaPath);
482 Builder parentBuilder = getActualNode();
483 builder.setParent(parentBuilder);
484 addChildToParent(parentBuilder, builder, qname.getLocalName());
485 allLists.add(builder);
490 public LeafSchemaNodeBuilder addLeafNode(final int line, final QName qname, final SchemaPath schemaPath) {
492 final LeafSchemaNodeBuilder builder = new LeafSchemaNodeBuilder(name, line, qname, schemaPath);
494 Builder parentBuilder = getActualNode();
495 builder.setParent(parentBuilder);
496 addChildToParent(parentBuilder, builder, qname.getLocalName());
501 public LeafListSchemaNodeBuilder addLeafListNode(final int line, final QName qname, final SchemaPath schemaPath) {
503 final LeafListSchemaNodeBuilder builder = new LeafListSchemaNodeBuilder(name, line, qname, schemaPath);
505 Builder parentBuilder = getActualNode();
506 builder.setParent(parentBuilder);
507 addChildToParent(parentBuilder, builder, qname.getLocalName());
512 public GroupingBuilder addGrouping(final int line, final QName qname, final SchemaPath path) {
514 final GroupingBuilder builder = new GroupingBuilderImpl(name, line, qname, path);
516 Builder parentBuilder = getActualNode();
517 builder.setParent(parentBuilder);
519 String groupingName = qname.getLocalName();
520 if (parentBuilder.equals(this)) {
521 for (GroupingBuilder addedGrouping : getGroupingBuilders()) {
522 if (addedGrouping.getQName().getLocalName().equals(groupingName)) {
523 raiseYangParserException("", GROUPING_STR, groupingName, line, addedGrouping.getLine());
526 addGrouping(builder);
528 if (parentBuilder instanceof DataNodeContainerBuilder) {
529 DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parentBuilder;
530 for (GroupingBuilder addedGrouping : parentNode.getGroupingBuilders()) {
531 if (addedGrouping.getQName().getLocalName().equals(groupingName)) {
532 raiseYangParserException("", GROUPING_STR, groupingName, line, addedGrouping.getLine());
535 parentNode.addGrouping(builder);
536 } else if (parentBuilder instanceof RpcDefinitionBuilder) {
537 RpcDefinitionBuilder parentNode = (RpcDefinitionBuilder) parentBuilder;
538 for (GroupingBuilder child : parentNode.getGroupings()) {
539 if (child.getQName().getLocalName().equals(groupingName)) {
540 raiseYangParserException("", GROUPING_STR, groupingName, line, child.getLine());
543 parentNode.addGrouping(builder);
545 throw new YangParseException(name, line, "Unresolved parent of grouping " + groupingName);
549 allGroupings.add(builder);
553 public AugmentationSchemaBuilder addAugment(final int line, final String augmentTargetStr,
554 final SchemaPath targetPath, final int order) {
556 final AugmentationSchemaBuilder builder = new AugmentationSchemaBuilderImpl(name, line, augmentTargetStr,
559 Builder parentBuilder = getActualNode();
560 builder.setParent(parentBuilder);
562 if (parentBuilder.equals(this)) {
563 // augment can be declared only under 'module' ...
564 if (!(augmentTargetStr.startsWith("/"))) {
565 throw new YangParseException(
568 "If the 'augment' statement is on the top level in a module, the absolute form of a schema node identifier MUST be used.");
570 augmentBuilders.add(builder);
572 // ... or 'uses' statement
573 if (parentBuilder instanceof UsesNodeBuilder) {
574 if (augmentTargetStr.startsWith("/")) {
575 throw new YangParseException(name, line,
576 "If 'augment' statement is a substatement to the 'uses' statement, it cannot contain absolute path ("
577 + augmentTargetStr + ")");
579 ((UsesNodeBuilder) parentBuilder).addAugment(builder);
581 throw new YangParseException(name, line, "Augment can be declared only under module or uses statement.");
584 allAugments.add(builder);
589 public UsesNodeBuilder addUsesNode(final int line, final SchemaPath grouping) {
591 final UsesNodeBuilder usesBuilder = new UsesNodeBuilderImpl(name, line, grouping);
593 Builder parentBuilder = getActualNode();
594 usesBuilder.setParent(parentBuilder);
596 if (parentBuilder.equals(this)) {
597 addUsesNode(usesBuilder);
599 if (!(parentBuilder instanceof DataNodeContainerBuilder)) {
600 throw new YangParseException(name, line, "Unresolved parent of uses '" + grouping + "'.");
602 ((DataNodeContainerBuilder) parentBuilder).addUsesNode(usesBuilder);
604 if (parentBuilder instanceof AugmentationSchemaBuilder) {
605 usesBuilder.setAugmenting(true);
608 allUsesNodes.add(usesBuilder);
612 public void addRefine(final RefineHolderImpl refine) {
614 final Builder parentBuilder = getActualNode();
615 if (!(parentBuilder instanceof UsesNodeBuilder)) {
616 throw new YangParseException(name, refine.getLine(), "refine can be defined only in uses statement");
618 ((UsesNodeBuilder) parentBuilder).addRefine(refine);
619 refine.setParent(parentBuilder);
622 public RpcDefinitionBuilder addRpc(final int line, final QName qname, final SchemaPath path) {
624 Builder parentBuilder = getActualNode();
625 if (!(parentBuilder.equals(this))) {
626 throw new YangParseException(name, line, "rpc can be defined only in module or submodule");
629 final RpcDefinitionBuilder rpcBuilder = new RpcDefinitionBuilder(name, line, qname, path);
630 rpcBuilder.setParent(parentBuilder);
632 String rpcName = qname.getLocalName();
633 checkNotConflictingInDataNamespace(rpcName, line);
634 addedRpcs.add(rpcBuilder);
638 private void checkNotConflictingInDataNamespace(final String rpcName, final int line) {
639 for (DataSchemaNodeBuilder addedChild : getChildNodeBuilders()) {
640 if (addedChild.getQName().getLocalName().equals(rpcName)) {
641 raiseYangParserException("rpc", "node", rpcName, line, addedChild.getLine());
644 for (RpcDefinitionBuilder rpc : addedRpcs) {
645 if (rpc.getQName().getLocalName().equals(rpcName)) {
646 raiseYangParserException("", "rpc", rpcName, line, rpc.getLine());
649 for (NotificationBuilder addedNotification : addedNotifications) {
650 if (addedNotification.getQName().getLocalName().equals(rpcName)) {
651 raiseYangParserException("rpc", "notification", rpcName, line, addedNotification.getLine());
656 public ContainerSchemaNodeBuilder addRpcInput(final int line, final QName qname, final SchemaPath schemaPath) {
658 final Builder parentBuilder = getActualNode();
659 if (!(parentBuilder instanceof RpcDefinitionBuilder)) {
660 throw new YangParseException(name, line, "input can be defined only in rpc statement");
662 final RpcDefinitionBuilder rpc = (RpcDefinitionBuilder) parentBuilder;
664 final ContainerSchemaNodeBuilder inputBuilder = new ContainerSchemaNodeBuilder(name, line, qname, schemaPath);
665 inputBuilder.setParent(rpc);
667 rpc.setInput(inputBuilder);
671 public ContainerSchemaNodeBuilder addRpcOutput(final SchemaPath schemaPath, final QName qname, final int line) {
673 final Builder parentBuilder = getActualNode();
674 if (!(parentBuilder instanceof RpcDefinitionBuilder)) {
675 throw new YangParseException(name, line, "output can be defined only in rpc statement");
677 final RpcDefinitionBuilder rpc = (RpcDefinitionBuilder) parentBuilder;
679 final ContainerSchemaNodeBuilder outputBuilder = new ContainerSchemaNodeBuilder(name, line, qname, schemaPath);
680 outputBuilder.setParent(rpc);
682 rpc.setOutput(outputBuilder);
683 return outputBuilder;
686 public void addNotification(final NotificationDefinition notification) {
688 notifications.add(notification);
691 public NotificationBuilder addNotification(final int line, final QName qname, final SchemaPath path) {
693 final Builder parentBuilder = getActualNode();
694 if (!(parentBuilder.equals(this))) {
695 throw new YangParseException(name, line, "notification can be defined only in module or submodule");
698 String notificationName = qname.getLocalName();
699 checkNotConflictingInDataNamespace(notificationName, line);
701 final NotificationBuilder builder = new NotificationBuilder(name, line, qname, path);
702 builder.setParent(parentBuilder);
703 addedNotifications.add(builder);
708 public FeatureBuilder addFeature(final int line, final QName qname, final SchemaPath path) {
709 Builder parentBuilder = getActualNode();
710 if (!(parentBuilder.equals(this))) {
711 throw new YangParseException(name, line, "feature can be defined only in module or submodule");
714 final FeatureBuilder builder = new FeatureBuilder(name, line, qname, path);
715 builder.setParent(parentBuilder);
717 String featureName = qname.getLocalName();
718 for (FeatureBuilder addedFeature : addedFeatures) {
719 if (addedFeature.getQName().getLocalName().equals(featureName)) {
720 raiseYangParserException("", "feature", featureName, line, addedFeature.getLine());
723 addedFeatures.add(builder);
727 public ChoiceBuilder addChoice(final int line, final QName qname, final SchemaPath path) {
728 final ChoiceBuilder builder = new ChoiceBuilder(name, line, qname, path);
730 Builder parentBuilder = getActualNode();
731 builder.setParent(parentBuilder);
732 addChildToParent(parentBuilder, builder, qname.getLocalName());
737 public ChoiceCaseBuilder addCase(final int line, final QName qname, final SchemaPath path) {
738 Builder parentBuilder = getActualNode();
739 if (parentBuilder == null || parentBuilder.equals(this)) {
740 throw new YangParseException(name, line, "'case' parent not found");
743 final ChoiceCaseBuilder builder = new ChoiceCaseBuilder(name, line, qname, path);
744 builder.setParent(parentBuilder);
746 if (parentBuilder instanceof ChoiceBuilder) {
747 ((ChoiceBuilder) parentBuilder).addCase(builder);
748 } else if (parentBuilder instanceof AugmentationSchemaBuilder) {
749 ((AugmentationSchemaBuilder) parentBuilder).addChildNode(builder);
751 throw new YangParseException(name, line, "Unresolved parent of 'case' " + qname.getLocalName());
757 public AnyXmlBuilder addAnyXml(final int line, final QName qname, final SchemaPath schemaPath) {
758 final AnyXmlBuilder builder = new AnyXmlBuilder(name, line, qname, schemaPath);
760 Builder parentBuilder = getActualNode();
761 builder.setParent(parentBuilder);
762 addChildToParent(parentBuilder, builder, qname.getLocalName());
768 public void addTypedef(final TypeDefinitionBuilder typedefBuilder) {
769 String nodeName = typedefBuilder.getQName().getLocalName();
770 for (TypeDefinitionBuilder tdb : getTypeDefinitionBuilders()) {
771 if (tdb.getQName().getLocalName().equals(nodeName)) {
772 raiseYangParserException("", TYPEDEF_STR, nodeName, typedefBuilder.getLine(), tdb.getLine());
775 super.addTypedef(typedefBuilder);
778 public TypeDefinitionBuilderImpl addTypedef(final int line, final QName qname, final SchemaPath path) {
779 final TypeDefinitionBuilderImpl builder = new TypeDefinitionBuilderImpl(name, line, qname, path);
781 Builder parentBuilder = getActualNode();
782 builder.setParent(parentBuilder);
784 String typedefName = qname.getLocalName();
785 if (parentBuilder.equals(this)) {
788 if (parentBuilder instanceof DataNodeContainerBuilder) {
789 DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parentBuilder;
790 for (TypeDefinitionBuilder child : parentNode.getTypeDefinitionBuilders()) {
791 if (child.getQName().getLocalName().equals(typedefName)) {
792 raiseYangParserException("", TYPEDEF_STR, typedefName, line, child.getLine());
795 parentNode.addTypedef(builder);
796 } else if (parentBuilder instanceof RpcDefinitionBuilder) {
797 RpcDefinitionBuilder rpcParent = (RpcDefinitionBuilder) parentBuilder;
798 for (TypeDefinitionBuilder tdb : rpcParent.getTypeDefinitions()) {
799 if (tdb.getQName().getLocalName().equals(builder.getQName().getLocalName())) {
800 raiseYangParserException("", TYPEDEF_STR, typedefName, line, tdb.getLine());
803 rpcParent.addTypedef(builder);
805 throw new YangParseException(name, line, "Unresolved parent of typedef " + typedefName);
812 public void setType(final TypeDefinition<?> type) {
813 Builder parentBuilder = getActualNode();
814 if (!(parentBuilder instanceof TypeAwareBuilder)) {
815 throw new YangParseException("Failed to set type '" + type.getQName().getLocalName()
816 + "'. Invalid parent node: " + parentBuilder);
818 ((TypeAwareBuilder) parentBuilder).setType(type);
821 public UnionTypeBuilder addUnionType(final int line, final QNameModule module) {
822 final Builder parentBuilder = getActualNode();
823 if (parentBuilder == null) {
824 throw new YangParseException(name, line, "Unresolved parent of union type");
826 final UnionTypeBuilder union = new UnionTypeBuilder(name, line);
827 if (parentBuilder instanceof TypeAwareBuilder) {
828 ((TypeAwareBuilder) parentBuilder).setTypedef(union);
831 throw new YangParseException(name, line, "Invalid parent of union type.");
836 public void addIdentityrefType(final int line, final SchemaPath schemaPath, final String baseString) {
837 final IdentityrefTypeBuilder identityref = new IdentityrefTypeBuilder(name, line, baseString, schemaPath);
839 final Builder parentBuilder = getActualNode();
840 if (parentBuilder == null) {
841 throw new YangParseException(name, line, "Unresolved parent of identityref type.");
843 if (parentBuilder instanceof TypeAwareBuilder) {
844 final TypeAwareBuilder typeParent = (TypeAwareBuilder) parentBuilder;
845 typeParent.setTypedef(identityref);
846 dirtyNodes.add(typeParent);
848 throw new YangParseException(name, line, "Invalid parent of identityref type.");
853 public DeviationBuilder addDeviation(final int line, final SchemaPath targetPath) {
854 Builder parentBuilder = getActualNode();
855 if (!(parentBuilder.equals(this))) {
856 throw new YangParseException(name, line, "deviation can be defined only in module or submodule");
859 final DeviationBuilder builder = new DeviationBuilder(name, line, targetPath);
860 builder.setParent(parentBuilder);
861 deviationBuilders.add(builder);
865 public IdentitySchemaNodeBuilder addIdentity(final QName qname, final int line, final SchemaPath path) {
866 Builder parentBuilder = getActualNode();
867 if (!(parentBuilder.equals(this))) {
868 throw new YangParseException(name, line, "identity can be defined only in module or submodule");
870 String identityName = qname.getLocalName();
871 for (IdentitySchemaNodeBuilder idBuilder : addedIdentities) {
872 if (idBuilder.getQName().equals(qname)) {
873 raiseYangParserException("", "identity", identityName, line, idBuilder.getLine());
877 final IdentitySchemaNodeBuilder builder = new IdentitySchemaNodeBuilder(name, line, qname, path);
878 builder.setParent(parentBuilder);
879 addedIdentities.add(builder);
884 public void addUnknownNodeBuilder(final UnknownSchemaNodeBuilder builder) {
885 addedUnknownNodes.add(builder);
886 allUnknownNodes.add(builder);
889 public UnknownSchemaNodeBuilderImpl addUnknownSchemaNode(final int line, final QName qname, final SchemaPath path) {
890 final Builder parentBuilder = getActualNode();
891 final UnknownSchemaNodeBuilderImpl builder = new UnknownSchemaNodeBuilderImpl(name, line, qname, path);
892 builder.setParent(parentBuilder);
893 allUnknownNodes.add(builder);
895 if (parentBuilder.equals(this)) {
896 addedUnknownNodes.add(builder);
898 if (parentBuilder instanceof SchemaNodeBuilder) {
899 parentBuilder.addUnknownNodeBuilder(builder);
900 } else if (parentBuilder instanceof DataNodeContainerBuilder) {
901 parentBuilder.addUnknownNodeBuilder(builder);
902 } else if (parentBuilder instanceof RefineHolderImpl) {
903 parentBuilder.addUnknownNodeBuilder(builder);
905 throw new YangParseException(name, line, "Unresolved parent of unknown node '" + qname.getLocalName()
913 public Set<RpcDefinition> getRpcs() {
917 public Set<RpcDefinitionBuilder> getAddedRpcs() {
921 public Set<NotificationDefinition> getNotifications() {
922 return notifications;
925 public Set<NotificationBuilder> getAddedNotifications() {
926 return addedNotifications;
930 public String toString() {
931 return "module " + name;
934 public void setSource(final ByteSource byteSource) throws IOException {
935 setSource(byteSource.asCharSource(Charsets.UTF_8).read());
938 public void setSource(final String source) {
939 this.source = source;
943 * Add child to parent. Method checks for duplicates and add given child
944 * node to parent. If node with same name is found, throws exception. If
945 * parent is null, child node will be added directly to module.
951 private void addChildToParent(final Builder parent, final DataSchemaNodeBuilder child, final String childName) {
952 final int lineNum = child.getLine();
953 if (parent.equals(this)) {
954 addChildToModule(child, childName, lineNum);
956 addChildToSubnodeOfModule(parent, child, childName, lineNum);
960 public String getYangVersion() {
964 public String getContact() {
968 public String getOrganization() {
973 * Adds child node <code>child</code> to the set of nodes child nodes.
975 * The method reduces the complexity of the method
976 * {@link #addChildToParent(Builder, DataSchemaNodeBuilder, String)
980 * data schema node builder for child node
982 * string with name of child node
984 * line number in YANG file where is the node with the name equal
985 * to <code>childName</code> is defined
987 private void addChildToModule(final DataSchemaNodeBuilder child, final String childName, final int lineNum) {
988 // if parent == null => node is defined under module
989 // All leafs, leaf-lists, lists, containers, choices, rpcs,
990 // notifications, and anyxmls defined within a parent node or at the
991 // top level of the module or its submodules share the same
992 // identifier namespace.
993 for (DataSchemaNodeBuilder childNode : getChildNodeBuilders()) {
994 if (childNode.getQName().getLocalName().equals(childName)) {
995 raiseYangParserException("'" + child + "'", "node", childName, lineNum, childNode.getLine());
998 for (RpcDefinitionBuilder rpc : addedRpcs) {
999 if (rpc.getQName().getLocalName().equals(childName)) {
1000 raiseYangParserException("'" + child + "'", "rpc", childName, lineNum, rpc.getLine());
1003 for (NotificationBuilder notification : addedNotifications) {
1004 if (notification.getQName().getLocalName().equals(childName)) {
1005 raiseYangParserException("'" + child + "'", "notification", childName, lineNum, notification.getLine());
1008 addChildNode(child);
1012 * Adds child node <code>child</code> to the group of child nodes of the
1013 * <code>parent</code>
1015 * The method reduces the complexity of the method
1016 * {@link #addChildToParent(Builder, DataSchemaNodeBuilder, String)
1017 * addChildToParent}. *
1020 * builder of node which is parent for <code>child</code>
1022 * data schema node builder for child node
1024 * string with name of child node
1026 * line number in YANG file where is the node with the name equal
1027 * to <code>childName</code> is defined
1029 private void addChildToSubnodeOfModule(final Builder parent, final DataSchemaNodeBuilder child,
1030 final String childName, final int lineNum) {
1031 // no need for checking rpc and notification because they can be
1032 // defined only under module or submodule
1033 if (parent instanceof DataNodeContainerBuilder) {
1034 DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parent;
1035 for (DataSchemaNodeBuilder childNode : parentNode.getChildNodeBuilders()) {
1036 if (childNode.getQName().getLocalName().equals(childName)) {
1037 raiseYangParserException("'" + child + "'", "node", childName, lineNum, childNode.getLine());
1040 parentNode.addChildNode(child);
1041 } else if (parent instanceof ChoiceBuilder) {
1042 ChoiceBuilder parentNode = (ChoiceBuilder) parent;
1043 for (ChoiceCaseBuilder caseBuilder : parentNode.getCases()) {
1044 if (caseBuilder.getQName().getLocalName().equals(childName)) {
1045 raiseYangParserException("'" + child + "'", "node", childName, lineNum, caseBuilder.getLine());
1048 parentNode.addCase(child);
1050 throw new YangParseException(name, lineNum, "Unresolved parent of node '" + childName + "'.");
1054 private void raiseYangParserException(final String cantAddType, final String type, final String name,
1055 final int currentLine, final int duplicateLine) {
1057 StringBuilder msgPrefix = new StringBuilder("");
1058 if (cantAddType != null && !cantAddType.isEmpty()) {
1059 msgPrefix.append("Can not add ");
1060 msgPrefix.append(cantAddType);
1061 msgPrefix.append(": ");
1064 String msg = String.format("%s%s with same name '%s' already declared at line %d.", msgPrefix, type, name,
1066 throw new YangParseException(getModuleName(), currentLine, msg);
1070 public int hashCode() {
1071 final int prime = 31;
1073 result = prime * result + ((name == null) ? 0 : name.hashCode());
1074 result = prime * result + qnameModule.hashCode();
1075 result = prime * result + ((prefix == null) ? 0 : prefix.hashCode());
1081 public boolean equals(final Object obj) {
1088 if (getClass() != obj.getClass()) {
1091 ModuleBuilder other = (ModuleBuilder) obj;
1093 if (other.name != null) {
1096 } else if (!name.equals(other.name)) {
1099 if (!qnameModule.equals(other.qnameModule)) {
1102 if (prefix == null) {
1103 if (other.prefix != null) {
1106 } else if (!prefix.equals(other.prefix)) {
1112 public List<UnknownSchemaNode> getExtensionInstances() {
1113 return unknownNodes;