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