Added support for parsing submodules & added dependency utility parser
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / builder / impl / GroupingBuilderImpl.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.HashMap;
15 import java.util.HashSet;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Set;
19 import java.util.TreeSet;
20
21 import org.opendaylight.yangtools.yang.common.QName;
22 import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
23 import org.opendaylight.yangtools.yang.model.api.GroupingDefinition;
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.parser.builder.api.AbstractDataNodeContainerBuilder;
30 import org.opendaylight.yangtools.yang.parser.builder.api.Builder;
31 import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
32 import org.opendaylight.yangtools.yang.parser.builder.api.GroupingBuilder;
33 import org.opendaylight.yangtools.yang.parser.builder.api.TypeDefinitionBuilder;
34 import org.opendaylight.yangtools.yang.parser.builder.api.UsesNodeBuilder;
35 import org.opendaylight.yangtools.yang.parser.util.Comparators;
36 import org.opendaylight.yangtools.yang.parser.util.CopyUtils;
37 import org.opendaylight.yangtools.yang.parser.util.ParserUtils;
38 import org.opendaylight.yangtools.yang.parser.util.YangParseException;
39
40 public final class GroupingBuilderImpl extends AbstractDataNodeContainerBuilder implements GroupingBuilder {
41     private boolean isBuilt;
42     private final GroupingDefinitionImpl instance;
43     private SchemaPath schemaPath;
44
45     public GroupingBuilderImpl(final String moduleName, final int line, final QName qname, final SchemaPath path) {
46         super(moduleName, line, qname);
47         schemaPath = path;
48         instance = new GroupingDefinitionImpl(qname, path);
49     }
50
51     public GroupingBuilderImpl(final String moduleName, final int line, final QName qname, final SchemaPath path, final GroupingDefinition base) {
52         super(moduleName, line, base.getQName());
53         schemaPath = path;
54         instance = new GroupingDefinitionImpl(qname, path);
55
56         instance.description = base.getDescription();
57         instance.reference = base.getReference();
58         instance.status = base.getStatus();
59         instance.addedByUses = base.isAddedByUses();
60
61         URI ns = qname.getNamespace();
62         Date rev = qname.getRevision();
63         String pref = qname.getPrefix();
64         addedChildNodes.addAll(ParserUtils.wrapChildNodes(moduleName, line, base.getChildNodes(), path, ns, rev, pref));
65         addedGroupings.addAll(ParserUtils.wrapGroupings(moduleName, line, base.getGroupings(), path, ns, rev, pref));
66         addedTypedefs.addAll(ParserUtils.wrapTypedefs(moduleName, line, base, path, ns, rev, pref));
67         addedUnknownNodes.addAll(ParserUtils.wrapUnknownNodes(moduleName, line, base.getUnknownSchemaNodes(), path, ns,
68                 rev, pref));
69
70         instance.uses.addAll(base.getUses());
71     }
72
73     @Override
74     public GroupingDefinition build() {
75         if (!isBuilt) {
76             // CHILD NODES
77             for (DataSchemaNodeBuilder node : addedChildNodes) {
78                 DataSchemaNode child = node.build();
79                 childNodes.put(child.getQName(), child);
80             }
81             instance.addChildNodes(childNodes);
82
83             // GROUPINGS
84             for (GroupingBuilder builder : addedGroupings) {
85                 groupings.add(builder.build());
86             }
87             instance.addGroupings(groupings);
88
89             // TYPEDEFS
90             for (TypeDefinitionBuilder entry : addedTypedefs) {
91                 typedefs.add(entry.build());
92             }
93             instance.addTypeDefinitions(typedefs);
94
95             // USES
96             for (UsesNodeBuilder builder : addedUsesNodes) {
97                 usesNodes.add(builder.build());
98             }
99             instance.addUses(usesNodes);
100
101             // UNKNOWN NODES
102             for (UnknownSchemaNodeBuilder b : addedUnknownNodes) {
103                 unknownNodes.add(b.build());
104             }
105             Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP);
106             instance.addUnknownSchemaNodes(unknownNodes);
107
108             isBuilt = true;
109         }
110
111         return instance;
112     }
113
114     @Override
115     public Set<DataSchemaNodeBuilder> instantiateChildNodes(Builder newParent) {
116         final Set<DataSchemaNodeBuilder> nodes = new HashSet<>();
117         for (DataSchemaNodeBuilder node : addedChildNodes) {
118             DataSchemaNodeBuilder copy = CopyUtils.copy(node, newParent, true);
119             ParserUtils.setNodeAddedByUses(copy);
120             nodes.add(copy);
121         }
122         return nodes;
123     }
124
125     @Override
126     public Set<TypeDefinitionBuilder> instantiateTypedefs(Builder newParent) {
127         final Set<TypeDefinitionBuilder> nodes = new HashSet<>();
128         for (TypeDefinitionBuilder node : addedTypedefs) {
129             TypeDefinitionBuilder copy = CopyUtils.copy(node, newParent, true);
130             nodes.add(copy);
131         }
132         return nodes;
133     }
134
135     @Override
136     public Set<GroupingBuilder> instantiateGroupings(Builder newParent) {
137         final Set<GroupingBuilder> nodes = new HashSet<>();
138         for (GroupingBuilder node : addedGroupings) {
139             GroupingBuilder copy = CopyUtils.copy(node, newParent, true);
140             copy.setAddedByUses(true);
141             for (DataSchemaNodeBuilder childNode : copy.getChildNodeBuilders()) {
142                 ParserUtils.setNodeAddedByUses(childNode);
143             }
144             nodes.add(copy);
145         }
146         return nodes;
147     }
148
149     @Override
150     public Set<UnknownSchemaNodeBuilder> instantiateUnknownNodes(Builder newParent) {
151         final Set<UnknownSchemaNodeBuilder> nodes = new HashSet<>();
152         for (UnknownSchemaNodeBuilder node : addedUnknownNodes) {
153             UnknownSchemaNodeBuilder copy = CopyUtils.copy(node, newParent, true);
154             copy.setAddedByUses(true);
155             nodes.add(copy);
156         }
157         return nodes;
158     }
159
160     @Override
161     public Set<TypeDefinitionBuilder> getTypeDefinitionBuilders() {
162         return addedTypedefs;
163     }
164
165     @Override
166     public void addTypedef(final TypeDefinitionBuilder type) {
167         String typeName = type.getQName().getLocalName();
168         for (TypeDefinitionBuilder addedTypedef : addedTypedefs) {
169             throw new YangParseException(moduleName, type.getLine(), "Can not add typedef '" + typeName
170                     + "': typedef with same name already declared at line " + addedTypedef.getLine());
171         }
172         addedTypedefs.add(type);
173     }
174
175     @Override
176     public SchemaPath getPath() {
177         return schemaPath;
178     }
179
180     @Override
181     public String getDescription() {
182         return instance.description;
183     }
184
185     @Override
186     public void setDescription(final String description) {
187         instance.description = description;
188     }
189
190     @Override
191     public String getReference() {
192         return instance.reference;
193     }
194
195     @Override
196     public void setReference(final String reference) {
197         instance.reference = reference;
198     }
199
200     @Override
201     public Status getStatus() {
202         return instance.status;
203     }
204
205     @Override
206     public void setStatus(Status status) {
207         if (status != null) {
208             instance.status = status;
209         }
210     }
211
212     @Override
213     public boolean isAddedByUses() {
214         return instance.addedByUses;
215     }
216
217     @Override
218     public void setAddedByUses(final boolean addedByUses) {
219         instance.addedByUses = addedByUses;
220     }
221
222     @Override
223     public String toString() {
224         return "grouping " + qname.getLocalName();
225     }
226
227     @Override
228     public int hashCode() {
229         final int prime = 31;
230         int result = 1;
231         result = prime * result + ((parentBuilder == null) ? 0 : parentBuilder.hashCode());
232         result = prime * result + ((schemaPath == null) ? 0 : schemaPath.hashCode());
233         return result;
234     }
235
236     @Override
237     public boolean equals(Object obj) {
238         if (this == obj) {
239             return true;
240         }
241         if (obj == null) {
242             return false;
243         }
244         if (getClass() != obj.getClass()) {
245             return false;
246         }
247         if (!super.equals(obj)) {
248             return false;
249         }
250         final GroupingBuilderImpl other = (GroupingBuilderImpl) obj;
251         if (parentBuilder == null) {
252             if (other.parentBuilder != null) {
253                 return false;
254             }
255         } else if (!parentBuilder.equals(other.parentBuilder)) {
256             return false;
257         }
258         if (schemaPath == null) {
259             if (other.schemaPath != null) {
260                 return false;
261             }
262         } else if (!schemaPath.equals(other.schemaPath)) {
263             return false;
264         }
265         return true;
266     }
267
268
269     private final class GroupingDefinitionImpl implements GroupingDefinition {
270         private final QName qname;
271         private final SchemaPath path;
272         private String description;
273         private String reference;
274         private Status status;
275         private boolean addedByUses;
276         private final Map<QName, DataSchemaNode> childNodes = new HashMap<>();
277         private final Set<GroupingDefinition> groupings = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
278         private final Set<TypeDefinition<?>> typeDefinitions = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
279         private final Set<UsesNode> uses = new HashSet<>();
280         private final List<UnknownSchemaNode> unknownNodes = new ArrayList<>();
281
282         private GroupingDefinitionImpl(final QName qname, final SchemaPath path) {
283             this.qname = qname;
284             this.path = path;
285         }
286
287         @Override
288         public QName getQName() {
289             return qname;
290         }
291
292         @Override
293         public SchemaPath getPath() {
294             return path;
295         }
296
297         @Override
298         public String getDescription() {
299             return description;
300         }
301
302         @Override
303         public String getReference() {
304             return reference;
305         }
306
307         @Override
308         public Status getStatus() {
309             return status;
310         }
311
312         @Override
313         public boolean isAddedByUses() {
314             return addedByUses;
315         }
316
317         @Override
318         public Set<DataSchemaNode> getChildNodes() {
319             final Set<DataSchemaNode> result = new TreeSet<>(Comparators.SCHEMA_NODE_COMP);
320             result.addAll(childNodes.values());
321             return Collections.unmodifiableSet(result);
322         }
323
324         private void addChildNodes(Map<QName, DataSchemaNode> childNodes) {
325             if (childNodes != null) {
326                 this.childNodes.putAll(childNodes);
327             }
328
329         }
330
331         @Override
332         public Set<GroupingDefinition> getGroupings() {
333             return Collections.unmodifiableSet(groupings);
334         }
335
336         private void addGroupings(Set<GroupingDefinition> groupings) {
337             if (groupings != null) {
338                 this.groupings.addAll(groupings);
339             }
340         }
341
342         @Override
343         public Set<UsesNode> getUses() {
344             return Collections.unmodifiableSet(uses);
345         }
346
347         private void addUses(Set<UsesNode> uses) {
348             if (uses != null) {
349                 this.uses.addAll(uses);
350             }
351         }
352
353         @Override
354         public Set<TypeDefinition<?>> getTypeDefinitions() {
355             return Collections.unmodifiableSet(typeDefinitions);
356         }
357
358         private void addTypeDefinitions(Set<TypeDefinition<?>> typeDefinitions) {
359             if (typeDefinitions != null) {
360                 this.typeDefinitions.addAll(typeDefinitions);
361             }
362         }
363
364         @Override
365         public List<UnknownSchemaNode> getUnknownSchemaNodes() {
366             return Collections.unmodifiableList(unknownNodes);
367         }
368
369         private void addUnknownSchemaNodes(List<UnknownSchemaNode> unknownNodes) {
370             if (unknownNodes != null) {
371                 this.unknownNodes.addAll(unknownNodes);
372             }
373         }
374
375         @Override
376         public DataSchemaNode getDataChildByName(QName name) {
377             return childNodes.get(name);
378         }
379
380         @Override
381         public DataSchemaNode getDataChildByName(String name) {
382             DataSchemaNode result = null;
383             for (Map.Entry<QName, DataSchemaNode> entry : childNodes.entrySet()) {
384                 if (entry.getKey().getLocalName().equals(name)) {
385                     result = entry.getValue();
386                     break;
387                 }
388             }
389             return result;
390         }
391
392         @Override
393         public int hashCode() {
394             final int prime = 31;
395             int result = 1;
396             result = prime * result + ((qname == null) ? 0 : qname.hashCode());
397             result = prime * result + ((path == null) ? 0 : path.hashCode());
398             return result;
399         }
400
401         @Override
402         public boolean equals(Object obj) {
403             if (this == obj) {
404                 return true;
405             }
406             if (obj == null) {
407                 return false;
408             }
409             if (getClass() != obj.getClass()) {
410                 return false;
411             }
412             final GroupingDefinitionImpl other = (GroupingDefinitionImpl) obj;
413             if (qname == null) {
414                 if (other.qname != null) {
415                     return false;
416                 }
417             } else if (!qname.equals(other.qname)) {
418                 return false;
419             }
420             if (path == null) {
421                 if (other.path != null) {
422                     return false;
423                 }
424             } else if (!path.equals(other.path)) {
425                 return false;
426             }
427             return true;
428         }
429
430         @Override
431         public String toString() {
432             StringBuilder sb = new StringBuilder(GroupingDefinitionImpl.class.getSimpleName());
433             sb.append("[");
434             sb.append("qname=" + qname);
435             sb.append("]");
436             return sb.toString();
437         }
438     }
439
440 }