BUG-868: do not use ParserUtils.createSchemaPath()
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / builder / impl / ChoiceBuilder.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.Date;
13 import java.util.HashSet;
14 import java.util.List;
15 import java.util.Set;
16 import java.util.TreeSet;
17
18 import org.opendaylight.yangtools.yang.common.QName;
19 import org.opendaylight.yangtools.yang.model.api.AugmentationSchema;
20 import org.opendaylight.yangtools.yang.model.api.ChoiceCaseNode;
21 import org.opendaylight.yangtools.yang.model.api.ChoiceNode;
22 import org.opendaylight.yangtools.yang.model.api.ConstraintDefinition;
23 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
24 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
25 import org.opendaylight.yangtools.yang.model.api.Status;
26 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
27 import org.opendaylight.yangtools.yang.parser.builder.api.AbstractSchemaNodeBuilder;
28 import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationSchemaBuilder;
29 import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationTargetBuilder;
30 import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
31 import org.opendaylight.yangtools.yang.parser.util.Comparators;
32 import org.opendaylight.yangtools.yang.parser.util.ParserUtils;
33 import org.opendaylight.yangtools.yang.parser.util.YangParseException;
34
35 import com.google.common.collect.ImmutableList;
36 import com.google.common.collect.ImmutableSet;
37
38 public final class ChoiceBuilder extends AbstractSchemaNodeBuilder implements DataSchemaNodeBuilder,
39         AugmentationTargetBuilder {
40     private ChoiceNodeImpl instance;
41
42     // DataSchemaNode args
43     private boolean augmenting;
44     private boolean addedByUses;
45     private boolean configuration;
46     private final ConstraintsBuilder constraints;
47     // AugmentationTarget args
48     private final Set<AugmentationSchema> augmentations = new HashSet<>();
49     private final List<AugmentationSchemaBuilder> augmentationBuilders = new ArrayList<>();
50     // ChoiceNode args
51     private final Set<ChoiceCaseBuilder> caseBuilders = new HashSet<>();
52     private String defaultCase;
53
54     public ChoiceBuilder(final String moduleName, final int line, final QName qname, final SchemaPath path) {
55         super(moduleName, line, qname);
56         this.schemaPath = path;
57         constraints = new ConstraintsBuilder(moduleName, line);
58     }
59
60     public ChoiceBuilder(final String moduleName, final int line, final QName qname, final SchemaPath path,
61             final ChoiceNode base) {
62         super(moduleName, line, qname);
63         this.schemaPath = path;
64         constraints = new ConstraintsBuilder(moduleName, line, base.getConstraints());
65
66         description = base.getDescription();
67         reference = base.getReference();
68         status = base.getStatus();
69         augmenting = base.isAugmenting();
70         addedByUses = base.isAddedByUses();
71         configuration = base.isConfiguration();
72         augmentations.addAll(base.getAvailableAugmentations());
73
74         URI ns = qname.getNamespace();
75         Date rev = qname.getRevision();
76         String pref = qname.getPrefix();
77         Set<DataSchemaNodeBuilder> wrapped = ParserUtils.wrapChildNodes(moduleName, line, new HashSet<DataSchemaNode>(
78                 base.getCases()), path, ns, rev, pref);
79         for (DataSchemaNodeBuilder wrap : wrapped) {
80             if (wrap instanceof ChoiceCaseBuilder) {
81                 caseBuilders.add((ChoiceCaseBuilder) wrap);
82             }
83         }
84
85         addedUnknownNodes.addAll(ParserUtils.wrapUnknownNodes(moduleName, line, base.getUnknownSchemaNodes(), path, ns,
86                 rev, pref));
87     }
88
89     @Override
90     public ChoiceNode build() {
91         if (instance != null) {
92             return instance;
93         }
94
95         instance = new ChoiceNodeImpl(qname, schemaPath);
96
97         instance.description = description;
98         instance.reference = reference;
99         instance.status = status;
100         instance.augmenting = augmenting;
101         instance.addedByUses = addedByUses;
102         instance.configuration = configuration;
103
104         instance.constraints = constraints.build();
105         instance.defaultCase = defaultCase;
106
107         // CASES
108         final Set<ChoiceCaseNode> cases = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
109         for (ChoiceCaseBuilder caseBuilder : caseBuilders) {
110             cases.add(caseBuilder.build());
111         }
112         instance.cases = ImmutableSet.copyOf(cases);
113
114         // AUGMENTATIONS
115         for (AugmentationSchemaBuilder builder : augmentationBuilders) {
116             augmentations.add(builder.build());
117         }
118         instance.augmentations = ImmutableSet.copyOf(augmentations);
119
120         // UNKNOWN NODES
121         for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
122             unknownNodes.add(b.build());
123         }
124         instance.unknownNodes = ImmutableList.copyOf(unknownNodes);
125
126         return instance;
127     }
128
129     public Set<ChoiceCaseBuilder> getCases() {
130         return caseBuilders;
131     }
132
133     /**
134      * Get case by name.
135      *
136      * @param caseName
137      *            name of case to search
138      * @return case with given name if present, null otherwise
139      */
140     public ChoiceCaseBuilder getCaseNodeByName(final String caseName) {
141         for (ChoiceCaseBuilder addedCase : caseBuilders) {
142             if (addedCase.getQName().getLocalName().equals(caseName)) {
143                 return addedCase;
144             }
145         }
146         return null;
147     }
148
149     /**
150      * Add case node to this choice.
151      *
152      * If node is not declared with 'case' keyword, create new case builder and
153      * make this node child of newly created case.
154      *
155      * @param caseNode
156      *            case node
157      */
158     public void addCase(final DataSchemaNodeBuilder caseNode) {
159         QName caseQName = caseNode.getQName();
160         String caseName = caseQName.getLocalName();
161
162         for (ChoiceCaseBuilder addedCase : caseBuilders) {
163             if (addedCase.getQName().getLocalName().equals(caseName)) {
164                 throw new YangParseException(caseNode.getModuleName(), caseNode.getLine(), "Can not add '" + caseNode
165                         + "' to node '" + qname.getLocalName() + "' in module '" + moduleName
166                         + "': case with same name already declared at line " + addedCase.getLine());
167             }
168         }
169
170         if (caseNode instanceof ChoiceCaseBuilder) {
171             caseBuilders.add((ChoiceCaseBuilder) caseNode);
172         } else {
173             ChoiceCaseBuilder caseBuilder = new ChoiceCaseBuilder(caseNode.getModuleName(), caseNode.getLine(),
174                     caseQName, caseNode.getPath());
175             if (caseNode.isAugmenting()) {
176                 // if node is added by augmentation, set case builder augmenting
177                 // as true and node augmenting as false
178                 caseBuilder.setAugmenting(true);
179                 caseNode.setAugmenting(false);
180             }
181             SchemaPath newPath = caseNode.getPath().createChild(caseQName);
182             caseNode.setPath(newPath);
183             caseBuilder.addChildNode(caseNode);
184             caseBuilders.add(caseBuilder);
185         }
186     }
187
188     @Override
189     public boolean isAugmenting() {
190         return augmenting;
191     }
192
193     @Override
194     public void setAugmenting(final boolean augmenting) {
195         this.augmenting = augmenting;
196     }
197
198     @Override
199     public boolean isAddedByUses() {
200         return addedByUses;
201     }
202
203     @Override
204     public void setAddedByUses(final boolean addedByUses) {
205         this.addedByUses = addedByUses;
206     }
207
208     @Override
209     public boolean isConfiguration() {
210         return configuration;
211     }
212
213     @Override
214     public void setConfiguration(final boolean configuration) {
215         this.configuration = configuration;
216     }
217
218     @Override
219     public ConstraintsBuilder getConstraints() {
220         return constraints;
221     }
222
223     @Override
224     public void addAugmentation(final AugmentationSchemaBuilder augment) {
225         augmentationBuilders.add(augment);
226     }
227
228     public List<AugmentationSchemaBuilder> getAugmentationBuilders() {
229         return augmentationBuilders;
230     }
231
232     public String getDefaultCase() {
233         return defaultCase;
234     }
235
236     public void setDefaultCase(final String defaultCase) {
237         this.defaultCase = defaultCase;
238     }
239
240     @Override
241     public int hashCode() {
242         final int prime = 31;
243         int result = 1;
244         result = prime * result + ((schemaPath == null) ? 0 : schemaPath.hashCode());
245         return result;
246     }
247
248     @Override
249     public boolean equals(final Object obj) {
250         if (this == obj) {
251             return true;
252         }
253         if (obj == null) {
254             return false;
255         }
256         if (getClass() != obj.getClass()) {
257             return false;
258         }
259         ChoiceBuilder other = (ChoiceBuilder) obj;
260         if (schemaPath == null) {
261             if (other.schemaPath != null) {
262                 return false;
263             }
264         } else if (!schemaPath.equals(other.schemaPath)) {
265             return false;
266         }
267         if (parentBuilder == null) {
268             if (other.parentBuilder != null) {
269                 return false;
270             }
271         } else if (!parentBuilder.equals(other.parentBuilder)) {
272             return false;
273         }
274         return true;
275     }
276
277     @Override
278     public String toString() {
279         return "choice " + qname.getLocalName();
280     }
281
282     private static final class ChoiceNodeImpl implements ChoiceNode {
283         private final QName qname;
284         private final SchemaPath path;
285         private String description;
286         private String reference;
287         private Status status;
288         private boolean augmenting;
289         private boolean addedByUses;
290         private boolean configuration;
291         private ConstraintDefinition constraints;
292         private ImmutableSet<ChoiceCaseNode> cases;
293         private ImmutableSet<AugmentationSchema> augmentations;
294         private ImmutableList<UnknownSchemaNode> unknownNodes;
295         private String defaultCase;
296
297         private ChoiceNodeImpl(final QName qname, final SchemaPath path) {
298             this.qname = qname;
299             this.path = path;
300         }
301
302         @Override
303         public QName getQName() {
304             return qname;
305         }
306
307         @Override
308         public SchemaPath getPath() {
309             return path;
310         }
311
312         @Override
313         public String getDescription() {
314             return description;
315         }
316
317         @Override
318         public String getReference() {
319             return reference;
320         }
321
322         @Override
323         public Status getStatus() {
324             return status;
325         }
326
327         @Override
328         public boolean isAugmenting() {
329             return augmenting;
330         }
331
332         @Override
333         public boolean isAddedByUses() {
334             return addedByUses;
335         }
336
337         @Override
338         public boolean isConfiguration() {
339             return configuration;
340         }
341
342         @Override
343         public ConstraintDefinition getConstraints() {
344             return constraints;
345         }
346
347         @Override
348         public Set<AugmentationSchema> getAvailableAugmentations() {
349             return augmentations;
350         }
351
352         @Override
353         public List<UnknownSchemaNode> getUnknownSchemaNodes() {
354             return unknownNodes;
355         }
356
357         @Override
358         public Set<ChoiceCaseNode> getCases() {
359             return cases;
360         }
361
362         @Override
363         public ChoiceCaseNode getCaseNodeByName(final QName name) {
364             if (name == null) {
365                 throw new IllegalArgumentException("Choice Case QName cannot be NULL!");
366             }
367             for (final ChoiceCaseNode caseNode : cases) {
368                 if (caseNode != null && name.equals(caseNode.getQName())) {
369                     return caseNode;
370                 }
371             }
372             return null;
373         }
374
375         @Override
376         public ChoiceCaseNode getCaseNodeByName(final String name) {
377             if (name == null) {
378                 throw new IllegalArgumentException("Choice Case string Name cannot be NULL!");
379             }
380             for (final ChoiceCaseNode caseNode : cases) {
381                 if (caseNode != null && (caseNode.getQName() != null)
382                         && name.equals(caseNode.getQName().getLocalName())) {
383                     return caseNode;
384                 }
385             }
386             return null;
387         }
388
389         @Override
390         public String getDefaultCase() {
391             return defaultCase;
392         }
393
394         @Override
395         public int hashCode() {
396             final int prime = 31;
397             int result = 1;
398             result = prime * result + ((qname == null) ? 0 : qname.hashCode());
399             result = prime * result + ((path == null) ? 0 : path.hashCode());
400             return result;
401         }
402
403         @Override
404         public boolean equals(final Object obj) {
405             if (this == obj) {
406                 return true;
407             }
408             if (obj == null) {
409                 return false;
410             }
411             if (getClass() != obj.getClass()) {
412                 return false;
413             }
414             ChoiceNodeImpl other = (ChoiceNodeImpl) obj;
415             if (qname == null) {
416                 if (other.qname != null) {
417                     return false;
418                 }
419             } else if (!qname.equals(other.qname)) {
420                 return false;
421             }
422             if (path == null) {
423                 if (other.path != null) {
424                     return false;
425                 }
426             } else if (!path.equals(other.path)) {
427                 return false;
428             }
429             return true;
430         }
431
432         @Override
433         public String toString() {
434             StringBuilder sb = new StringBuilder(ChoiceNodeImpl.class.getSimpleName());
435             sb.append("[");
436             sb.append("qname=" + qname);
437             sb.append("]");
438             return sb.toString();
439         }
440     }
441
442 }