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