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