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