Fixed tests. Added javadocs to yang-model-api.
[controller.git] / opendaylight / sal / yang-prototype / code-generator / yang-model-parser-impl / src / main / java / org / opendaylight / controller / yang / parser / builder / impl / ModuleBuilder.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.controller.yang.parser.builder.impl;
9
10 import java.net.URI;
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.List;
17 import java.util.Map;
18 import java.util.Set;
19
20 import org.opendaylight.controller.yang.common.QName;
21 import org.opendaylight.controller.yang.model.api.AugmentationSchema;
22 import org.opendaylight.controller.yang.model.api.DataSchemaNode;
23 import org.opendaylight.controller.yang.model.api.Deviation;
24 import org.opendaylight.controller.yang.model.api.ExtensionDefinition;
25 import org.opendaylight.controller.yang.model.api.FeatureDefinition;
26 import org.opendaylight.controller.yang.model.api.GroupingDefinition;
27 import org.opendaylight.controller.yang.model.api.IdentitySchemaNode;
28 import org.opendaylight.controller.yang.model.api.Module;
29 import org.opendaylight.controller.yang.model.api.ModuleImport;
30 import org.opendaylight.controller.yang.model.api.NotificationDefinition;
31 import org.opendaylight.controller.yang.model.api.RpcDefinition;
32 import org.opendaylight.controller.yang.model.api.SchemaPath;
33 import org.opendaylight.controller.yang.model.api.TypeDefinition;
34 import org.opendaylight.controller.yang.model.api.UsesNode;
35 import org.opendaylight.controller.yang.parser.builder.api.AugmentationSchemaBuilder;
36 import org.opendaylight.controller.yang.parser.builder.api.Builder;
37 import org.opendaylight.controller.yang.parser.builder.api.ChildNodeBuilder;
38 import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
39 import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
40 import org.opendaylight.controller.yang.parser.builder.api.SchemaNodeBuilder;
41 import org.opendaylight.controller.yang.parser.builder.api.TypeAwareBuilder;
42 import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionAwareBuilder;
43 import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
44 import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
45 import org.opendaylight.controller.yang.parser.util.RefineHolder;
46 import org.opendaylight.controller.yang.parser.util.YangParseException;
47
48 /**
49  * This builder builds Module object. If this module is dependent on external
50  * module/modules, these dependencies must be resolved before module is built,
51  * otherwise result may not be valid.
52  */
53 public class ModuleBuilder implements Builder {
54     private final ModuleImpl instance;
55     private final String name;
56     private URI namespace;
57     private String prefix;
58     private Date revision;
59
60     private int augmentsResolved;
61
62     private final Set<ModuleImport> imports = new HashSet<ModuleImport>();
63
64     /**
65      * All nodes, that can contain other nodes
66      */
67     private final Map<List<String>, Builder> moduleNodes = new HashMap<List<String>, Builder>();
68
69     /**
70      * Holds all child (DataSchemaNode) nodes: anyxml, choice, case, container,
71      * list, leaf, leaf-list.
72      */
73     private final Map<List<String>, DataSchemaNodeBuilder> addedChilds = new HashMap<List<String>, DataSchemaNodeBuilder>();
74
75     private final Map<List<String>, GroupingBuilder> addedGroupings = new HashMap<List<String>, GroupingBuilder>();
76     private final List<AugmentationSchemaBuilder> addedAugments = new ArrayList<AugmentationSchemaBuilder>();
77     private final Map<List<String>, UsesNodeBuilder> addedUsesNodes = new HashMap<List<String>, UsesNodeBuilder>();
78     private final Map<List<String>, RpcDefinitionBuilder> addedRpcs = new HashMap<List<String>, RpcDefinitionBuilder>();
79     private final Set<NotificationBuilder> addedNotifications = new HashSet<NotificationBuilder>();
80     private final Set<IdentitySchemaNodeBuilder> addedIdentities = new HashSet<IdentitySchemaNodeBuilder>();
81     private final Map<List<String>, FeatureBuilder> addedFeatures = new HashMap<List<String>, FeatureBuilder>();
82     private final Map<String, DeviationBuilder> addedDeviations = new HashMap<String, DeviationBuilder>();
83     private final Map<List<String>, TypeDefinitionBuilder> addedTypedefs = new HashMap<List<String>, TypeDefinitionBuilder>();
84     private final List<ExtensionBuilder> addedExtensions = new ArrayList<ExtensionBuilder>();
85     private final Set<UnknownSchemaNodeBuilder> addedUnknownNodes = new HashSet<UnknownSchemaNodeBuilder>();
86
87     private final Map<List<String>, TypeAwareBuilder> dirtyNodes = new HashMap<List<String>, TypeAwareBuilder>();
88
89     public ModuleBuilder(final String name) {
90         this.name = name;
91         instance = new ModuleImpl(name);
92     }
93
94     /**
95      * Build new Module object based on this builder.
96      */
97     @Override
98     public Module build() {
99         instance.setPrefix(prefix);
100         instance.setRevision(revision);
101         instance.setImports(imports);
102         instance.setNamespace(namespace);
103
104         // TYPEDEFS
105         final Set<TypeDefinition<?>> typedefs = buildModuleTypedefs(addedTypedefs);
106         instance.setTypeDefinitions(typedefs);
107
108         // CHILD NODES
109         final Map<QName, DataSchemaNode> childNodes = buildModuleChildNodes(addedChilds);
110         instance.setChildNodes(childNodes);
111
112         // GROUPINGS
113         final Set<GroupingDefinition> groupings = buildModuleGroupings(addedGroupings);
114         instance.setGroupings(groupings);
115
116         // USES
117         final Set<UsesNode> usesDefinitions = buildUsesNodes(addedUsesNodes);
118         instance.setUses(usesDefinitions);
119
120         // FEATURES
121         final Set<FeatureDefinition> features = buildModuleFeatures(addedFeatures);
122         instance.setFeatures(features);
123
124         // NOTIFICATIONS
125         final Set<NotificationDefinition> notifications = new HashSet<NotificationDefinition>();
126         for (NotificationBuilder entry : addedNotifications) {
127             notifications.add((NotificationDefinition) entry.build());
128         }
129         instance.setNotifications(notifications);
130
131         // AUGMENTATIONS
132         final Set<AugmentationSchema> augmentations = new HashSet<AugmentationSchema>();
133         for (AugmentationSchemaBuilder builder : addedAugments) {
134             augmentations.add(builder.build());
135         }
136         instance.setAugmentations(augmentations);
137
138         // RPCs
139         final Set<RpcDefinition> rpcs = buildModuleRpcs(addedRpcs);
140         instance.setRpcs(rpcs);
141
142         // DEVIATIONS
143         final Set<Deviation> deviations = new HashSet<Deviation>();
144         for (Map.Entry<String, DeviationBuilder> entry : addedDeviations
145                 .entrySet()) {
146             deviations.add(entry.getValue().build());
147         }
148         instance.setDeviations(deviations);
149
150         // EXTENSIONS
151         final List<ExtensionDefinition> extensions = new ArrayList<ExtensionDefinition>();
152         for (ExtensionBuilder b : addedExtensions) {
153             extensions.add(b.build());
154         }
155         instance.setExtensionSchemaNodes(extensions);
156
157         // IDENTITIES
158         final Set<IdentitySchemaNode> identities = new HashSet<IdentitySchemaNode>();
159         for (IdentitySchemaNodeBuilder idBuilder : addedIdentities) {
160             identities.add(idBuilder.build());
161         }
162         instance.setIdentities(identities);
163
164         return instance;
165     }
166
167     @Override
168     public int getLine() {
169         return 0;
170     }
171
172     public Builder getNode(final List<String> path) {
173         return moduleNodes.get(path);
174     }
175
176     public Set<DataSchemaNodeBuilder> getChildNodes() {
177         final Set<DataSchemaNodeBuilder> childNodes = new HashSet<DataSchemaNodeBuilder>();
178         for (Map.Entry<List<String>, DataSchemaNodeBuilder> entry : addedChilds
179                 .entrySet()) {
180             List<String> path = entry.getKey();
181             DataSchemaNodeBuilder child = entry.getValue();
182             if (path.size() == 2) {
183                 childNodes.add(child);
184             }
185         }
186         return childNodes;
187     }
188
189     public Map<List<String>, TypeAwareBuilder> getDirtyNodes() {
190         return dirtyNodes;
191     }
192
193     public List<AugmentationSchemaBuilder> getAddedAugments() {
194         return addedAugments;
195     }
196
197     public Set<IdentitySchemaNodeBuilder> getAddedIdentities() {
198         return addedIdentities;
199     }
200
201     public Map<List<String>, UsesNodeBuilder> getAddedUsesNodes() {
202         return addedUsesNodes;
203     }
204
205     public Set<UnknownSchemaNodeBuilder> getAddedUnknownNodes() {
206         return addedUnknownNodes;
207     }
208
209     public Set<TypeDefinitionBuilder> getModuleTypedefs() {
210         Set<TypeDefinitionBuilder> typedefs = new HashSet<TypeDefinitionBuilder>();
211         for (Map.Entry<List<String>, TypeDefinitionBuilder> entry : addedTypedefs
212                 .entrySet()) {
213             if (entry.getKey().size() == 2) {
214                 typedefs.add(entry.getValue());
215             }
216         }
217         return typedefs;
218     }
219
220     public String getName() {
221         return name;
222     }
223
224     public URI getNamespace() {
225         return namespace;
226     }
227
228     public void setNamespace(final URI namespace) {
229         this.namespace = namespace;
230     }
231
232     public String getPrefix() {
233         return prefix;
234     }
235
236     public Date getRevision() {
237         return revision;
238     }
239
240     public int getAugmentsResolved() {
241         return augmentsResolved;
242     }
243
244     public void augmentResolved() {
245         augmentsResolved++;
246     }
247
248     public void addDirtyNode(final List<String> path) {
249         final List<String> dirtyNodePath = new ArrayList<String>(path);
250         final TypeAwareBuilder nodeBuilder = (TypeAwareBuilder) moduleNodes
251                 .get(dirtyNodePath);
252         dirtyNodes.put(dirtyNodePath, nodeBuilder);
253     }
254
255     public void setRevision(final Date revision) {
256         this.revision = revision;
257     }
258
259     public void setPrefix(final String prefix) {
260         this.prefix = prefix;
261     }
262
263     public void setYangVersion(final String yangVersion) {
264         instance.setYangVersion(yangVersion);
265     }
266
267     public void setDescription(final String description) {
268         instance.setDescription(description);
269     }
270
271     public void setReference(final String reference) {
272         instance.setReference(reference);
273     }
274
275     public void setOrganization(final String organization) {
276         instance.setOrganization(organization);
277     }
278
279     public void setContact(final String contact) {
280         instance.setContact(contact);
281     }
282
283     public boolean addModuleImport(final String moduleName,
284             final Date revision, final String prefix) {
285         final ModuleImport moduleImport = createModuleImport(moduleName,
286                 revision, prefix);
287         return imports.add(moduleImport);
288     }
289
290     public Set<ModuleImport> getModuleImports() {
291         return imports;
292     }
293
294     public ExtensionBuilder addExtension(final QName qname, final int line) {
295         final ExtensionBuilder builder = new ExtensionBuilder(qname, line);
296         addedExtensions.add(builder);
297         return builder;
298     }
299
300     public ContainerSchemaNodeBuilder addContainerNode(
301             final QName containerName, final List<String> parentPath,
302             final int line) {
303         final List<String> pathToNode = new ArrayList<String>(parentPath);
304         final ContainerSchemaNodeBuilder containerBuilder = new ContainerSchemaNodeBuilder(
305                 containerName, line);
306         final ChildNodeBuilder parent = (ChildNodeBuilder) moduleNodes
307                 .get(pathToNode);
308         if (parent != null) {
309             if (parent instanceof AugmentationSchemaBuilder) {
310                 containerBuilder.setAugmenting(true);
311             }
312             parent.addChildNode(containerBuilder);
313         }
314
315         pathToNode.add(containerName.getLocalName());
316         moduleNodes.put(pathToNode, containerBuilder);
317         addedChilds.put(pathToNode, containerBuilder);
318
319         return containerBuilder;
320     }
321
322     public ListSchemaNodeBuilder addListNode(final QName listName,
323             final List<String> parentPath, final int line) {
324         final List<String> pathToNode = new ArrayList<String>(parentPath);
325         final ListSchemaNodeBuilder listBuilder = new ListSchemaNodeBuilder(
326                 listName, line);
327         final ChildNodeBuilder parent = (ChildNodeBuilder) moduleNodes
328                 .get(pathToNode);
329         if (parent != null) {
330             if (parent instanceof AugmentationSchemaBuilder) {
331                 listBuilder.setAugmenting(true);
332             }
333             parent.addChildNode(listBuilder);
334         }
335
336         pathToNode.add(listName.getLocalName());
337         moduleNodes.put(pathToNode, listBuilder);
338         addedChilds.put(pathToNode, listBuilder);
339
340         return listBuilder;
341     }
342
343     public LeafSchemaNodeBuilder addLeafNode(final QName leafName,
344             final List<String> parentPath, final int line) {
345         final List<String> pathToNode = new ArrayList<String>(parentPath);
346         final LeafSchemaNodeBuilder leafBuilder = new LeafSchemaNodeBuilder(
347                 leafName, line);
348         final ChildNodeBuilder parent = (ChildNodeBuilder) moduleNodes
349                 .get(pathToNode);
350         if (parent != null) {
351             if (parent instanceof AugmentationSchemaBuilder) {
352                 leafBuilder.setAugmenting(true);
353             }
354             parent.addChildNode(leafBuilder);
355         }
356
357         pathToNode.add(leafName.getLocalName());
358         addedChilds.put(pathToNode, leafBuilder);
359         moduleNodes.put(pathToNode, leafBuilder);
360
361         return leafBuilder;
362     }
363
364     public LeafListSchemaNodeBuilder addLeafListNode(final QName leafListName,
365             final List<String> parentPath, final int line) {
366         final List<String> pathToNode = new ArrayList<String>(parentPath);
367         final LeafListSchemaNodeBuilder leafListBuilder = new LeafListSchemaNodeBuilder(
368                 leafListName, line);
369         final ChildNodeBuilder parent = (ChildNodeBuilder) moduleNodes
370                 .get(pathToNode);
371         if (parent != null) {
372             if (parent instanceof AugmentationSchemaBuilder) {
373                 leafListBuilder.setAugmenting(true);
374             }
375             parent.addChildNode(leafListBuilder);
376         }
377
378         pathToNode.add(leafListName.getLocalName());
379         addedChilds.put(pathToNode, leafListBuilder);
380         moduleNodes.put(pathToNode, leafListBuilder);
381
382         return leafListBuilder;
383     }
384
385     public GroupingBuilder addGrouping(final QName qname,
386             final List<String> parentPath, final int line) {
387         final List<String> pathToGroup = new ArrayList<String>(parentPath);
388         final GroupingBuilder builder = new GroupingBuilderImpl(qname, line);
389         final ChildNodeBuilder parentNodeBuilder = (ChildNodeBuilder) moduleNodes
390                 .get(pathToGroup);
391         if (parentNodeBuilder != null) {
392             parentNodeBuilder.addGrouping(builder);
393         }
394
395         pathToGroup.add("grouping");
396         pathToGroup.add(qname.getLocalName());
397         moduleNodes.put(pathToGroup, builder);
398         addedGroupings.put(pathToGroup, builder);
399
400         return builder;
401     }
402
403     public AugmentationSchemaBuilder addAugment(final String name,
404             final List<String> parentPath, final int line) {
405         final List<String> pathToAugment = new ArrayList<String>(parentPath);
406         final AugmentationSchemaBuilder builder = new AugmentationSchemaBuilderImpl(
407                 name, line);
408
409         // augment can only be in 'module' or 'uses' statement
410         final UsesNodeBuilder parent = addedUsesNodes.get(pathToAugment);
411         if (parent != null) {
412             parent.addAugment(builder);
413         }
414
415         pathToAugment.add(name);
416         moduleNodes.put(pathToAugment, builder);
417         addedAugments.add(builder);
418
419         return builder;
420     }
421
422     public UsesNodeBuilder addUsesNode(final String groupingPathStr,
423             final List<String> parentPath, final int line) {
424         final List<String> pathToUses = new ArrayList<String>(parentPath);
425         final UsesNodeBuilder usesBuilder = new UsesNodeBuilderImpl(
426                 groupingPathStr, line);
427         final ChildNodeBuilder parent = (ChildNodeBuilder) moduleNodes
428                 .get(pathToUses);
429         if (parent != null) {
430             parent.addUsesNode(usesBuilder);
431         }
432
433         pathToUses.add(groupingPathStr);
434         addedUsesNodes.put(pathToUses, usesBuilder);
435         moduleNodes.put(pathToUses, usesBuilder);
436         return usesBuilder;
437     }
438
439     public void addRefine(final RefineHolder refine,
440             final List<String> parentPath) {
441         final List<String> path = new ArrayList<String>(parentPath);
442         final Builder parent = moduleNodes.get(path);
443         if (!(parent instanceof UsesNodeBuilder)) {
444             throw new YangParseException("Failed to parse refine "
445                     + refine.getName());
446         }
447         UsesNodeBuilder usesBuilder = (UsesNodeBuilder) parent;
448         usesBuilder.addRefine(refine);
449         path.add(refine.getName());
450         moduleNodes.put(path, refine);
451     }
452
453     public RpcDefinitionBuilder addRpc(final QName qname,
454             final List<String> parentPath, final int line) {
455         final List<String> pathToRpc = new ArrayList<String>(parentPath);
456         final RpcDefinitionBuilder rpcBuilder = new RpcDefinitionBuilder(qname,
457                 line);
458
459         pathToRpc.add(qname.getLocalName());
460         addedRpcs.put(pathToRpc, rpcBuilder);
461
462         final QName inputQName = new QName(qname.getNamespace(),
463                 qname.getRevision(), qname.getPrefix(), "input");
464         final ContainerSchemaNodeBuilder inputBuilder = new ContainerSchemaNodeBuilder(
465                 inputQName, line);
466         final List<String> pathToInput = new ArrayList<String>(pathToRpc);
467         pathToInput.add("input");
468         moduleNodes.put(pathToInput, inputBuilder);
469         rpcBuilder.setInput(inputBuilder);
470
471         final QName outputQName = new QName(qname.getNamespace(),
472                 qname.getRevision(), qname.getPrefix(), "output");
473         final ContainerSchemaNodeBuilder outputBuilder = new ContainerSchemaNodeBuilder(
474                 outputQName, line);
475         final List<String> pathToOutput = new ArrayList<String>(pathToRpc);
476         pathToOutput.add("output");
477         moduleNodes.put(pathToOutput, outputBuilder);
478         rpcBuilder.setOutput(outputBuilder);
479
480         return rpcBuilder;
481     }
482
483     public NotificationBuilder addNotification(final QName notificationName,
484             final List<String> parentPath, final int line) {
485         final List<String> pathToNotification = new ArrayList<String>(
486                 parentPath);
487
488         NotificationBuilder builder = new NotificationBuilder(notificationName,
489                 line);
490
491         pathToNotification.add(notificationName.getLocalName());
492         moduleNodes.put(pathToNotification, builder);
493         addedNotifications.add(builder);
494
495         return builder;
496     }
497
498     public FeatureBuilder addFeature(final QName featureName,
499             final List<String> parentPath, final int line) {
500         List<String> pathToFeature = new ArrayList<String>(parentPath);
501         pathToFeature.add(featureName.getLocalName());
502
503         FeatureBuilder builder = new FeatureBuilder(featureName, line);
504         addedFeatures.put(pathToFeature, builder);
505         return builder;
506     }
507
508     public ChoiceBuilder addChoice(final QName choiceName,
509             final List<String> parentPath, final int line) {
510         List<String> pathToChoice = new ArrayList<String>(parentPath);
511         ChoiceBuilder builder = new ChoiceBuilder(choiceName, line);
512
513         final ChildNodeBuilder parent = (ChildNodeBuilder) moduleNodes
514                 .get(pathToChoice);
515         if (parent != null) {
516             if (parent instanceof AugmentationSchemaBuilder) {
517                 builder.setAugmenting(true);
518             }
519             parent.addChildNode(builder);
520         }
521
522         pathToChoice.add(choiceName.getLocalName());
523         addedChilds.put(pathToChoice, builder);
524         moduleNodes.put(pathToChoice, builder);
525
526         return builder;
527     }
528
529     public ChoiceCaseBuilder addCase(final QName caseName,
530             final List<String> parentPath, final int line) {
531         List<String> pathToCase = new ArrayList<String>(parentPath);
532         ChoiceCaseBuilder builder = new ChoiceCaseBuilder(caseName, line);
533
534         final ChildNodeBuilder parent = (ChildNodeBuilder) moduleNodes
535                 .get(pathToCase);
536         if (parent != null) {
537             if (parent instanceof AugmentationSchemaBuilder) {
538                 builder.setAugmenting(true);
539             }
540             parent.addChildNode(builder);
541         }
542
543         pathToCase.add(caseName.getLocalName());
544         moduleNodes.put(pathToCase, builder);
545
546         return builder;
547     }
548
549     public AnyXmlBuilder addAnyXml(final QName anyXmlName,
550             final List<String> parentPath, final int line) {
551         List<String> pathToAnyXml = new ArrayList<String>(parentPath);
552         AnyXmlBuilder builder = new AnyXmlBuilder(anyXmlName, line);
553
554         final ChildNodeBuilder parent = (ChildNodeBuilder) moduleNodes
555                 .get(pathToAnyXml);
556         if (parent != null) {
557             if (parent instanceof AugmentationSchemaBuilder) {
558                 throw new UnsupportedOperationException(
559                         "An anyxml node cannot be augmented.");
560             }
561             parent.addChildNode(builder);
562         }
563
564         pathToAnyXml.add(anyXmlName.getLocalName());
565         addedChilds.put(pathToAnyXml, builder);
566         moduleNodes.put(pathToAnyXml, builder);
567
568         return builder;
569     }
570
571     public TypedefBuilder addTypedef(final QName typeDefName,
572             final List<String> parentPath, final int line) {
573         List<String> pathToType = new ArrayList<String>(parentPath);
574         TypedefBuilder builder = new TypedefBuilder(typeDefName, line);
575         TypeDefinitionAwareBuilder parent = (TypeDefinitionAwareBuilder) moduleNodes
576                 .get(pathToType);
577         if (parent != null) {
578             parent.addTypedef(builder);
579         }
580         pathToType.add(typeDefName.getLocalName());
581         addedTypedefs.put(pathToType, builder);
582         moduleNodes.put(pathToType, builder);
583         return builder;
584     }
585
586     public void setType(TypeDefinition<?> type, List<String> parentPath) {
587         TypeAwareBuilder parent = (TypeAwareBuilder) moduleNodes
588                 .get(parentPath);
589         if (parent == null) {
590             throw new YangParseException("Failed to set type '"
591                     + type.getQName().getLocalName()
592                     + "'. Parent node not found.");
593         }
594         parent.setType(type);
595     }
596
597     public void addUnionType(final List<String> actualPath,
598             final URI namespace, final Date revision, final int line) {
599         List<String> pathToUnion = new ArrayList<String>(actualPath);
600         TypeAwareBuilder parent = (TypeAwareBuilder) moduleNodes
601                 .get(pathToUnion);
602         UnionTypeBuilder union = new UnionTypeBuilder(pathToUnion, namespace,
603                 revision, line);
604         parent.setType(union);
605
606         List<String> path = new ArrayList<String>(pathToUnion);
607         path.add("union");
608
609         moduleNodes.put(path, union);
610     }
611
612     public void addIdentityrefType(final String baseString,
613             final List<String> parentPath, final SchemaPath schemaPath,
614             final int line) {
615         List<String> pathToIdentityref = new ArrayList<String>(parentPath);
616         TypeAwareBuilder parent = (TypeAwareBuilder) moduleNodes
617                 .get(pathToIdentityref);
618         IdentityrefTypeBuilder identityref = new IdentityrefTypeBuilder(
619                 baseString, schemaPath, line);
620         parent.setType(identityref);
621         dirtyNodes.put(pathToIdentityref, parent);
622     }
623
624     public DeviationBuilder addDeviation(final String targetPath,
625             final List<String> parentPath, final int line) {
626         final List<String> pathToDeviation = new ArrayList<String>(parentPath);
627         pathToDeviation.add(targetPath);
628         DeviationBuilder builder = new DeviationBuilder(targetPath, line);
629         addedDeviations.put(targetPath, builder);
630         moduleNodes.put(pathToDeviation, builder);
631         return builder;
632     }
633
634     public IdentitySchemaNodeBuilder addIdentity(final QName qname,
635             final List<String> parentPath, final int line) {
636         final List<String> pathToIdentity = new ArrayList<String>(parentPath);
637         final IdentitySchemaNodeBuilder builder = new IdentitySchemaNodeBuilder(
638                 qname, line);
639         pathToIdentity.add(qname.getLocalName());
640         moduleNodes.put(pathToIdentity, builder);
641         addedIdentities.add(builder);
642         return builder;
643     }
644
645     public void addConfiguration(boolean configuration, List<String> parentPath) {
646         Builder builder = moduleNodes.get(parentPath);
647         // current api did not support adding config to deviate
648         if (!(builder instanceof DeviationBuilder)) {
649             DataSchemaNodeBuilder configBuilder = (DataSchemaNodeBuilder) moduleNodes
650                     .get(parentPath);
651             configBuilder.setConfiguration(configuration);
652         }
653     }
654
655     public UnknownSchemaNodeBuilder addUnknownSchemaNode(final QName qname,
656             final List<String> parentPath, final int line) {
657         final List<String> pathToUnknown = new ArrayList<String>(parentPath);
658         final UnknownSchemaNodeBuilder builder = new UnknownSchemaNodeBuilder(
659                 qname, line);
660         final Builder parent = moduleNodes.get(pathToUnknown);
661         if (parent instanceof RefineHolder) {
662             ((RefineHolder) parent).addUnknownSchemaNode(builder);
663         } else if (parent instanceof SchemaNodeBuilder) {
664             ((SchemaNodeBuilder) parent).addUnknownSchemaNode(builder);
665         }
666         addedUnknownNodes.add(builder);
667         return builder;
668     }
669
670     private class ModuleImpl implements Module {
671         private URI namespace;
672         private final String name;
673         private Date revision;
674         private String prefix;
675         private String yangVersion;
676         private String description;
677         private String reference;
678         private String organization;
679         private String contact;
680         private Set<ModuleImport> imports = Collections.emptySet();
681         private Set<FeatureDefinition> features = Collections.emptySet();
682         private Set<TypeDefinition<?>> typeDefinitions = Collections.emptySet();
683         private Set<NotificationDefinition> notifications = Collections
684                 .emptySet();
685         private Set<AugmentationSchema> augmentations = Collections.emptySet();
686         private Set<RpcDefinition> rpcs = Collections.emptySet();
687         private Set<Deviation> deviations = Collections.emptySet();
688         private Map<QName, DataSchemaNode> childNodes = Collections.emptyMap();
689         private Set<GroupingDefinition> groupings = Collections.emptySet();
690         private Set<UsesNode> uses = Collections.emptySet();
691         private List<ExtensionDefinition> extensionNodes = Collections
692                 .emptyList();
693         private Set<IdentitySchemaNode> identities = Collections.emptySet();
694
695         private ModuleImpl(String name) {
696             this.name = name;
697         }
698
699         @Override
700         public URI getNamespace() {
701             return namespace;
702         }
703
704         private void setNamespace(URI namespace) {
705             this.namespace = namespace;
706         }
707
708         @Override
709         public String getName() {
710             return name;
711         }
712
713         @Override
714         public Date getRevision() {
715             return revision;
716         }
717
718         private void setRevision(Date revision) {
719             this.revision = revision;
720         }
721
722         @Override
723         public String getPrefix() {
724             return prefix;
725         }
726
727         private void setPrefix(String prefix) {
728             this.prefix = prefix;
729         }
730
731         @Override
732         public String getYangVersion() {
733             return yangVersion;
734         }
735
736         private void setYangVersion(String yangVersion) {
737             this.yangVersion = yangVersion;
738         }
739
740         @Override
741         public String getDescription() {
742             return description;
743         }
744
745         private void setDescription(String description) {
746             this.description = description;
747         }
748
749         @Override
750         public String getReference() {
751             return reference;
752         }
753
754         private void setReference(String reference) {
755             this.reference = reference;
756         }
757
758         @Override
759         public String getOrganization() {
760             return organization;
761         }
762
763         private void setOrganization(String organization) {
764             this.organization = organization;
765         }
766
767         @Override
768         public String getContact() {
769             return contact;
770         }
771
772         private void setContact(String contact) {
773             this.contact = contact;
774         }
775
776         @Override
777         public Set<ModuleImport> getImports() {
778             return imports;
779         }
780
781         private void setImports(Set<ModuleImport> imports) {
782             if (imports != null) {
783                 this.imports = imports;
784             }
785         }
786
787         @Override
788         public Set<FeatureDefinition> getFeatures() {
789             return features;
790         }
791
792         private void setFeatures(Set<FeatureDefinition> features) {
793             if (features != null) {
794                 this.features = features;
795             }
796         }
797
798         @Override
799         public Set<TypeDefinition<?>> getTypeDefinitions() {
800             return typeDefinitions;
801         }
802
803         private void setTypeDefinitions(Set<TypeDefinition<?>> typeDefinitions) {
804             if (typeDefinitions != null) {
805                 this.typeDefinitions = typeDefinitions;
806             }
807         }
808
809         @Override
810         public Set<NotificationDefinition> getNotifications() {
811             return notifications;
812         }
813
814         private void setNotifications(Set<NotificationDefinition> notifications) {
815             if (notifications != null) {
816                 this.notifications = notifications;
817             }
818         }
819
820         @Override
821         public Set<AugmentationSchema> getAugmentations() {
822             return augmentations;
823         }
824
825         private void setAugmentations(Set<AugmentationSchema> augmentations) {
826             if (augmentations != null) {
827                 this.augmentations = augmentations;
828             }
829         }
830
831         @Override
832         public Set<RpcDefinition> getRpcs() {
833             return rpcs;
834         }
835
836         private void setRpcs(Set<RpcDefinition> rpcs) {
837             if (rpcs != null) {
838                 this.rpcs = rpcs;
839             }
840         }
841
842         @Override
843         public Set<Deviation> getDeviations() {
844             return deviations;
845         }
846
847         private void setDeviations(Set<Deviation> deviations) {
848             if (deviations != null) {
849                 this.deviations = deviations;
850             }
851         }
852
853         @Override
854         public Set<DataSchemaNode> getChildNodes() {
855             return new HashSet<DataSchemaNode>(childNodes.values());
856         }
857
858         private void setChildNodes(Map<QName, DataSchemaNode> childNodes) {
859             if (childNodes != null) {
860                 this.childNodes = childNodes;
861             }
862         }
863
864         @Override
865         public Set<GroupingDefinition> getGroupings() {
866             return groupings;
867         }
868
869         private void setGroupings(Set<GroupingDefinition> groupings) {
870             if (groupings != null) {
871                 this.groupings = groupings;
872             }
873         }
874
875         @Override
876         public Set<UsesNode> getUses() {
877             return uses;
878         }
879
880         private void setUses(Set<UsesNode> uses) {
881             if (uses != null) {
882                 this.uses = uses;
883             }
884         }
885
886         @Override
887         public List<ExtensionDefinition> getExtensionSchemaNodes() {
888             return extensionNodes;
889         }
890
891         private void setExtensionSchemaNodes(
892                 List<ExtensionDefinition> extensionNodes) {
893             if (extensionNodes != null) {
894                 this.extensionNodes = extensionNodes;
895             }
896         }
897
898         @Override
899         public Set<IdentitySchemaNode> getIdentities() {
900             return identities;
901         }
902
903         private void setIdentities(Set<IdentitySchemaNode> identities) {
904             if (identities != null) {
905                 this.identities = identities;
906             }
907         }
908
909         @Override
910         public DataSchemaNode getDataChildByName(QName name) {
911             return childNodes.get(name);
912         }
913
914         @Override
915         public DataSchemaNode getDataChildByName(String name) {
916             DataSchemaNode result = null;
917             for (Map.Entry<QName, DataSchemaNode> entry : childNodes.entrySet()) {
918                 if (entry.getKey().getLocalName().equals(name)) {
919                     result = entry.getValue();
920                     break;
921                 }
922             }
923             return result;
924         }
925
926         @Override
927         public int hashCode() {
928             final int prime = 31;
929             int result = 1;
930             result = prime * result
931                     + ((namespace == null) ? 0 : namespace.hashCode());
932             result = prime * result + ((name == null) ? 0 : name.hashCode());
933             result = prime * result
934                     + ((revision == null) ? 0 : revision.hashCode());
935             result = prime * result
936                     + ((prefix == null) ? 0 : prefix.hashCode());
937             result = prime * result
938                     + ((yangVersion == null) ? 0 : yangVersion.hashCode());
939             return result;
940         }
941
942         @Override
943         public boolean equals(Object obj) {
944             if (this == obj) {
945                 return true;
946             }
947             if (obj == null) {
948                 return false;
949             }
950             if (getClass() != obj.getClass()) {
951                 return false;
952             }
953             ModuleImpl other = (ModuleImpl) obj;
954             if (namespace == null) {
955                 if (other.namespace != null) {
956                     return false;
957                 }
958             } else if (!namespace.equals(other.namespace)) {
959                 return false;
960             }
961             if (name == null) {
962                 if (other.name != null) {
963                     return false;
964                 }
965             } else if (!name.equals(other.name)) {
966                 return false;
967             }
968             if (revision == null) {
969                 if (other.revision != null) {
970                     return false;
971                 }
972             } else if (!revision.equals(other.revision)) {
973                 return false;
974             }
975             if (prefix == null) {
976                 if (other.prefix != null) {
977                     return false;
978                 }
979             } else if (!prefix.equals(other.prefix)) {
980                 return false;
981             }
982             if (yangVersion == null) {
983                 if (other.yangVersion != null) {
984                     return false;
985                 }
986             } else if (!yangVersion.equals(other.yangVersion)) {
987                 return false;
988             }
989             return true;
990         }
991
992         @Override
993         public String toString() {
994             StringBuilder sb = new StringBuilder(
995                     ModuleImpl.class.getSimpleName());
996             sb.append("[");
997             sb.append("name=" + name);
998             sb.append(", namespace=" + namespace);
999             sb.append(", revision=" + revision);
1000             sb.append(", prefix=" + prefix);
1001             sb.append(", yangVersion=" + yangVersion);
1002             sb.append("]");
1003             return sb.toString();
1004         }
1005     }
1006
1007     private ModuleImport createModuleImport(final String moduleName,
1008             final Date revision, final String prefix) {
1009         ModuleImport moduleImport = new ModuleImport() {
1010             @Override
1011             public String getModuleName() {
1012                 return moduleName;
1013             }
1014
1015             @Override
1016             public Date getRevision() {
1017                 return revision;
1018             }
1019
1020             @Override
1021             public String getPrefix() {
1022                 return prefix;
1023             }
1024
1025             @Override
1026             public int hashCode() {
1027                 final int prime = 31;
1028                 int result = 1;
1029                 result = prime * result
1030                         + ((moduleName == null) ? 0 : moduleName.hashCode());
1031                 result = prime * result
1032                         + ((revision == null) ? 0 : revision.hashCode());
1033                 result = prime * result
1034                         + ((prefix == null) ? 0 : prefix.hashCode());
1035                 return result;
1036             }
1037
1038             @Override
1039             public boolean equals(Object obj) {
1040                 if (this == obj) {
1041                     return true;
1042                 }
1043                 if (obj == null) {
1044                     return false;
1045                 }
1046                 if (getClass() != obj.getClass()) {
1047                     return false;
1048                 }
1049                 ModuleImport other = (ModuleImport) obj;
1050                 if (getModuleName() == null) {
1051                     if (other.getModuleName() != null) {
1052                         return false;
1053                     }
1054                 } else if (!getModuleName().equals(other.getModuleName())) {
1055                     return false;
1056                 }
1057                 if (getRevision() == null) {
1058                     if (other.getRevision() != null) {
1059                         return false;
1060                     }
1061                 } else if (!getRevision().equals(other.getRevision())) {
1062                     return false;
1063                 }
1064                 if (getPrefix() == null) {
1065                     if (other.getPrefix() != null) {
1066                         return false;
1067                     }
1068                 } else if (!getPrefix().equals(other.getPrefix())) {
1069                     return false;
1070                 }
1071                 return true;
1072             }
1073
1074             @Override
1075             public String toString() {
1076                 return "ModuleImport[moduleName=" + moduleName + ", revision="
1077                         + revision + ", prefix=" + prefix + "]";
1078             }
1079         };
1080         return moduleImport;
1081     }
1082
1083     /**
1084      * Traverse through given addedChilds and add only direct module childs.
1085      * Direct module child path size is 2 (1. module name, 2. child name).
1086      *
1087      * @param addedChilds
1088      * @return map of children, where key is child QName and value is child
1089      *         itself
1090      */
1091     private Map<QName, DataSchemaNode> buildModuleChildNodes(
1092             Map<List<String>, DataSchemaNodeBuilder> addedChilds) {
1093         final Map<QName, DataSchemaNode> childNodes = new HashMap<QName, DataSchemaNode>();
1094         for (Map.Entry<List<String>, DataSchemaNodeBuilder> entry : addedChilds
1095                 .entrySet()) {
1096             List<String> path = entry.getKey();
1097             DataSchemaNodeBuilder child = entry.getValue();
1098             if (path.size() == 2) {
1099                 DataSchemaNode node = child.build();
1100                 QName qname = node.getQName();
1101                 childNodes.put(qname, node);
1102             }
1103         }
1104         return childNodes;
1105     }
1106
1107     /**
1108      * Traverse through given addedGroupings and add only direct module
1109      * groupings. Direct module grouping path size is 2 (1. module name, 2.
1110      * grouping name).
1111      *
1112      * @param addedGroupings
1113      * @return set of built GroupingDefinition objects
1114      */
1115     private Set<GroupingDefinition> buildModuleGroupings(
1116             Map<List<String>, GroupingBuilder> addedGroupings) {
1117         final Set<GroupingDefinition> groupings = new HashSet<GroupingDefinition>();
1118         for (Map.Entry<List<String>, GroupingBuilder> entry : addedGroupings
1119                 .entrySet()) {
1120             if (entry.getKey().size() == 2) {
1121                 groupings.add(entry.getValue().build());
1122             }
1123         }
1124         return groupings;
1125     }
1126
1127     /**
1128      * Traverse through given addedRpcs and build RpcDefinition objects.
1129      *
1130      * @param addedRpcs
1131      * @return set of built RpcDefinition objects
1132      */
1133     private Set<RpcDefinition> buildModuleRpcs(
1134             Map<List<String>, RpcDefinitionBuilder> addedRpcs) {
1135         final Set<RpcDefinition> rpcs = new HashSet<RpcDefinition>();
1136         RpcDefinitionBuilder builder;
1137         for (Map.Entry<List<String>, RpcDefinitionBuilder> entry : addedRpcs
1138                 .entrySet()) {
1139             builder = entry.getValue();
1140             RpcDefinition rpc = builder.build();
1141             rpcs.add(rpc);
1142         }
1143         return rpcs;
1144     }
1145
1146     /**
1147      * Traverse through given addedTypedefs and add only direct module typedef
1148      * statements. Direct module typedef path size is 2 (1. module name, 2.
1149      * typedef name).
1150      *
1151      * @param addedTypedefs
1152      * @return set of built module typedef statements
1153      */
1154     private Set<TypeDefinition<?>> buildModuleTypedefs(
1155             Map<List<String>, TypeDefinitionBuilder> addedTypedefs) {
1156         Set<TypeDefinition<?>> typedefs = new HashSet<TypeDefinition<?>>();
1157         for (Map.Entry<List<String>, TypeDefinitionBuilder> entry : addedTypedefs
1158                 .entrySet()) {
1159             List<String> key = entry.getKey();
1160             TypeDefinitionBuilder typedefBuilder = entry.getValue();
1161             if (key.size() == 2) {
1162                 TypeDefinition<? extends TypeDefinition<?>> node = typedefBuilder
1163                         .build();
1164                 typedefs.add(node);
1165             }
1166         }
1167         return typedefs;
1168     }
1169
1170     /**
1171      * Traverse through given addedUsesNodes and add only direct module uses
1172      * nodes. Direct module uses node path size is 2 (1. module name, 2. uses
1173      * name).
1174      *
1175      * @param addedUsesNodes
1176      * @return set of built module uses nodes
1177      */
1178     private Set<UsesNode> buildUsesNodes(
1179             Map<List<String>, UsesNodeBuilder> addedUsesNodes) {
1180         final Set<UsesNode> usesNodeDefs = new HashSet<UsesNode>();
1181         for (Map.Entry<List<String>, UsesNodeBuilder> entry : addedUsesNodes
1182                 .entrySet()) {
1183             if (entry.getKey().size() == 2) {
1184                 usesNodeDefs.add(entry.getValue().build());
1185             }
1186         }
1187         return usesNodeDefs;
1188     }
1189
1190     /**
1191      * Traverse through given addedFeatures and add only direct module features.
1192      * Direct module feature path size is 2 (1. module name, 2. feature name).
1193      *
1194      * @param addedFeatures
1195      * @return set of built module features
1196      */
1197     private Set<FeatureDefinition> buildModuleFeatures(
1198             Map<List<String>, FeatureBuilder> addedFeatures) {
1199         Set<FeatureDefinition> features = new HashSet<FeatureDefinition>();
1200         for (Map.Entry<List<String>, FeatureBuilder> entry : addedFeatures
1201                 .entrySet()) {
1202             if (entry.getKey().size() == 2) {
1203                 features.add(entry.getValue().build());
1204             }
1205         }
1206         return features;
1207     }
1208
1209 }