Fixed resolving of schema path and qname for nodes added by augmentation.
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / builder / impl / AugmentationSchemaBuilderImpl.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.util.ArrayList;
11 import java.util.Collections;
12 import java.util.HashSet;
13 import java.util.List;
14 import java.util.Map;
15 import java.util.Set;
16 import java.util.TreeMap;
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.DataSchemaNode;
22 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
23 import org.opendaylight.yangtools.yang.model.api.RevisionAwareXPath;
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.TypeDefinition;
27 import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode;
28 import org.opendaylight.yangtools.yang.model.api.UsesNode;
29 import org.opendaylight.yangtools.yang.model.util.RevisionAwareXPathImpl;
30 import org.opendaylight.yangtools.yang.parser.builder.api.AbstractDataNodeContainerBuilder;
31 import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationSchemaBuilder;
32 import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
33 import org.opendaylight.yangtools.yang.parser.builder.api.GroupingBuilder;
34 import org.opendaylight.yangtools.yang.parser.builder.api.TypeDefinitionBuilder;
35 import org.opendaylight.yangtools.yang.parser.builder.api.UsesNodeBuilder;
36 import org.opendaylight.yangtools.yang.parser.util.Comparators;
37 import org.opendaylight.yangtools.yang.parser.util.ParserUtils;
38 import org.opendaylight.yangtools.yang.parser.util.YangParseException;
39
40 public final class AugmentationSchemaBuilderImpl extends AbstractDataNodeContainerBuilder implements
41         AugmentationSchemaBuilder {
42     private boolean built;
43     private final AugmentationSchemaImpl instance;
44
45     private String whenCondition;
46     private String description;
47     private String reference;
48     private Status status = Status.CURRENT;
49
50     private final String augmentTargetStr;
51     private SchemaPath dirtyAugmentTarget;
52     private SchemaPath finalAugmentTarget;
53
54     private final Set<UsesNodeBuilder> usesNodes = new HashSet<UsesNodeBuilder>();
55     private boolean resolved;
56
57     public AugmentationSchemaBuilderImpl(final String moduleName, final int line, final String augmentTargetStr) {
58         super(moduleName, line, null);
59         this.augmentTargetStr = augmentTargetStr;
60         final SchemaPath targetPath = ParserUtils.parseXPathString(augmentTargetStr);
61         dirtyAugmentTarget = targetPath;
62         instance = new AugmentationSchemaImpl(targetPath);
63     }
64
65     @Override
66     public Set<GroupingDefinition> getGroupings() {
67         return Collections.emptySet();
68     }
69
70     @Override
71     public Set<GroupingBuilder> getGroupingBuilders() {
72         return Collections.emptySet();
73     }
74
75     @Override
76     public void addGrouping(GroupingBuilder grouping) {
77         throw new YangParseException(moduleName, line, "augment can not contains grouping statement");
78     }
79
80     @Override
81     public Set<UsesNodeBuilder> getUsesNodes() {
82         return usesNodes;
83     }
84
85     @Override
86     public void addUsesNode(UsesNodeBuilder usesBuilder) {
87         usesNodes.add(usesBuilder);
88     }
89
90     @Override
91     public SchemaPath getPath() {
92         return finalAugmentTarget;
93     }
94
95     @Override
96     public AugmentationSchema build() {
97         if (!built) {
98             instance.setDescription(description);
99             instance.setReference(reference);
100             instance.setStatus(status);
101             instance.setTargetPath(finalAugmentTarget);
102
103             RevisionAwareXPath whenStmt;
104             if (whenCondition == null) {
105                 whenStmt = null;
106             } else {
107                 whenStmt = new RevisionAwareXPathImpl(whenCondition, false);
108             }
109             instance.setWhenCondition(whenStmt);
110
111             // CHILD NODES
112             final Map<QName, DataSchemaNode> childs = new TreeMap<QName, DataSchemaNode>(Comparators.QNAME_COMP);
113             for (DataSchemaNodeBuilder node : addedChildNodes) {
114                 childs.put(node.getQName(), node.build());
115             }
116             instance.setChildNodes(childs);
117
118             // USES
119             final Set<UsesNode> usesNodeDefinitions = new HashSet<UsesNode>();
120             for (UsesNodeBuilder builder : usesNodes) {
121                 usesNodeDefinitions.add(builder.build());
122             }
123             instance.setUses(usesNodeDefinitions);
124
125             // UNKNOWN NODES
126             List<UnknownSchemaNode> unknownNodes = new ArrayList<UnknownSchemaNode>();
127             for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
128                 unknownNodes.add(b.build());
129             }
130             Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
131             instance.setUnknownSchemaNodes(unknownNodes);
132
133             built = true;
134         }
135         return instance;
136     }
137
138     @Override
139     public boolean isResolved() {
140         return resolved;
141     }
142
143     @Override
144     public void setResolved(boolean resolved) {
145         this.resolved = resolved;
146     }
147
148     public String getWhenCondition() {
149         return whenCondition;
150     }
151
152     public void addWhenCondition(String whenCondition) {
153         this.whenCondition = whenCondition;
154     }
155
156     @Override
157     public Set<TypeDefinitionBuilder> getTypeDefinitionBuilders() {
158         return Collections.emptySet();
159     }
160
161     @Override
162     public void addTypedef(TypeDefinitionBuilder type) {
163         throw new YangParseException(moduleName, line, "Augmentation can not contains typedef statement.");
164     }
165
166     @Override
167     public String getDescription() {
168         return description;
169     }
170
171     @Override
172     public void setDescription(String description) {
173         this.description = description;
174     }
175
176     @Override
177     public String getReference() {
178         return reference;
179     }
180
181     @Override
182     public void setReference(String reference) {
183         this.reference = reference;
184     }
185
186     @Override
187     public Status getStatus() {
188         return status;
189     }
190
191     @Override
192     public void setStatus(Status status) {
193         if (status != null) {
194             this.status = status;
195         }
196     }
197
198     @Override
199     public SchemaPath getTargetPath() {
200         if(finalAugmentTarget == null) {
201             return dirtyAugmentTarget;
202         } else {
203             return finalAugmentTarget;
204         }
205     }
206
207     @Override
208     public void setTargetPath(SchemaPath path) {
209         this.finalAugmentTarget = path;
210     }
211
212     @Override
213     public String getTargetPathAsString() {
214         return augmentTargetStr;
215     }
216
217     @Override
218     public int hashCode() {
219         final int prime = 17;
220         int result = 1;
221         result = prime * result + ((augmentTargetStr == null) ? 0 : augmentTargetStr.hashCode());
222         result = prime * result + ((whenCondition == null) ? 0 : whenCondition.hashCode());
223         result = prime * result + ((childNodes == null) ? 0 : childNodes.hashCode());
224         return result;
225     }
226
227     @Override
228     public boolean equals(Object obj) {
229         if (this == obj) {
230             return true;
231         }
232         if (obj == null) {
233             return false;
234         }
235         if (getClass() != obj.getClass()) {
236             return false;
237         }
238         AugmentationSchemaBuilderImpl other = (AugmentationSchemaBuilderImpl) obj;
239         if (augmentTargetStr == null) {
240             if (other.augmentTargetStr != null) {
241                 return false;
242             }
243         } else if (!augmentTargetStr.equals(other.augmentTargetStr)) {
244             return false;
245         }
246         if (whenCondition == null) {
247             if (other.whenCondition != null) {
248                 return false;
249             }
250         } else if (!whenCondition.equals(other.whenCondition)) {
251             return false;
252         }
253         if (childNodes == null) {
254             if (other.childNodes != null) {
255                 return false;
256             }
257         } else if (!childNodes.equals(other.childNodes)) {
258             return false;
259         }
260         return true;
261     }
262
263     public String toString() {
264         return "augment " + augmentTargetStr;
265     }
266
267     private final class AugmentationSchemaImpl implements AugmentationSchema {
268         private SchemaPath targetPath;
269         private RevisionAwareXPath whenCondition;
270         private Map<QName, DataSchemaNode> childNodes = Collections.emptyMap();
271         private Set<UsesNode> uses = Collections.emptySet();
272         private String description;
273         private String reference;
274         private Status status;
275         private List<UnknownSchemaNode> unknownNodes = Collections.emptyList();
276
277         private AugmentationSchemaImpl(SchemaPath targetPath) {
278             this.targetPath = targetPath;
279         }
280
281         @Override
282         public SchemaPath getTargetPath() {
283             return targetPath;
284         }
285
286         private void setTargetPath(SchemaPath path) {
287             this.targetPath = path;
288         }
289
290         @Override
291         public RevisionAwareXPath getWhenCondition() {
292             return whenCondition;
293         }
294
295         private void setWhenCondition(RevisionAwareXPath whenCondition) {
296             this.whenCondition = whenCondition;
297         }
298
299         @Override
300         public Set<DataSchemaNode> getChildNodes() {
301             final Set<DataSchemaNode> result = new TreeSet<DataSchemaNode>(Comparators.SCHEMA_NODE_COMP);
302             result.addAll(childNodes.values());
303             return result;
304         }
305
306         private void setChildNodes(Map<QName, DataSchemaNode> childNodes) {
307             if (childNodes != null) {
308                 this.childNodes = childNodes;
309             }
310         }
311
312         /**
313          * Always returns an empty set, because augment can not contains
314          * grouping statement.
315          */
316         @Override
317         public Set<GroupingDefinition> getGroupings() {
318             return Collections.emptySet();
319         }
320
321         @Override
322         public Set<UsesNode> getUses() {
323             return uses;
324         }
325
326         private void setUses(Set<UsesNode> uses) {
327             if (uses != null) {
328                 this.uses = uses;
329             }
330         }
331
332         /**
333          * Always returns an empty set, because augment can not contains type
334          * definitions.
335          */
336         @Override
337         public Set<TypeDefinition<?>> getTypeDefinitions() {
338             return Collections.emptySet();
339         }
340
341         @Override
342         public String getDescription() {
343             return description;
344         }
345
346         private void setDescription(String description) {
347             this.description = description;
348         }
349
350         @Override
351         public String getReference() {
352             return reference;
353         }
354
355         private void setReference(String reference) {
356             this.reference = reference;
357         }
358
359         @Override
360         public Status getStatus() {
361             return status;
362         }
363
364         private void setStatus(Status status) {
365             this.status = status;
366         }
367
368         @Override
369         public List<UnknownSchemaNode> getUnknownSchemaNodes() {
370             return unknownNodes;
371         }
372
373         private void setUnknownSchemaNodes(List<UnknownSchemaNode> unknownSchemaNodes) {
374             if (unknownSchemaNodes != null) {
375                 this.unknownNodes = unknownSchemaNodes;
376             }
377         }
378
379         @Override
380         public DataSchemaNode getDataChildByName(QName name) {
381             return childNodes.get(name);
382         }
383
384         @Override
385         public DataSchemaNode getDataChildByName(String name) {
386             DataSchemaNode result = null;
387             for (Map.Entry<QName, DataSchemaNode> entry : childNodes.entrySet()) {
388                 if (entry.getKey().getLocalName().equals(name)) {
389                     result = entry.getValue();
390                     break;
391                 }
392             }
393             return result;
394         }
395
396         @Override
397         public int hashCode() {
398             final int prime = 17;
399             int result = 1;
400             result = prime * result + ((targetPath == null) ? 0 : targetPath.hashCode());
401             result = prime * result + ((whenCondition == null) ? 0 : whenCondition.hashCode());
402             result = prime * result + ((childNodes == null) ? 0 : childNodes.hashCode());
403             return result;
404         }
405
406         @Override
407         public boolean equals(Object obj) {
408             if (this == obj) {
409                 return true;
410             }
411             if (obj == null) {
412                 return false;
413             }
414             if (getClass() != obj.getClass()) {
415                 return false;
416             }
417             AugmentationSchemaImpl other = (AugmentationSchemaImpl) obj;
418             if (targetPath == null) {
419                 if (other.targetPath != null) {
420                     return false;
421                 }
422             } else if (!targetPath.equals(other.targetPath)) {
423                 return false;
424             }
425             if (whenCondition == null) {
426                 if (other.whenCondition != null) {
427                     return false;
428                 }
429             } else if (!whenCondition.equals(other.whenCondition)) {
430                 return false;
431             }
432             if (childNodes == null) {
433                 if (other.childNodes != null) {
434                     return false;
435                 }
436             } else if (!childNodes.equals(other.childNodes)) {
437                 return false;
438             }
439             return true;
440         }
441
442         @Override
443         public String toString() {
444             StringBuilder sb = new StringBuilder(AugmentationSchemaImpl.class.getSimpleName());
445             sb.append("[");
446             sb.append("targetPath=" + targetPath);
447             sb.append(", when=" + whenCondition);
448             sb.append("]");
449             return sb.toString();
450         }
451     }
452
453 }