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