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