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