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