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