Fix for Bug 364.
[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.net.URI;
11 import java.util.ArrayList;
12 import java.util.Collections;
13 import java.util.Date;
14 import java.util.HashSet;
15 import java.util.List;
16 import java.util.Set;
17 import java.util.TreeSet;
18
19 import org.opendaylight.yangtools.yang.common.QName;
20 import org.opendaylight.yangtools.yang.model.api.*;
21 import org.opendaylight.yangtools.yang.parser.builder.api.AbstractDataNodeContainerBuilder;
22 import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationSchemaBuilder;
23 import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationTargetBuilder;
24 import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
25 import org.opendaylight.yangtools.yang.parser.builder.api.GroupingBuilder;
26 import org.opendaylight.yangtools.yang.parser.builder.api.TypeDefinitionBuilder;
27 import org.opendaylight.yangtools.yang.parser.builder.api.UsesNodeBuilder;
28 import org.opendaylight.yangtools.yang.parser.util.Comparators;
29 import org.opendaylight.yangtools.yang.parser.util.ParserUtils;
30 import org.opendaylight.yangtools.yang.parser.util.YangParseException;
31
32 public final class ContainerSchemaNodeBuilder extends AbstractDataNodeContainerBuilder implements
33         AugmentationTargetBuilder, DataSchemaNodeBuilder {
34     private boolean isBuilt;
35     private final ContainerSchemaNodeImpl instance;
36
37     private final SchemaPath path;
38     // DataSchemaNode args
39     private final ConstraintsBuilder constraints;
40     // AugmentationTarget args
41     private final List<AugmentationSchemaBuilder> augmentationBuilders = new ArrayList<>();
42
43     public ContainerSchemaNodeBuilder(final String moduleName, final int line, final QName qname, final SchemaPath path) {
44         super(moduleName, line, qname);
45         this.path = path;
46         this.instance = new ContainerSchemaNodeImpl(qname, path);
47         this.constraints = new ConstraintsBuilder(moduleName, line);
48     }
49
50     // constructor for uses
51     public ContainerSchemaNodeBuilder(final String moduleName, final int line, final QName qname,
52             final SchemaPath path, final ContainerSchemaNode base) {
53         super(moduleName, line, qname);
54         this.path = path;
55         instance = new ContainerSchemaNodeImpl(qname, path);
56         constraints = new ConstraintsBuilder(moduleName, line, base.getConstraints());
57
58         instance.description = base.getDescription();
59         instance.reference = base.getReference();
60         instance.status = base.getStatus();
61         instance.augmenting = base.isAugmenting();
62         instance.addedByUses = base.isAddedByUses();
63         instance.configuration = base.isConfiguration();
64         instance.constraints = base.getConstraints();
65         instance.augmentations.addAll(base.getAvailableAugmentations());
66
67         URI ns = qname.getNamespace();
68         Date rev = qname.getRevision();
69         String pref = qname.getPrefix();
70         addedChildNodes.addAll(ParserUtils.wrapChildNodes(moduleName, line, base.getChildNodes(), path, ns, rev, pref));
71         addedGroupings.addAll(ParserUtils.wrapGroupings(moduleName, line, base.getGroupings(), path, ns, rev, pref));
72         addedTypedefs.addAll(ParserUtils.wrapTypedefs(moduleName, line, base, path, ns, rev, pref));
73         addedUnknownNodes.addAll(ParserUtils.wrapUnknownNodes(moduleName, line, base.getUnknownSchemaNodes(), path, ns,
74                 rev, pref));
75
76         instance.uses.addAll(base.getUses());
77         instance.presence = base.isPresenceContainer();
78         instance.configuration = base.isConfiguration();
79         instance.configuration = base.isConfiguration();
80     }
81
82     @Override
83     public ContainerSchemaNode build() {
84         if (!isBuilt) {
85             // USES
86             for (UsesNodeBuilder builder : addedUsesNodes) {
87                 usesNodes.add(builder.build());
88             }
89             instance.addUses(usesNodes);
90
91             // CHILD NODES
92             for (DataSchemaNodeBuilder node : addedChildNodes) {
93                 childNodes.add(node.build());
94             }
95             instance.addChildNodes(childNodes);
96
97             // GROUPINGS
98             for (GroupingBuilder builder : addedGroupings) {
99                 groupings.add(builder.build());
100             }
101             instance.addGroupings(groupings);
102
103             // TYPEDEFS
104             for (TypeDefinitionBuilder entry : addedTypedefs) {
105                 typedefs.add(entry.build());
106             }
107             instance.addTypeDefinitions(typedefs);
108
109             // AUGMENTATIONS
110             final List<AugmentationSchema> augmentations = new ArrayList<>();
111             for (AugmentationSchemaBuilder builder : augmentationBuilders) {
112                 augmentations.add(builder.build());
113             }
114             instance.addAvailableAugmentations(new HashSet<>(augmentations));
115
116             // UNKNOWN NODES
117             for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
118                 unknownNodes.add(b.build());
119             }
120             Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
121             instance.addUnknownSchemaNodes(unknownNodes);
122
123             if (constraints != null) {
124                 instance.setConstraints(constraints.build());
125             }
126
127             isBuilt = true;
128         }
129         return instance;
130     }
131
132     @Override
133     public Set<TypeDefinitionBuilder> getTypeDefinitionBuilders() {
134         return addedTypedefs;
135     }
136
137     @Override
138     public void addTypedef(final TypeDefinitionBuilder type) {
139         String typeName = type.getQName().getLocalName();
140         for (TypeDefinitionBuilder addedTypedef : addedTypedefs) {
141             if (addedTypedef.getQName().getLocalName().equals(typeName)) {
142                 throw new YangParseException(moduleName, type.getLine(), "Can not add typedef '" + typeName
143                         + "': typedef with same name already declared at line " + addedTypedef.getLine());
144             }
145         }
146         addedTypedefs.add(type);
147     }
148
149     public List<AugmentationSchemaBuilder> getAugmentationBuilders() {
150         return augmentationBuilders;
151     }
152
153     @Override
154     public void addAugmentation(AugmentationSchemaBuilder augment) {
155         augmentationBuilders.add(augment);
156     }
157
158     @Override
159     public SchemaPath getPath() {
160         return instance.path;
161     }
162
163     @Override
164     public void setPath(SchemaPath path) {
165         instance.path = path;
166     }
167
168     @Override
169     public String getDescription() {
170         return instance.description;
171     }
172
173     @Override
174     public void setDescription(final String description) {
175         instance.description = description;
176     }
177
178     @Override
179     public String getReference() {
180         return instance.reference;
181     }
182
183     @Override
184     public void setReference(final String reference) {
185         instance.reference = reference;
186     }
187
188     @Override
189     public Status getStatus() {
190         return instance.status;
191     }
192
193     @Override
194     public void setStatus(Status status) {
195         if (status != null) {
196             instance.status = status;
197         }
198     }
199
200     @Override
201     public boolean isAugmenting() {
202         return instance.augmenting;
203     }
204
205     @Override
206     public void setAugmenting(boolean augmenting) {
207         instance.augmenting = augmenting;
208     }
209
210     @Override
211     public boolean isAddedByUses() {
212         return instance.addedByUses;
213     }
214
215     @Override
216     public void setAddedByUses(final boolean addedByUses) {
217         instance.addedByUses = addedByUses;
218     }
219
220     @Override
221     public boolean isConfiguration() {
222         return instance.configuration;
223     }
224
225     @Override
226     public void setConfiguration(boolean configuration) {
227         instance.configuration = configuration;
228     }
229
230     @Override
231     public ConstraintsBuilder getConstraints() {
232         return constraints;
233     }
234
235     public boolean isPresence() {
236         return instance.presence;
237     }
238
239     public void setPresence(boolean presence) {
240         instance.presence = presence;
241     }
242
243     @Override
244     public int hashCode() {
245         final int prime = 31;
246         int result = 1;
247         result = prime * result + ((path == null) ? 0 : path.hashCode());
248         return result;
249     }
250
251     @Override
252     public boolean equals(Object obj) {
253         if (this == obj) {
254             return true;
255         }
256         if (obj == null) {
257             return false;
258         }
259         if (getClass() != obj.getClass()) {
260             return false;
261         }
262         ContainerSchemaNodeBuilder other = (ContainerSchemaNodeBuilder) obj;
263         if (path == null) {
264             if (other.path != null) {
265                 return false;
266             }
267         } else if (!path.equals(other.path)) {
268             return false;
269         }
270         if (parentBuilder == null) {
271             if (other.parentBuilder != null) {
272                 return false;
273             }
274         } else if (!parentBuilder.equals(other.parentBuilder)) {
275             return false;
276         }
277         return true;
278     }
279
280     @Override
281     public String toString() {
282         return "container " + qname.getLocalName();
283     }
284
285     private static final class ContainerSchemaNodeImpl implements ContainerSchemaNode {
286         private final QName qname;
287         private SchemaPath path;
288         private String description;
289         private String reference;
290         private Status status = Status.CURRENT;
291         private boolean augmenting;
292         private boolean addedByUses;
293         private boolean configuration;
294         private ConstraintDefinition constraints;
295         private final Set<AugmentationSchema> augmentations = new HashSet<>();
296         private final Set<DataSchemaNode> childNodes = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
297         private final Set<GroupingDefinition> groupings = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
298         private final Set<TypeDefinition<?>> typeDefinitions = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
299         private final Set<UsesNode> uses = new HashSet<>();
300         private final List<UnknownSchemaNode> unknownNodes = new ArrayList<>();
301         private boolean presence;
302
303         private ContainerSchemaNodeImpl(QName qname, SchemaPath path) {
304             this.qname = qname;
305             this.path = path;
306         }
307
308         @Override
309         public QName getQName() {
310             return qname;
311         }
312
313         @Override
314         public SchemaPath getPath() {
315             return path;
316         }
317
318         @Override
319         public String getDescription() {
320             return description;
321         }
322
323         @Override
324         public String getReference() {
325             return reference;
326         }
327
328         @Override
329         public Status getStatus() {
330             return status;
331         }
332
333         @Override
334         public boolean isAugmenting() {
335             return augmenting;
336         }
337
338         @Override
339         public boolean isAddedByUses() {
340             return addedByUses;
341         }
342
343         @Override
344         public boolean isConfiguration() {
345             return configuration;
346         }
347
348         @Override
349         public ConstraintDefinition getConstraints() {
350             return constraints;
351         }
352
353         private void setConstraints(ConstraintDefinition constraints) {
354             this.constraints = constraints;
355         }
356
357         @Override
358         public Set<AugmentationSchema> getAvailableAugmentations() {
359             return Collections.unmodifiableSet(augmentations);
360         }
361
362         private void addAvailableAugmentations(Set<AugmentationSchema> augmentations) {
363             if (augmentations != null) {
364                 this.augmentations.addAll(augmentations);
365             }
366         }
367
368         @Override
369         public Set<DataSchemaNode> getChildNodes() {
370             return Collections.unmodifiableSet(childNodes);
371         }
372
373         private void addChildNodes(Set<DataSchemaNode> childNodes) {
374             if (childNodes != null) {
375                 this.childNodes.addAll(childNodes);
376             }
377         }
378
379         @Override
380         public Set<GroupingDefinition> getGroupings() {
381             return Collections.unmodifiableSet(groupings);
382         }
383
384         private void addGroupings(Set<GroupingDefinition> groupings) {
385             if (groupings != null) {
386                 this.groupings.addAll(groupings);
387             }
388         }
389
390         @Override
391         public DataSchemaNode getDataChildByName(QName name) {
392             return getChildNode(childNodes, name);
393         }
394
395         @Override
396         public DataSchemaNode getDataChildByName(String name) {
397             return getChildNode(childNodes, name);
398         }
399
400         @Override
401         public Set<UsesNode> getUses() {
402             return Collections.unmodifiableSet(uses);
403         }
404
405         private void addUses(Set<UsesNode> uses) {
406             if (uses != null) {
407                 this.uses.addAll(uses);
408             }
409         }
410
411         @Override
412         public boolean isPresenceContainer() {
413             return presence;
414         }
415
416         @Override
417         public Set<TypeDefinition<?>> getTypeDefinitions() {
418             return Collections.unmodifiableSet(typeDefinitions);
419         }
420
421         private void addTypeDefinitions(Set<TypeDefinition<?>> typeDefinitions) {
422             if (typeDefinitions != null) {
423                 this.typeDefinitions.addAll(typeDefinitions);
424             }
425         }
426
427         @Override
428         public List<UnknownSchemaNode> getUnknownSchemaNodes() {
429             return Collections.unmodifiableList(unknownNodes);
430         }
431
432         private void addUnknownSchemaNodes(List<UnknownSchemaNode> unknownSchemaNodes) {
433             if (unknownSchemaNodes != null) {
434                 this.unknownNodes.addAll(unknownSchemaNodes);
435             }
436         }
437
438         @Override
439         public int hashCode() {
440             final int prime = 31;
441             int result = 1;
442             result = prime * result + ((qname == null) ? 0 : qname.hashCode());
443             result = prime * result + ((path == null) ? 0 : path.hashCode());
444             return result;
445         }
446
447         @Override
448         public boolean equals(Object obj) {
449             if (this == obj) {
450                 return true;
451             }
452             if (obj == null) {
453                 return false;
454             }
455             if (getClass() != obj.getClass()) {
456                 return false;
457             }
458             ContainerSchemaNodeImpl other = (ContainerSchemaNodeImpl) obj;
459             if (qname == null) {
460                 if (other.qname != null) {
461                     return false;
462                 }
463             } else if (!qname.equals(other.qname)) {
464                 return false;
465             }
466             if (path == null) {
467                 if (other.path != null) {
468                     return false;
469                 }
470             } else if (!path.equals(other.path)) {
471                 return false;
472             }
473             return true;
474         }
475
476         @Override
477         public String toString() {
478             return "container " + qname.getLocalName();
479         }
480     }
481
482 }