2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.yang.parser.builder.impl;
11 import java.util.ArrayList;
12 import java.util.Collections;
13 import java.util.Date;
14 import java.util.HashMap;
15 import java.util.HashSet;
16 import java.util.LinkedHashSet;
17 import java.util.LinkedList;
18 import java.util.List;
21 import java.util.TreeMap;
22 import java.util.TreeSet;
24 import org.opendaylight.controller.yang.common.QName;
25 import org.opendaylight.controller.yang.model.api.AugmentationSchema;
26 import org.opendaylight.controller.yang.model.api.DataSchemaNode;
27 import org.opendaylight.controller.yang.model.api.Deviation;
28 import org.opendaylight.controller.yang.model.api.ExtensionDefinition;
29 import org.opendaylight.controller.yang.model.api.FeatureDefinition;
30 import org.opendaylight.controller.yang.model.api.GroupingDefinition;
31 import org.opendaylight.controller.yang.model.api.IdentitySchemaNode;
32 import org.opendaylight.controller.yang.model.api.Module;
33 import org.opendaylight.controller.yang.model.api.ModuleImport;
34 import org.opendaylight.controller.yang.model.api.NotificationDefinition;
35 import org.opendaylight.controller.yang.model.api.RpcDefinition;
36 import org.opendaylight.controller.yang.model.api.SchemaPath;
37 import org.opendaylight.controller.yang.model.api.TypeDefinition;
38 import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
39 import org.opendaylight.controller.yang.model.api.UsesNode;
40 import org.opendaylight.controller.yang.parser.builder.api.AugmentationSchemaBuilder;
41 import org.opendaylight.controller.yang.parser.builder.api.Builder;
42 import org.opendaylight.controller.yang.parser.builder.api.DataNodeContainerBuilder;
43 import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
44 import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
45 import org.opendaylight.controller.yang.parser.builder.api.SchemaNodeBuilder;
46 import org.opendaylight.controller.yang.parser.builder.api.TypeAwareBuilder;
47 import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
48 import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
49 import org.opendaylight.controller.yang.parser.util.Comparators;
50 import org.opendaylight.controller.yang.parser.util.RefineHolder;
51 import org.opendaylight.controller.yang.parser.util.YangParseException;
54 * This builder builds Module object. If this module is dependent on external
55 * module/modules, these dependencies must be resolved before module is built,
56 * otherwise result may not be valid.
58 public class ModuleBuilder implements DataNodeContainerBuilder {
59 private final ModuleImpl instance;
60 private final String name;
61 private URI namespace;
62 private String prefix;
63 private Date revision;
65 private int augmentsResolved;
67 private final Set<ModuleImport> imports = new HashSet<ModuleImport>();
70 * Holds all child (DataSchemaNode) nodes: anyxml, choice, case, container,
71 * list, leaf, leaf-list.
73 private final Set<DataSchemaNodeBuilder> childNodes = new HashSet<DataSchemaNodeBuilder>();
75 private final Set<GroupingBuilder> addedGroupings = new HashSet<GroupingBuilder>();
76 private final List<AugmentationSchemaBuilder> addedAugments = new ArrayList<AugmentationSchemaBuilder>();
77 private final List<AugmentationSchemaBuilder> allAugments = new ArrayList<AugmentationSchemaBuilder>();
78 private final Set<UsesNodeBuilder> addedUsesNodes = new HashSet<UsesNodeBuilder>();
79 private final List<UsesNodeBuilder> allUsesNodes = new ArrayList<UsesNodeBuilder>();
80 private final Set<RpcDefinitionBuilder> addedRpcs = new HashSet<RpcDefinitionBuilder>();
81 private final Set<NotificationBuilder> addedNotifications = new HashSet<NotificationBuilder>();
82 private final Set<IdentitySchemaNodeBuilder> addedIdentities = new HashSet<IdentitySchemaNodeBuilder>();
83 private final Set<FeatureBuilder> addedFeatures = new HashSet<FeatureBuilder>();
84 private final Map<List<String>, DeviationBuilder> addedDeviations = new HashMap<List<String>, DeviationBuilder>();
85 private final Set<TypeDefinitionBuilder> addedTypedefs = new HashSet<TypeDefinitionBuilder>();
86 private final Map<List<String>, UnionTypeBuilder> addedUnionTypes = new HashMap<List<String>, UnionTypeBuilder>();
87 private final List<ExtensionBuilder> addedExtensions = new ArrayList<ExtensionBuilder>();
88 private final Map<List<String>, List<UnknownSchemaNodeBuilder>> addedUnknownNodes = new HashMap<List<String>, List<UnknownSchemaNodeBuilder>>();
90 private final Map<List<String>, TypeAwareBuilder> dirtyNodes = new HashMap<List<String>, TypeAwareBuilder>();
92 private final LinkedList<Builder> actualPath = new LinkedList<Builder>();
94 public ModuleBuilder(final String name) {
96 instance = new ModuleImpl(name);
100 * Build new Module object based on this builder.
103 public Module build() {
104 instance.setPrefix(prefix);
105 instance.setRevision(revision);
106 instance.setImports(imports);
107 instance.setNamespace(namespace);
110 final Set<TypeDefinition<?>> typedefs = new TreeSet<TypeDefinition<?>>(Comparators.SCHEMA_NODE_COMP);
111 for (TypeDefinitionBuilder tdb : addedTypedefs) {
112 typedefs.add(tdb.build());
114 instance.setTypeDefinitions(typedefs);
117 final Map<QName, DataSchemaNode> children = new TreeMap<QName, DataSchemaNode>(Comparators.QNAME_COMP);
118 for (DataSchemaNodeBuilder child : childNodes) {
119 children.put(child.getQName(), child.build());
121 instance.setChildNodes(children);
124 final Set<GroupingDefinition> groupings = new TreeSet<GroupingDefinition>(Comparators.SCHEMA_NODE_COMP);
125 for (GroupingBuilder gb : addedGroupings) {
126 groupings.add(gb.build());
128 instance.setGroupings(groupings);
131 final Set<UsesNode> usesDefinitions = new HashSet<UsesNode>();
132 for (UsesNodeBuilder unb : addedUsesNodes) {
133 usesDefinitions.add(unb.build());
135 instance.setUses(usesDefinitions);
138 final Set<FeatureDefinition> features = new TreeSet<FeatureDefinition>(Comparators.SCHEMA_NODE_COMP);
139 for (FeatureBuilder fb : addedFeatures) {
140 features.add(fb.build());
142 instance.setFeatures(features);
145 final Set<NotificationDefinition> notifications = new TreeSet<NotificationDefinition>(
146 Comparators.SCHEMA_NODE_COMP);
147 for (NotificationBuilder entry : addedNotifications) {
148 notifications.add(entry.build());
150 instance.setNotifications(notifications);
153 final Set<AugmentationSchema> augmentations = new HashSet<AugmentationSchema>();
154 for (AugmentationSchemaBuilder builder : addedAugments) {
155 augmentations.add(builder.build());
157 instance.setAugmentations(augmentations);
160 final Set<RpcDefinition> rpcs = new TreeSet<RpcDefinition>(Comparators.SCHEMA_NODE_COMP);
161 for (RpcDefinitionBuilder rpc : addedRpcs) {
162 rpcs.add(rpc.build());
164 instance.setRpcs(rpcs);
167 final Set<Deviation> deviations = new HashSet<Deviation>();
168 for (Map.Entry<List<String>, DeviationBuilder> entry : addedDeviations.entrySet()) {
169 deviations.add(entry.getValue().build());
171 instance.setDeviations(deviations);
174 final List<ExtensionDefinition> extensions = new ArrayList<ExtensionDefinition>();
175 for (ExtensionBuilder eb : addedExtensions) {
176 extensions.add(eb.build());
178 Collections.sort(extensions, Comparators.SCHEMA_NODE_COMP);
179 instance.setExtensionSchemaNodes(extensions);
182 final Set<IdentitySchemaNode> identities = new TreeSet<IdentitySchemaNode>(Comparators.SCHEMA_NODE_COMP);
183 for (IdentitySchemaNodeBuilder id : addedIdentities) {
184 identities.add(id.build());
186 instance.setIdentities(identities);
189 final List<UnknownSchemaNode> unknownNodes = buildModuleUnknownNodes(addedUnknownNodes);
190 instance.setUnknownSchemaNodes(unknownNodes);
196 public int getLine() {
201 public Builder getParent() {
206 public void setParent(Builder parent) {
207 throw new YangParseException(name, 0, "Can not set parent to module");
211 public QName getQName() {
212 return new QName(namespace, revision, prefix, name);
216 public SchemaPath getPath() {
221 public Set<TypeDefinitionBuilder> getTypeDefinitionBuilders() {
222 return addedTypedefs;
225 public void enterNode(final Builder node) {
226 actualPath.push(node);
229 public void exitNode() {
233 public Builder getActualNode() {
234 if (actualPath.isEmpty()) {
237 return actualPath.get(0);
241 public Builder getActualParent() {
242 if (actualPath.size() < 2) {
245 return actualPath.get(1);
250 public Set<GroupingDefinition> getGroupings() {
251 return Collections.emptySet();
255 public Set<GroupingBuilder> getGroupingBuilders() {
256 return addedGroupings;
260 public Set<DataSchemaNode> getChildNodes() {
261 return Collections.emptySet();
264 public Set<DataSchemaNodeBuilder> getChildNodeBuilders() {
268 public Map<List<String>, TypeAwareBuilder> getDirtyNodes() {
272 public List<AugmentationSchemaBuilder> getAllAugments() {
276 public Set<IdentitySchemaNodeBuilder> getIdentities() {
277 return addedIdentities;
280 public List<UsesNodeBuilder> getAllUsesNodes() {
284 public List<UnknownSchemaNodeBuilder> getUnknownNodes() {
285 List<UnknownSchemaNodeBuilder> result = new ArrayList<UnknownSchemaNodeBuilder>();
286 for (List<UnknownSchemaNodeBuilder> entry : addedUnknownNodes.values()) {
287 result.addAll(entry);
292 public String getName() {
296 public URI getNamespace() {
300 public void setNamespace(final URI namespace) {
301 this.namespace = namespace;
304 public String getPrefix() {
308 public Date getRevision() {
312 public int getAugmentsResolved() {
313 return augmentsResolved;
316 public void augmentResolved() {
320 public void addDirtyNode(final List<String> path) {
321 final List<String> dirtyNodePath = new ArrayList<String>(path);
322 final TypeAwareBuilder nodeBuilder = (TypeAwareBuilder) actualPath.getFirst();
323 dirtyNodes.put(dirtyNodePath, nodeBuilder);
326 public void setRevision(final Date revision) {
327 this.revision = revision;
330 public void setPrefix(final String prefix) {
331 this.prefix = prefix;
334 public void setYangVersion(final String yangVersion) {
335 instance.setYangVersion(yangVersion);
338 public void setDescription(final String description) {
339 instance.setDescription(description);
342 public void setReference(final String reference) {
343 instance.setReference(reference);
346 public void setOrganization(final String organization) {
347 instance.setOrganization(organization);
350 public void setContact(final String contact) {
351 instance.setContact(contact);
354 public boolean addModuleImport(final String moduleName, final Date revision, final String prefix) {
355 final ModuleImport moduleImport = createModuleImport(moduleName, revision, prefix);
356 return imports.add(moduleImport);
359 public Set<ModuleImport> getModuleImports() {
363 public ExtensionBuilder addExtension(final QName qname, final int line) {
364 final ExtensionBuilder builder = new ExtensionBuilder(line, qname);
365 addedExtensions.add(builder);
370 public void addChildNode(DataSchemaNodeBuilder child) {
371 for (DataSchemaNodeBuilder childNode : childNodes) {
372 if (childNode.getQName().getLocalName().equals(child.getQName().getLocalName())) {
373 throw new YangParseException(name, child.getLine(), "Duplicate node found at line "
374 + childNode.getLine());
377 childNodes.add(child);
380 public ContainerSchemaNodeBuilder addContainerNode(final int line, final QName containerName,
381 final SchemaPath schemaPath) {
382 final ContainerSchemaNodeBuilder builder = new ContainerSchemaNodeBuilder(line, containerName, schemaPath);
384 Builder parent = getActualNode();
385 builder.setParent(parent);
386 addChildToParent(parent, builder, containerName.getLocalName());
391 public ListSchemaNodeBuilder addListNode(final int line, final QName listName, final SchemaPath schemaPath) {
392 final ListSchemaNodeBuilder builder = new ListSchemaNodeBuilder(line, listName, schemaPath);
394 Builder parent = getActualNode();
395 builder.setParent(parent);
396 addChildToParent(parent, builder, listName.getLocalName());
401 public LeafSchemaNodeBuilder addLeafNode(final int line, final QName leafName, final SchemaPath schemaPath) {
402 final LeafSchemaNodeBuilder builder = new LeafSchemaNodeBuilder(leafName, schemaPath, line);
404 Builder parent = getActualNode();
405 builder.setParent(parent);
406 addChildToParent(parent, builder, leafName.getLocalName());
411 public LeafListSchemaNodeBuilder addLeafListNode(final int line, final QName leafListName,
412 final SchemaPath schemaPath) {
413 final LeafListSchemaNodeBuilder builder = new LeafListSchemaNodeBuilder(line, leafListName, schemaPath);
415 Builder parent = getActualNode();
416 builder.setParent(parent);
417 addChildToParent(parent, builder, leafListName.getLocalName());
423 public void addGrouping(GroupingBuilder groupingBuilder) {
424 for (GroupingBuilder gb : addedGroupings) {
425 if (gb.getQName().getLocalName().equals(groupingBuilder.getQName().getLocalName())) {
426 throw new YangParseException(name, groupingBuilder.getLine(), "Duplicate node found at line "
430 addedGroupings.add(groupingBuilder);
433 public GroupingBuilder addGrouping(final int line, final QName qname) {
434 final GroupingBuilder builder = new GroupingBuilderImpl(qname, line);
436 Builder parent = getActualNode();
437 builder.setParent(parent);
439 if (parent == null) {
440 for (GroupingBuilder child : addedGroupings) {
441 if (child.getQName().getLocalName().equals(qname.getLocalName())) {
442 throw new YangParseException(name, line, "Duplicate node found at line " + child.getLine());
445 addedGroupings.add(builder);
447 if (parent instanceof DataNodeContainerBuilder) {
448 DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parent;
449 for (DataSchemaNodeBuilder child : parentNode.getChildNodeBuilders()) {
450 if (child.getQName().getLocalName().equals(qname.getLocalName())) {
451 throw new YangParseException(name, line, "Duplicate node found at line " + child.getLine());
454 parentNode.addGrouping(builder);
455 } else if (parent instanceof RpcDefinitionBuilder) {
456 RpcDefinitionBuilder parentNode = (RpcDefinitionBuilder) parent;
457 for (GroupingBuilder child : parentNode.getGroupings()) {
458 if (child.getQName().getLocalName().equals(qname.getLocalName())) {
459 throw new YangParseException(name, line, "Duplicate node found at line " + child.getLine());
462 parentNode.addGrouping(builder);
464 throw new YangParseException(name, line, "Unresolved parent of grouping " + qname.getLocalName());
471 public AugmentationSchemaBuilder addAugment(final int line, final String augmentTargetStr) {
472 final AugmentationSchemaBuilder builder = new AugmentationSchemaBuilderImpl(line, augmentTargetStr);
474 Builder parent = getActualNode();
475 builder.setParent(parent);
477 if (parent == null) {
478 addedAugments.add(builder);
480 // augment can only be in 'module' or 'uses' statement
481 if (parent instanceof UsesNodeBuilder) {
482 ((UsesNodeBuilder) parent).addAugment(builder);
484 throw new YangParseException(name, line, "Augment can be declared only under module or uses.");
487 allAugments.add(builder);
493 public void addUsesNode(UsesNodeBuilder usesBuilder) {
494 addedUsesNodes.add(usesBuilder);
495 allUsesNodes.add(usesBuilder);
498 public UsesNodeBuilder addUsesNode(final int line, final String groupingPathStr) {
499 final UsesNodeBuilder usesBuilder = new UsesNodeBuilderImpl(line, groupingPathStr);
501 Builder parent = getActualNode();
502 usesBuilder.setParent(parent);
504 if (parent == null) {
505 addedUsesNodes.add(usesBuilder);
507 if (!(parent instanceof DataNodeContainerBuilder)) {
508 throw new YangParseException(name, line, "Unresolved parent of uses '" + groupingPathStr + "'.");
510 if (parent instanceof AugmentationSchemaBuilder) {
511 usesBuilder.setAugmenting(true);
513 ((DataNodeContainerBuilder) parent).addUsesNode(usesBuilder);
515 allUsesNodes.add(usesBuilder);
519 public void addRefine(final RefineHolder refine, final List<String> parentPath) {
520 final List<String> path = new ArrayList<String>(parentPath);
522 if (actualPath.isEmpty()) {
523 throw new YangParseException(name, refine.getLine(), "refine can be defined only in uses statement");
525 final Builder parent = getActualNode();
526 if (parent instanceof UsesNodeBuilder) {
527 ((UsesNodeBuilder) parent).addRefine(refine);
529 throw new YangParseException(name, refine.getLine(), "refine can be defined only in uses statement");
531 refine.setParent(parent);
534 path.add(refine.getName());
537 public RpcDefinitionBuilder addRpc(final int line, final QName qname) {
538 Builder parent = getActualNode();
539 if (parent != null) {
540 throw new YangParseException(name, line, "rpc can be defined only in module or submodule");
543 final RpcDefinitionBuilder rpcBuilder = new RpcDefinitionBuilder(line, qname);
544 for (RpcDefinitionBuilder rpc : addedRpcs) {
545 if (rpc.getQName().getLocalName().equals(qname.getLocalName())) {
546 throw new YangParseException(name, line, "Duplicate node found at line " + rpc.getLine());
549 addedRpcs.add(rpcBuilder);
553 public ContainerSchemaNodeBuilder addRpcInput(final SchemaPath schemaPath, final QName inputQName, final int line) {
554 final Builder parent = getActualNode();
555 if (!(parent instanceof RpcDefinitionBuilder)) {
556 throw new YangParseException(name, line, "input can be defined only in rpc statement");
558 final RpcDefinitionBuilder rpc = (RpcDefinitionBuilder) parent;
560 final ContainerSchemaNodeBuilder inputBuilder = new ContainerSchemaNodeBuilder(line, inputQName, schemaPath);
561 inputBuilder.setParent(rpc);
563 rpc.setInput(inputBuilder);
567 public ContainerSchemaNodeBuilder addRpcOutput(final SchemaPath schemaPath, final QName outputQName, final int line) {
568 final Builder parent = actualPath.getFirst();
569 if (!(parent instanceof RpcDefinitionBuilder)) {
570 throw new YangParseException(name, line, "output can be defined only in rpc statement");
572 final RpcDefinitionBuilder rpc = (RpcDefinitionBuilder) parent;
574 final ContainerSchemaNodeBuilder outputBuilder = new ContainerSchemaNodeBuilder(line, outputQName, schemaPath);
575 outputBuilder.setParent(rpc);
577 rpc.setOutput(outputBuilder);
578 return outputBuilder;
581 public NotificationBuilder addNotification(final QName notificationName, final List<String> parentPath,
583 if (!(actualPath.isEmpty())) {
584 throw new YangParseException(name, line, "notification can be defined only in module or submodule");
586 for (NotificationBuilder nb : addedNotifications) {
587 if (nb.getQName().equals(notificationName)) {
588 throw new YangParseException(name, line, "Duplicate node found at line " + nb.getLine());
592 final NotificationBuilder builder = new NotificationBuilder(line, notificationName);
593 addedNotifications.add(builder);
598 public FeatureBuilder addFeature(final int line, final QName featureName) {
599 Builder parent = getActualNode();
600 if (parent != null) {
601 throw new YangParseException(name, line, "feature can be defined only in module or submodule");
604 final FeatureBuilder builder = new FeatureBuilder(line, featureName);
605 for (FeatureBuilder fb : addedFeatures) {
606 if (fb.getQName().getLocalName().equals(featureName.getLocalName())) {
607 throw new YangParseException(name, line, "Duplicate node found at line " + fb.getLine());
610 addedFeatures.add(builder);
614 public ChoiceBuilder addChoice(final int line, final QName choiceName) {
615 final ChoiceBuilder builder = new ChoiceBuilder(line, choiceName);
617 Builder parent = getActualNode();
618 builder.setParent(parent);
619 addChildToParent(parent, builder, choiceName.getLocalName());
624 public ChoiceCaseBuilder addCase(final int line, final QName caseName) {
625 Builder parent = getActualNode();
626 if (parent == null) {
627 throw new YangParseException(name, line, "'case' parent not found");
630 final ChoiceCaseBuilder builder = new ChoiceCaseBuilder(line, caseName);
631 builder.setParent(parent);
633 if (parent instanceof ChoiceBuilder) {
634 ((ChoiceBuilder) parent).addChildNode(builder);
635 } else if (parent instanceof AugmentationSchemaBuilder) {
636 ((AugmentationSchemaBuilder) parent).addChildNode(builder);
638 throw new YangParseException(name, line, "Unresolved parent of 'case' " + caseName.getLocalName());
644 public AnyXmlBuilder addAnyXml(final int line, final QName anyXmlName, final SchemaPath schemaPath) {
645 final AnyXmlBuilder builder = new AnyXmlBuilder(line, anyXmlName, schemaPath);
647 Builder parent = getActualNode();
648 builder.setParent(parent);
649 addChildToParent(parent, builder, anyXmlName.getLocalName());
655 public void addTypedef(TypeDefinitionBuilder typedefBuilder) {
656 for (TypeDefinitionBuilder tdb : addedTypedefs) {
657 if (tdb.getQName().getLocalName().equals(typedefBuilder.getQName().getLocalName())) {
658 throw new YangParseException(name, typedefBuilder.getLine(), "Duplicate node found at line "
662 addedTypedefs.add(typedefBuilder);
665 public TypeDefinitionBuilderImpl addTypedef(final int line, final QName typeDefName) {
666 final TypeDefinitionBuilderImpl builder = new TypeDefinitionBuilderImpl(typeDefName, line);
668 Builder parent = getActualNode();
669 builder.setParent(parent);
671 if (parent == null) {
672 for (TypeDefinitionBuilder tdb : addedTypedefs) {
673 if (tdb.getQName().getLocalName().equals(builder.getQName().getLocalName())) {
674 throw new YangParseException(name, builder.getLine(), "Duplicate node found at line "
678 addedTypedefs.add(builder);
680 if (parent instanceof DataNodeContainerBuilder) {
681 DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parent;
682 for (DataSchemaNodeBuilder child : parentNode.getChildNodeBuilders()) {
683 if (child.getQName().getLocalName().equals(typeDefName.getLocalName())) {
684 throw new YangParseException(name, line, "Duplicate node found at line " + child.getLine());
687 parentNode.addTypedef(builder);
688 } else if (parent instanceof RpcDefinitionBuilder) {
689 RpcDefinitionBuilder rpcParent = (RpcDefinitionBuilder) parent;
690 for (TypeDefinitionBuilder tdb : rpcParent.getTypeDefinitions()) {
691 if (tdb.getQName().getLocalName().equals(builder.getQName().getLocalName())) {
692 throw new YangParseException(name, builder.getLine(), "Duplicate node found at line "
696 rpcParent.addTypedef(builder);
698 throw new YangParseException(name, line, "Unresolved parent of typedef " + typeDefName.getLocalName());
705 public void setType(final TypeDefinition<?> type) {
706 Builder parent = getActualNode();
707 if (parent == null || !(parent instanceof TypeAwareBuilder)) {
708 throw new YangParseException("Failed to set type '" + type.getQName().getLocalName()
709 + "'. Unknown parent node: " + parent);
711 ((TypeAwareBuilder) parent).setType(type);
714 public UnionTypeBuilder addUnionType(final List<String> currentPath, final URI namespace, final Date revision,
716 final List<String> pathToUnion = new ArrayList<String>(currentPath);
717 final UnionTypeBuilder union = new UnionTypeBuilder(line);
719 if (actualPath.isEmpty()) {
720 throw new YangParseException(line, "union error");
722 final Builder parent = actualPath.getFirst();
723 if (parent instanceof TypeAwareBuilder) {
725 ((TypeAwareBuilder) parent).setTypedef(union);
727 final List<String> path = new ArrayList<String>(pathToUnion);
730 addedUnionTypes.put(path, union);
733 throw new YangParseException(name, line, "Unresolved parent of union type.");
738 public void addIdentityrefType(final String baseString, final List<String> parentPath, final SchemaPath schemaPath,
740 final List<String> pathToIdentityref = new ArrayList<String>(parentPath);
741 final IdentityrefTypeBuilder identityref = new IdentityrefTypeBuilder(baseString, schemaPath, line);
743 if (actualPath.isEmpty()) {
744 throw new YangParseException(line, "identityref error");
746 final Builder parent = actualPath.getFirst();
747 if (parent instanceof TypeAwareBuilder) {
748 final TypeAwareBuilder typeParent = (TypeAwareBuilder) parent;
749 typeParent.setTypedef(identityref);
750 dirtyNodes.put(pathToIdentityref, typeParent);
752 throw new YangParseException(name, line, "Unresolved parent of identityref type.");
757 public DeviationBuilder addDeviation(final String targetPath, final List<String> parentPath, final int line) {
758 Builder parent = getActualNode();
759 if (parent != null) {
760 throw new YangParseException(name, line, "deviation can be defined only in module or submodule");
763 final List<String> pathToDeviation = new ArrayList<String>(parentPath);
764 pathToDeviation.add(targetPath);
765 final DeviationBuilder builder = new DeviationBuilder(targetPath, line);
766 addedDeviations.put(pathToDeviation, builder);
770 public IdentitySchemaNodeBuilder addIdentity(final QName qname, final List<String> parentPath, final int line) {
771 Builder parent = getActualNode();
772 if (parent != null) {
773 throw new YangParseException(name, line, "identity can be defined only in module or submodule");
775 for (IdentitySchemaNodeBuilder idBuilder : addedIdentities) {
776 if (idBuilder.getQName().equals(qname)) {
777 throw new YangParseException(name, line, "Duplicate node found at line " + idBuilder.getLine());
781 final IdentitySchemaNodeBuilder builder = new IdentitySchemaNodeBuilder(line, qname);
782 addedIdentities.add(builder);
787 public void addUnknownSchemaNode(UnknownSchemaNodeBuilder builder) {
788 final List<String> unPath = new ArrayList<String>();
789 for (QName name : builder.getPath().getPath()) {
790 unPath.add(name.getLocalName());
792 if (addedUnknownNodes.containsKey(unPath)) {
793 addedUnknownNodes.get(unPath).add(builder);
795 List<UnknownSchemaNodeBuilder> nodes = new ArrayList<UnknownSchemaNodeBuilder>();
797 addedUnknownNodes.put(unPath, nodes);
801 public UnknownSchemaNodeBuilder addUnknownSchemaNode(final QName qname, final List<String> parentPath,
803 final Builder parent = getActualNode();
804 final UnknownSchemaNodeBuilder builder = new UnknownSchemaNodeBuilder(line, qname);
805 builder.setParent(parent);
807 if (parent != null) {
808 if (parent instanceof SchemaNodeBuilder) {
809 ((SchemaNodeBuilder) parent).addUnknownSchemaNode(builder);
810 } else if (parent instanceof RefineHolder) {
811 ((RefineHolder) parent).addUnknownSchemaNode(builder);
813 throw new YangParseException(name, line, "Unresolved parent of unknown node '" + qname.getLocalName()
817 final List<String> unPath = new ArrayList<String>(parentPath);
818 unPath.add(qname.getLocalName());
820 if (addedUnknownNodes.containsKey(unPath)) {
821 addedUnknownNodes.get(unPath).add(builder);
823 List<UnknownSchemaNodeBuilder> nodes = new ArrayList<UnknownSchemaNodeBuilder>();
825 addedUnknownNodes.put(unPath, nodes);
831 public String toString() {
832 return ModuleBuilder.class.getSimpleName() + "[" + name + "]";
835 private final class ModuleImpl implements Module {
836 private URI namespace;
837 private final String name;
838 private Date revision;
839 private String prefix;
840 private String yangVersion;
841 private String description;
842 private String reference;
843 private String organization;
844 private String contact;
845 private Set<ModuleImport> imports = Collections.emptySet();
846 private Set<FeatureDefinition> features = Collections.emptySet();
847 private Set<TypeDefinition<?>> typeDefinitions = Collections.emptySet();
848 private Set<NotificationDefinition> notifications = Collections.emptySet();
849 private Set<AugmentationSchema> augmentations = Collections.emptySet();
850 private Set<RpcDefinition> rpcs = Collections.emptySet();
851 private Set<Deviation> deviations = Collections.emptySet();
852 private Map<QName, DataSchemaNode> childNodes = Collections.emptyMap();
853 private Set<GroupingDefinition> groupings = Collections.emptySet();
854 private Set<UsesNode> uses = Collections.emptySet();
855 private List<ExtensionDefinition> extensionNodes = Collections.emptyList();
856 private Set<IdentitySchemaNode> identities = Collections.emptySet();
857 private List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
859 private ModuleImpl(String name) {
864 public URI getNamespace() {
868 private void setNamespace(URI namespace) {
869 this.namespace = namespace;
873 public String getName() {
878 public Date getRevision() {
882 private void setRevision(Date revision) {
883 this.revision = revision;
887 public String getPrefix() {
891 private void setPrefix(String prefix) {
892 this.prefix = prefix;
896 public String getYangVersion() {
900 private void setYangVersion(String yangVersion) {
901 this.yangVersion = yangVersion;
905 public String getDescription() {
909 private void setDescription(String description) {
910 this.description = description;
914 public String getReference() {
918 private void setReference(String reference) {
919 this.reference = reference;
923 public String getOrganization() {
927 private void setOrganization(String organization) {
928 this.organization = organization;
932 public String getContact() {
936 private void setContact(String contact) {
937 this.contact = contact;
941 public Set<ModuleImport> getImports() {
945 private void setImports(Set<ModuleImport> imports) {
946 if (imports != null) {
947 this.imports = imports;
952 public Set<FeatureDefinition> getFeatures() {
956 private void setFeatures(Set<FeatureDefinition> features) {
957 if (features != null) {
958 this.features = features;
963 public Set<TypeDefinition<?>> getTypeDefinitions() {
964 return typeDefinitions;
967 private void setTypeDefinitions(Set<TypeDefinition<?>> typeDefinitions) {
968 if (typeDefinitions != null) {
969 this.typeDefinitions = typeDefinitions;
974 public Set<NotificationDefinition> getNotifications() {
975 return notifications;
978 private void setNotifications(Set<NotificationDefinition> notifications) {
979 if (notifications != null) {
980 this.notifications = notifications;
985 public Set<AugmentationSchema> getAugmentations() {
986 return augmentations;
989 private void setAugmentations(Set<AugmentationSchema> augmentations) {
990 if (augmentations != null) {
991 this.augmentations = augmentations;
996 public Set<RpcDefinition> getRpcs() {
1000 private void setRpcs(Set<RpcDefinition> rpcs) {
1007 public Set<Deviation> getDeviations() {
1011 private void setDeviations(Set<Deviation> deviations) {
1012 if (deviations != null) {
1013 this.deviations = deviations;
1018 public Set<DataSchemaNode> getChildNodes() {
1019 return new LinkedHashSet<DataSchemaNode>(childNodes.values());
1022 private void setChildNodes(Map<QName, DataSchemaNode> childNodes) {
1023 if (childNodes != null) {
1024 this.childNodes = childNodes;
1029 public Set<GroupingDefinition> getGroupings() {
1033 private void setGroupings(Set<GroupingDefinition> groupings) {
1034 if (groupings != null) {
1035 this.groupings = groupings;
1040 public Set<UsesNode> getUses() {
1044 private void setUses(Set<UsesNode> uses) {
1051 public List<ExtensionDefinition> getExtensionSchemaNodes() {
1052 return extensionNodes;
1055 private void setExtensionSchemaNodes(final List<ExtensionDefinition> extensionNodes) {
1056 if (extensionNodes != null) {
1057 this.extensionNodes = extensionNodes;
1062 public Set<IdentitySchemaNode> getIdentities() {
1066 private void setIdentities(final Set<IdentitySchemaNode> identities) {
1067 if (identities != null) {
1068 this.identities = identities;
1073 public List<UnknownSchemaNode> getUnknownSchemaNodes() {
1074 return unknownNodes;
1077 private void setUnknownSchemaNodes(final List<UnknownSchemaNode> unknownNodes) {
1078 if (unknownNodes != null) {
1079 this.unknownNodes = unknownNodes;
1084 public DataSchemaNode getDataChildByName(QName name) {
1085 return childNodes.get(name);
1089 public DataSchemaNode getDataChildByName(String name) {
1090 DataSchemaNode result = null;
1091 for (Map.Entry<QName, DataSchemaNode> entry : childNodes.entrySet()) {
1092 if (entry.getKey().getLocalName().equals(name)) {
1093 result = entry.getValue();
1101 public int hashCode() {
1102 final int prime = 31;
1104 result = prime * result + ((namespace == null) ? 0 : namespace.hashCode());
1105 result = prime * result + ((name == null) ? 0 : name.hashCode());
1106 result = prime * result + ((revision == null) ? 0 : revision.hashCode());
1107 result = prime * result + ((prefix == null) ? 0 : prefix.hashCode());
1108 result = prime * result + ((yangVersion == null) ? 0 : yangVersion.hashCode());
1113 public boolean equals(Object obj) {
1120 if (getClass() != obj.getClass()) {
1123 ModuleImpl other = (ModuleImpl) obj;
1124 if (namespace == null) {
1125 if (other.namespace != null) {
1128 } else if (!namespace.equals(other.namespace)) {
1132 if (other.name != null) {
1135 } else if (!name.equals(other.name)) {
1138 if (revision == null) {
1139 if (other.revision != null) {
1142 } else if (!revision.equals(other.revision)) {
1145 if (prefix == null) {
1146 if (other.prefix != null) {
1149 } else if (!prefix.equals(other.prefix)) {
1152 if (yangVersion == null) {
1153 if (other.yangVersion != null) {
1156 } else if (!yangVersion.equals(other.yangVersion)) {
1163 public String toString() {
1164 StringBuilder sb = new StringBuilder(ModuleImpl.class.getSimpleName());
1166 sb.append("name=" + name);
1167 sb.append(", namespace=" + namespace);
1168 sb.append(", revision=" + revision);
1169 sb.append(", prefix=" + prefix);
1170 sb.append(", yangVersion=" + yangVersion);
1172 return sb.toString();
1176 private void addChildToParent(final Builder parent, final DataSchemaNodeBuilder child, final String childLocalName) {
1177 final int line = child.getLine();
1178 if (parent == null) {
1179 // if parent == null => node is defined under module
1180 // All leafs, leaf-lists, lists, containers, choices, rpcs,
1181 // notifications, and anyxmls defined within a parent node or at the
1182 // top level of the module or its submodules share the same
1183 // identifier namespace.
1184 for (DataSchemaNodeBuilder childNode : childNodes) {
1185 if (childNode.getQName().getLocalName().equals(childLocalName)) {
1186 throw new YangParseException(name, line, "Duplicate node found at line " + childNode.getLine());
1189 for (RpcDefinitionBuilder rpc : addedRpcs) {
1190 if (rpc.getQName().getLocalName().equals(childLocalName)) {
1191 throw new YangParseException(name, line, "Duplicate node found at line " + rpc.getLine());
1194 for (NotificationBuilder notification : addedNotifications) {
1195 if (notification.getQName().getLocalName().equals(childLocalName)) {
1196 throw new YangParseException(name, line, "Duplicate node found at line " + notification.getLine());
1199 childNodes.add(child);
1201 // no need for checking rpc and notification because they can be
1202 // defined only under module or submodule
1203 if (parent instanceof DataNodeContainerBuilder) {
1204 DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parent;
1205 for (DataSchemaNodeBuilder childNode : parentNode.getChildNodeBuilders()) {
1206 if (childNode.getQName().getLocalName().equals(childLocalName)) {
1207 throw new YangParseException(name, line, "Duplicate node found at line " + childNode.getLine());
1210 parentNode.addChildNode(child);
1211 } else if (parent instanceof ChoiceBuilder) {
1212 ChoiceBuilder parentNode = (ChoiceBuilder) parent;
1213 for (ChoiceCaseBuilder caseBuilder : parentNode.getCases()) {
1214 if (caseBuilder.getQName().getLocalName().equals(childLocalName)) {
1215 throw new YangParseException(name, line, "Duplicate node found at line "
1216 + caseBuilder.getLine());
1219 parentNode.addChildNode(child);
1221 throw new YangParseException(name, line, "Unresolved parent of node '" + childLocalName + "'.");
1226 private ModuleImport createModuleImport(final String moduleName, final Date revision, final String prefix) {
1227 final ModuleImport moduleImport = new ModuleImport() {
1229 public String getModuleName() {
1234 public Date getRevision() {
1239 public String getPrefix() {
1244 public int hashCode() {
1245 final int prime = 31;
1247 result = prime * result + ((moduleName == null) ? 0 : moduleName.hashCode());
1248 result = prime * result + ((revision == null) ? 0 : revision.hashCode());
1249 result = prime * result + ((prefix == null) ? 0 : prefix.hashCode());
1254 public boolean equals(Object obj) {
1261 if (getClass() != obj.getClass()) {
1264 ModuleImport other = (ModuleImport) obj;
1265 if (getModuleName() == null) {
1266 if (other.getModuleName() != null) {
1269 } else if (!getModuleName().equals(other.getModuleName())) {
1272 if (getRevision() == null) {
1273 if (other.getRevision() != null) {
1276 } else if (!getRevision().equals(other.getRevision())) {
1279 if (getPrefix() == null) {
1280 if (other.getPrefix() != null) {
1283 } else if (!getPrefix().equals(other.getPrefix())) {
1290 public String toString() {
1291 return "ModuleImport[moduleName=" + moduleName + ", revision=" + revision + ", prefix=" + prefix + "]";
1294 return moduleImport;
1298 * Traverse through given addedUnknownNodes and add only unknown nodes
1299 * defined under module statement.
1301 * @param addedUnknownNodes
1302 * unknown node builders
1303 * @return list of all unknown nodes defined in module in lexicographical
1306 private List<UnknownSchemaNode> buildModuleUnknownNodes(
1307 final Map<List<String>, List<UnknownSchemaNodeBuilder>> addedUnknownNodes) {
1308 final List<UnknownSchemaNode> result = new ArrayList<UnknownSchemaNode>();
1309 for (Map.Entry<List<String>, List<UnknownSchemaNodeBuilder>> entry : addedUnknownNodes.entrySet()) {
1310 final List<String> path = entry.getKey();
1311 final List<UnknownSchemaNodeBuilder> child = entry.getValue();
1313 if (path.size() == 2) {
1314 for (UnknownSchemaNodeBuilder node : child) {
1315 result.add(node.build());
1319 Collections.sort(result, Comparators.SCHEMA_NODE_COMP);