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