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