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