Fixed resolving of schema path and qname for nodes added by augmentation.
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / builder / impl / ContainerSchemaNodeBuilder.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.yangtools.yang.parser.builder.impl;
9
10 import java.util.ArrayList;
11 import java.util.Collections;
12 import java.util.HashSet;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.Set;
16 import java.util.TreeMap;
17 import java.util.TreeSet;
18
19 import org.opendaylight.yangtools.yang.common.QName;
20 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
21 import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition;
22 import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode;
23 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
24 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
25 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
26 import org.opendaylight.yangtools.yang.model.api.Status;
27 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
28 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
29 import org.opendaylight.yangtools.yang.model.api.UsesNode;
30 import org.opendaylight.yangtools.yang.parser.builder.api.AbstractDataNodeContainerBuilder;
31 import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationSchemaBuilder;
32 import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationTargetBuilder;
33 import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
34 import org.opendaylight.yangtools.yang.parser.builder.api.GroupingBuilder;
35 import org.opendaylight.yangtools.yang.parser.builder.api.GroupingMember;
36 import org.opendaylight.yangtools.yang.parser.builder.api.TypeDefinitionBuilder;
37 import org.opendaylight.yangtools.yang.parser.builder.api.UsesNodeBuilder;
38 import org.opendaylight.yangtools.yang.parser.util.Comparators;
39 import org.opendaylight.yangtools.yang.parser.util.YangParseException;
40
41 public final class ContainerSchemaNodeBuilder extends AbstractDataNodeContainerBuilder implements
42         AugmentationTargetBuilder, DataSchemaNodeBuilder, GroupingMember {
43     private boolean isBuilt;
44     private final ContainerSchemaNodeImpl instance;
45
46     // SchemaNode args
47     private SchemaPath schemaPath;
48     private String description;
49     private String reference;
50     private Status status = Status.CURRENT;
51     // DataSchemaNode args
52     private boolean augmenting;
53     private boolean addedByUses;
54     private Boolean configuration;
55     private final ConstraintsBuilder constraints;
56     // DataNodeContainer args
57     private Set<TypeDefinition<?>> typedefs;
58     private final Set<TypeDefinitionBuilder> addedTypedefs = new HashSet<TypeDefinitionBuilder>();
59     private Set<UsesNode> usesNodes;
60     private final Set<UsesNodeBuilder> addedUsesNodes = new HashSet<UsesNodeBuilder>();
61     // AugmentationTarget args
62     private Set<AugmentationSchema> augmentations;
63     private final Set<AugmentationSchemaBuilder> addedAugmentations = new HashSet<AugmentationSchemaBuilder>();
64     // ContainerSchemaNode args
65     private boolean presence;
66
67     public ContainerSchemaNodeBuilder(final String moduleName, final int line, final QName qname,
68             final SchemaPath schemaPath) {
69         super(moduleName, line, qname);
70         this.schemaPath = schemaPath;
71         instance = new ContainerSchemaNodeImpl(qname);
72         constraints = new ConstraintsBuilder(moduleName, line);
73     }
74
75     @Override
76     public ContainerSchemaNode build() {
77         if (!isBuilt) {
78             instance.setPath(schemaPath);
79             instance.setDescription(description);
80             instance.setReference(reference);
81             instance.setStatus(status);
82             instance.setPresenceContainer(presence);
83             instance.setAugmenting(augmenting);
84             instance.setAddedByUses(addedByUses);
85
86             // if this builder represents rpc input or output, it can has
87             // configuration value set to null
88             if (configuration == null) {
89                 configuration = false;
90             }
91             instance.setConfiguration(configuration);
92
93             // USES
94             if (usesNodes == null) {
95                 usesNodes = new HashSet<UsesNode>();
96                 for (UsesNodeBuilder builder : addedUsesNodes) {
97                     usesNodes.add(builder.build());
98                 }
99             }
100             instance.setUses(usesNodes);
101
102             // CHILD NODES
103             final Map<QName, DataSchemaNode> childs = new TreeMap<QName, DataSchemaNode>(Comparators.QNAME_COMP);
104             if (childNodes == null || childNodes.isEmpty()) {
105                 for (DataSchemaNodeBuilder node : addedChildNodes) {
106                     childs.put(node.getQName(), node.build());
107                 }
108             } else {
109                 for (DataSchemaNode node : childNodes) {
110                     childs.put(node.getQName(), node);
111                 }
112             }
113             instance.setChildNodes(childs);
114
115             // GROUPINGS
116             if (groupings == null) {
117                 groupings = new TreeSet<GroupingDefinition>(Comparators.SCHEMA_NODE_COMP);
118                 for (GroupingBuilder builder : addedGroupings) {
119                     groupings.add(builder.build());
120                 }
121             }
122             instance.setGroupings(groupings);
123
124             // TYPEDEFS
125             if (typedefs == null) {
126                 typedefs = new TreeSet<TypeDefinition<?>>(Comparators.SCHEMA_NODE_COMP);
127                 for (TypeDefinitionBuilder entry : addedTypedefs) {
128                     typedefs.add(entry.build());
129                 }
130             }
131             instance.setTypeDefinitions(typedefs);
132
133             // AUGMENTATIONS
134             if (augmentations == null) {
135                 augmentations = new HashSet<AugmentationSchema>();
136                 for (AugmentationSchemaBuilder builder : addedAugmentations) {
137                     augmentations.add(builder.build());
138                 }
139             }
140             instance.setAvailableAugmentations(augmentations);
141
142             // UNKNOWN NODES
143             if (unknownNodes == null) {
144                 unknownNodes = new ArrayList<UnknownSchemaNode>();
145                 for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
146                     unknownNodes.add(b.build());
147                 }
148                 Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
149             }
150             instance.setUnknownSchemaNodes(unknownNodes);
151
152             instance.setConstraints(constraints.build());
153             instance.setAvailableAugmentations(augmentations);
154
155             isBuilt = true;
156         }
157         return instance;
158     }
159
160     @Override
161     public void rebuild() {
162         isBuilt = false;
163         build();
164     }
165
166     @Override
167     public void setQName(QName qname) {
168         this.qname = qname;
169     }
170
171     @Override
172     public Set<TypeDefinitionBuilder> getTypeDefinitionBuilders() {
173         return addedTypedefs;
174     }
175
176     @Override
177     public void addTypedef(final TypeDefinitionBuilder type) {
178         String typeName = type.getQName().getLocalName();
179         for (TypeDefinitionBuilder addedTypedef : addedTypedefs) {
180             throw new YangParseException(moduleName, type.getLine(), "Can not add typedef '" + typeName
181                     + "': typedef with same name already declared at line " + addedTypedef.getLine());
182         }
183         addedTypedefs.add(type);
184     }
185
186     public void setTypedefs(final Set<TypeDefinition<?>> typedefs) {
187         this.typedefs = typedefs;
188     }
189
190     public Set<AugmentationSchemaBuilder> getAugmentations() {
191         return addedAugmentations;
192     }
193
194     @Override
195     public void addAugmentation(AugmentationSchemaBuilder augment) {
196         addedAugmentations.add(augment);
197     }
198
199     public void setAugmentations(final Set<AugmentationSchema> augmentations) {
200         this.augmentations = augmentations;
201     }
202
203     public SchemaPath getPath() {
204         return schemaPath;
205     }
206
207     @Override
208     public void setPath(final SchemaPath schemaPath) {
209         this.schemaPath = schemaPath;
210     }
211
212     @Override
213     public String getDescription() {
214         return description;
215     }
216
217     @Override
218     public void setDescription(final String description) {
219         this.description = description;
220     }
221
222     @Override
223     public String getReference() {
224         return reference;
225     }
226
227     @Override
228     public void setReference(String reference) {
229         this.reference = reference;
230     }
231
232     @Override
233     public Status getStatus() {
234         return status;
235     }
236
237     @Override
238     public void setStatus(Status status) {
239         if (status != null) {
240             this.status = status;
241         }
242     }
243
244     @Override
245     public boolean isAugmenting() {
246         return augmenting;
247     }
248
249     @Override
250     public void setAugmenting(boolean augmenting) {
251         this.augmenting = augmenting;
252     }
253
254     @Override
255     public boolean isAddedByUses() {
256         return addedByUses;
257     }
258
259     @Override
260     public void setAddedByUses(final boolean addedByUses) {
261         this.addedByUses = addedByUses;
262     }
263
264     @Override
265     public Boolean isConfiguration() {
266         return configuration;
267     }
268
269     @Override
270     public void setConfiguration(Boolean configuration) {
271         this.configuration = configuration;
272     }
273
274     @Override
275     public ConstraintsBuilder getConstraints() {
276         return constraints;
277     }
278
279     @Override
280     public Set<UsesNodeBuilder> getUsesNodes() {
281         return addedUsesNodes;
282     }
283
284     @Override
285     public void addUsesNode(UsesNodeBuilder usesNodeBuilder) {
286         addedUsesNodes.add(usesNodeBuilder);
287     }
288
289     public void setUsesnodes(final Set<UsesNode> usesNodes) {
290         this.usesNodes = usesNodes;
291     }
292
293     public boolean isPresence() {
294         return presence;
295     }
296
297     public void setPresence(boolean presence) {
298         this.presence = presence;
299     }
300
301     @Override
302     public int hashCode() {
303         final int prime = 31;
304         int result = 1;
305         result = prime * result + ((schemaPath == null) ? 0 : schemaPath.hashCode());
306         return result;
307     }
308
309     @Override
310     public boolean equals(Object obj) {
311         if (this == obj) {
312             return true;
313         }
314         if (obj == null) {
315             return false;
316         }
317         if (getClass() != obj.getClass()) {
318             return false;
319         }
320         ContainerSchemaNodeBuilder other = (ContainerSchemaNodeBuilder) obj;
321         if (schemaPath == null) {
322             if (other.schemaPath != null) {
323                 return false;
324             }
325         } else if (!schemaPath.equals(other.schemaPath)) {
326             return false;
327         }
328         if (parent == null) {
329             if (other.parent != null) {
330                 return false;
331             }
332         } else if (!parent.equals(other.parent)) {
333             return false;
334         }
335         return true;
336     }
337
338     @Override
339     public String toString() {
340         return "container " + qname.getLocalName();
341     }
342
343     public final class ContainerSchemaNodeImpl implements ContainerSchemaNode {
344         private final QName qname;
345         private SchemaPath path;
346         private String description;
347         private String reference;
348         private Status status = Status.CURRENT;
349         private boolean augmenting;
350         private boolean addedByUses;
351         private boolean configuration;
352         private ConstraintDefinition constraints;
353         private Set<AugmentationSchema> augmentations = Collections.emptySet();
354         private Map<QName, DataSchemaNode> childNodes = Collections.emptyMap();
355         private Set<GroupingDefinition> groupings = Collections.emptySet();
356         private Set<TypeDefinition<?>> typeDefinitions = Collections.emptySet();
357         private Set<UsesNode> uses = Collections.emptySet();
358         private List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
359         private boolean presence;
360
361         private ContainerSchemaNodeImpl(QName qname) {
362             this.qname = qname;
363         }
364
365         @Override
366         public QName getQName() {
367             return qname;
368         }
369
370         @Override
371         public SchemaPath getPath() {
372             return path;
373         }
374
375         private void setPath(SchemaPath path) {
376             this.path = path;
377         }
378
379         @Override
380         public String getDescription() {
381             return description;
382         }
383
384         private void setDescription(String description) {
385             this.description = description;
386         }
387
388         @Override
389         public String getReference() {
390             return reference;
391         }
392
393         private void setReference(String reference) {
394             this.reference = reference;
395         }
396
397         @Override
398         public Status getStatus() {
399             return status;
400         }
401
402         private void setStatus(Status status) {
403             if (status != null) {
404                 this.status = status;
405             }
406         }
407
408         @Override
409         public boolean isAugmenting() {
410             return augmenting;
411         }
412
413         private void setAugmenting(boolean augmenting) {
414             this.augmenting = augmenting;
415         }
416
417         @Override
418         public boolean isAddedByUses() {
419             return addedByUses;
420         }
421
422         private void setAddedByUses(boolean addedByUses) {
423             this.addedByUses = addedByUses;
424         }
425
426         @Override
427         public boolean isConfiguration() {
428             return configuration;
429         }
430
431         private void setConfiguration(boolean configuration) {
432             this.configuration = configuration;
433         }
434
435         @Override
436         public ConstraintDefinition getConstraints() {
437             return constraints;
438         }
439
440         private void setConstraints(ConstraintDefinition constraints) {
441             this.constraints = constraints;
442         }
443
444         @Override
445         public Set<AugmentationSchema> getAvailableAugmentations() {
446             return augmentations;
447         }
448
449         private void setAvailableAugmentations(Set<AugmentationSchema> augmentations) {
450             if (augmentations != null) {
451                 this.augmentations = augmentations;
452             }
453         }
454
455         @Override
456         public Set<DataSchemaNode> getChildNodes() {
457             return new HashSet<DataSchemaNode>(childNodes.values());
458         }
459
460         private void setChildNodes(Map<QName, DataSchemaNode> childNodes) {
461             if (childNodes != null) {
462                 this.childNodes = childNodes;
463             }
464         }
465
466         @Override
467         public Set<GroupingDefinition> getGroupings() {
468             return groupings;
469         }
470
471         private void setGroupings(Set<GroupingDefinition> groupings) {
472             if (groupings != null) {
473                 this.groupings = groupings;
474             }
475         }
476
477         @Override
478         public DataSchemaNode getDataChildByName(QName name) {
479             return childNodes.get(name);
480         }
481
482         @Override
483         public DataSchemaNode getDataChildByName(String name) {
484             DataSchemaNode result = null;
485             for (Map.Entry<QName, DataSchemaNode> entry : childNodes.entrySet()) {
486                 if (entry.getKey().getLocalName().equals(name)) {
487                     result = entry.getValue();
488                     break;
489                 }
490             }
491             return result;
492         }
493
494         @Override
495         public Set<UsesNode> getUses() {
496             return uses;
497         }
498
499         private void setUses(Set<UsesNode> uses) {
500             if (uses != null) {
501                 this.uses = uses;
502             }
503         }
504
505         @Override
506         public boolean isPresenceContainer() {
507             return presence;
508         }
509
510         private void setPresenceContainer(boolean presence) {
511             this.presence = presence;
512         }
513
514         @Override
515         public Set<TypeDefinition<?>> getTypeDefinitions() {
516             return typeDefinitions;
517         }
518
519         private void setTypeDefinitions(Set<TypeDefinition<?>> typeDefinitions) {
520             if (typeDefinitions != null) {
521                 this.typeDefinitions = typeDefinitions;
522             }
523         }
524
525         @Override
526         public List<UnknownSchemaNode> getUnknownSchemaNodes() {
527             return unknownNodes;
528         }
529
530         private void setUnknownSchemaNodes(List<UnknownSchemaNode> unknownSchemaNodes) {
531             if (unknownSchemaNodes != null) {
532                 this.unknownNodes = unknownSchemaNodes;
533             }
534         }
535
536         public ContainerSchemaNodeBuilder toBuilder() {
537             return ContainerSchemaNodeBuilder.this;
538         }
539
540         @Override
541         public int hashCode() {
542             final int prime = 31;
543             int result = 1;
544             result = prime * result + ((qname == null) ? 0 : qname.hashCode());
545             result = prime * result + ((path == null) ? 0 : path.hashCode());
546             return result;
547         }
548
549         @Override
550         public boolean equals(Object obj) {
551             if (this == obj) {
552                 return true;
553             }
554             if (obj == null) {
555                 return false;
556             }
557             if (getClass() != obj.getClass()) {
558                 return false;
559             }
560             ContainerSchemaNodeImpl other = (ContainerSchemaNodeImpl) obj;
561             if (qname == null) {
562                 if (other.qname != null) {
563                     return false;
564                 }
565             } else if (!qname.equals(other.qname)) {
566                 return false;
567             }
568             if (path == null) {
569                 if (other.path != null) {
570                     return false;
571                 }
572             } else if (!path.equals(other.path)) {
573                 return false;
574             }
575             return true;
576         }
577
578         @Override
579         public String toString() {
580             StringBuilder sb = new StringBuilder(ContainerSchemaNodeImpl.class.getSimpleName());
581             sb.append("[");
582             sb.append("qname=" + qname);
583             sb.append("]");
584             return sb.toString();
585         }
586     }
587
588 }