Merge "BUG-994: improve CopyUtils performance"
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / builder / impl / CopyUtils.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.util.ArrayList;
11
12 import org.opendaylight.yangtools.yang.common.QName;
13 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
14 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
15 import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationSchemaBuilder;
16 import org.opendaylight.yangtools.yang.parser.builder.api.Builder;
17 import org.opendaylight.yangtools.yang.parser.builder.api.ConstraintsBuilder;
18 import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder;
19 import org.opendaylight.yangtools.yang.parser.builder.api.GroupingBuilder;
20 import org.opendaylight.yangtools.yang.parser.builder.api.SchemaNodeBuilder;
21 import org.opendaylight.yangtools.yang.parser.builder.api.TypeDefinitionBuilder;
22 import org.opendaylight.yangtools.yang.parser.builder.api.UnknownSchemaNodeBuilder;
23 import org.opendaylight.yangtools.yang.parser.builder.api.UsesNodeBuilder;
24 import org.opendaylight.yangtools.yang.parser.util.YangParseException;
25
26 public final class CopyUtils {
27
28     private CopyUtils() {
29     }
30
31     /**
32      * Create copy of DataSchemaNodeBuilder with new parent. If updateQName is
33      * true, qname of node will be corrected based on new parent.
34      *
35      * @param old
36      *            builder to copy
37      * @param newParent
38      *            new parent
39      * @param updateQName
40      *            flag to indicate if qname should be updated based on new
41      *            parent location
42      * @return copy of given builder
43      */
44     public static DataSchemaNodeBuilder copy(final DataSchemaNodeBuilder old, final Builder newParent, final boolean updateQName) {
45         if (old instanceof AnyXmlBuilder) {
46             return copy((AnyXmlBuilder) old, newParent, updateQName);
47         } else if (old instanceof ChoiceBuilder) {
48             return copy((ChoiceBuilder) old, newParent, updateQName);
49         } else if (old instanceof ContainerSchemaNodeBuilder) {
50             return copy((ContainerSchemaNodeBuilder) old, newParent, updateQName);
51         } else if (old instanceof LeafSchemaNodeBuilder) {
52             return copy((LeafSchemaNodeBuilder) old, newParent, updateQName);
53         } else if (old instanceof LeafListSchemaNodeBuilder) {
54             return copy((LeafListSchemaNodeBuilder) old, newParent, updateQName);
55         } else if (old instanceof ListSchemaNodeBuilder) {
56             return copy((ListSchemaNodeBuilder) old, newParent, updateQName);
57         } else if (old instanceof ChoiceCaseBuilder) {
58             return copy((ChoiceCaseBuilder) old, newParent, updateQName);
59         } else {
60             throw new YangParseException(old.getModuleName(), old.getLine(),
61                     "Failed to copy node: Unknown type of DataSchemaNode: " + old);
62         }
63     }
64
65     private static AnyXmlBuilder copy(final AnyXmlBuilder old, final Builder newParent, final boolean updateQName) {
66         DataBean data = getdata(old, newParent, updateQName);
67         QName newQName = data.qname;
68         SchemaPath newSchemaPath = data.schemaPath;
69
70         AnyXmlBuilder copy = new AnyXmlBuilder(newParent.getModuleName(), newParent.getLine(), newQName, newSchemaPath);
71         copyConstraints(copy.getConstraints(), old.getConstraints());
72         copy.setParent(newParent);
73         copy.setDescription(old.getDescription());
74         copy.setReference(old.getReference());
75         copy.setStatus(old.getStatus());
76         copy.setAugmenting(old.isAugmenting());
77         copy.setAddedByUses(old.isAddedByUses());
78         copy.setConfiguration(old.isConfiguration());
79         for (UnknownSchemaNodeBuilder un : old.getUnknownNodes()) {
80             copy.addUnknownNodeBuilder((copy(un, copy, updateQName)));
81         }
82
83         return copy;
84     }
85
86     private static ChoiceBuilder copy(final ChoiceBuilder old, final Builder newParent, final boolean updateQName) {
87         DataBean data = getdata(old, newParent, updateQName);
88         QName newQName = data.qname;
89         SchemaPath newSchemaPath = data.schemaPath;
90
91         ChoiceBuilder copy = new ChoiceBuilder(newParent.getModuleName(), newParent.getLine(), newQName, newSchemaPath);
92         copyConstraints(copy.getConstraints(), old.getConstraints());
93         copy.setParent(newParent);
94         copy.setDescription(old.getDescription());
95         copy.setReference(old.getReference());
96         copy.setStatus(old.getStatus());
97         copy.setAugmenting(old.isAugmenting());
98         copy.setAddedByUses(old.isAddedByUses());
99         copy.setConfiguration(old.isConfiguration());
100         for (ChoiceCaseBuilder childNode : old.getCases()) {
101             copy.addCase(copy(childNode, copy, updateQName));
102         }
103         for (AugmentationSchemaBuilder augment : old.getAugmentationBuilders()) {
104             copy.addAugmentation(copyAugment(augment, copy));
105         }
106         for (UnknownSchemaNodeBuilder un : old.getUnknownNodes()) {
107             copy.addUnknownNodeBuilder((copy(un, copy, updateQName)));
108         }
109
110         return copy;
111     }
112
113     private static ChoiceCaseBuilder copy(final ChoiceCaseBuilder old, final Builder newParent, final boolean updateQName) {
114         DataBean data = getdata(old, newParent, updateQName);
115         QName newQName = data.qname;
116         SchemaPath newSchemaPath = data.schemaPath;
117
118         ChoiceCaseBuilder copy = new ChoiceCaseBuilder(newParent.getModuleName(), newParent.getLine(), newQName, newSchemaPath);
119         copyConstraints(copy.getConstraints(), old.getConstraints());
120         copy.setParent(newParent);
121         copy.setDescription(old.getDescription());
122         copy.setReference(old.getReference());
123         copy.setStatus(old.getStatus());
124         copy.setAugmenting(old.isAugmenting());
125         for (DataSchemaNodeBuilder childNode : old.getChildNodeBuilders()) {
126             copy.addChildNode(copy(childNode, copy, updateQName));
127         }
128         copy.getGroupings().addAll(old.getGroupings());
129         for (GroupingBuilder grouping : old.getGroupingBuilders()) {
130             copy.addGrouping(copy(grouping, copy, updateQName));
131         }
132         for (TypeDefinitionBuilder tdb : old.getTypeDefinitionBuilders()) {
133             copy.addTypedef(copy(tdb, copy, updateQName));
134         }
135         for (UsesNodeBuilder oldUses : old.getUsesNodeBuilders()) {
136             copy.addUsesNode(copyUses(oldUses, copy));
137         }
138         for (UnknownSchemaNodeBuilder un : old.getUnknownNodes()) {
139             copy.addUnknownNodeBuilder((copy(un, copy, updateQName)));
140         }
141
142         return copy;
143     }
144
145     private static ContainerSchemaNodeBuilder copy(final ContainerSchemaNodeBuilder old, final Builder newParent,
146             final boolean updateQName) {
147         DataBean data = getdata(old, newParent, updateQName);
148         QName newQName = data.qname;
149         SchemaPath newSchemaPath = data.schemaPath;
150
151         ContainerSchemaNodeBuilder copy = new ContainerSchemaNodeBuilder(newParent.getModuleName(),
152                 newParent.getLine(), newQName, newSchemaPath);
153         copyConstraints(copy.getConstraints(), old.getConstraints());
154         copy.setParent(newParent);
155         copy.setDescription(old.getDescription());
156         copy.setReference(old.getReference());
157         copy.setStatus(old.getStatus());
158         copy.setPresence(old.isPresence());
159         copy.setAugmenting(old.isAugmenting());
160         copy.setAddedByUses(old.isAddedByUses());
161         copy.setConfiguration(old.isConfiguration());
162         for (DataSchemaNodeBuilder childNode : old.getChildNodeBuilders()) {
163             copy.addChildNode(copy(childNode, copy, updateQName));
164         }
165         copy.getGroupings().addAll(old.getGroupings());
166         for (GroupingBuilder grouping : old.getGroupingBuilders()) {
167             copy.addGrouping(copy(grouping, copy, updateQName));
168         }
169         for (TypeDefinitionBuilder tdb : old.getTypeDefinitionBuilders()) {
170             copy.addTypedef(copy(tdb, copy, updateQName));
171         }
172         for (UsesNodeBuilder oldUses : old.getUsesNodeBuilders()) {
173             copy.addUsesNode(copyUses(oldUses, copy));
174         }
175         for (AugmentationSchemaBuilder augment : old.getAugmentationBuilders()) {
176             copy.addAugmentation(copyAugment(augment, copy));
177         }
178         for (UnknownSchemaNodeBuilder un : old.getUnknownNodes()) {
179             copy.addUnknownNodeBuilder((copy(un, copy, updateQName)));
180         }
181
182         return copy;
183     }
184
185     private static LeafSchemaNodeBuilder copy(final LeafSchemaNodeBuilder old, final Builder newParent, final boolean updateQName) {
186         DataBean data = getdata(old, newParent, updateQName);
187         QName newQName = data.qname;
188         SchemaPath newSchemaPath = data.schemaPath;
189
190         LeafSchemaNodeBuilder copy = new LeafSchemaNodeBuilder(newParent.getModuleName(), newParent.getLine(),
191                 newQName, newSchemaPath);
192         copyConstraints(copy.getConstraints(), old.getConstraints());
193         copy.setParent(newParent);
194         copy.setDescription(old.getDescription());
195         copy.setReference(old.getReference());
196         copy.setStatus(old.getStatus());
197         copy.setAugmenting(old.isAugmenting());
198         copy.setAddedByUses(old.isAddedByUses());
199         copy.setConfiguration(old.isConfiguration());
200         for (UnknownSchemaNodeBuilder un : old.getUnknownNodes()) {
201             copy.addUnknownNodeBuilder((copy(un, copy, updateQName)));
202         }
203
204         if (old.getType() == null) {
205             copy.setTypedef(copy(old.getTypedef(), copy, updateQName));
206         } else {
207             copy.setType(old.getType());
208         }
209
210         copy.setDefaultStr(old.getDefaultStr());
211         copy.setUnits(old.getUnits());
212
213         return copy;
214     }
215
216     public static LeafListSchemaNodeBuilder copy(final LeafListSchemaNodeBuilder old, final Builder newParent, final boolean updateQName) {
217         DataBean data = getdata(old, newParent, updateQName);
218         QName newQName = data.qname;
219         SchemaPath newSchemaPath = data.schemaPath;
220
221         LeafListSchemaNodeBuilder copy = new LeafListSchemaNodeBuilder(newParent.getModuleName(), newParent.getLine(),
222                 newQName, newSchemaPath);
223         copyConstraints(copy.getConstraints(), old.getConstraints());
224         copy.setParent(newParent);
225         copy.setDescription(old.getDescription());
226         copy.setReference(old.getReference());
227         copy.setStatus(old.getStatus());
228         copy.setAugmenting(old.isAugmenting());
229         copy.setAddedByUses(old.isAddedByUses());
230         copy.setConfiguration(old.isConfiguration());
231         for (UnknownSchemaNodeBuilder un : old.getUnknownNodes()) {
232             copy.addUnknownNodeBuilder((copy(un, copy, updateQName)));
233         }
234
235         if (old.getType() == null) {
236             copy.setTypedef(copy(old.getTypedef(), copy, updateQName));
237         } else {
238             copy.setType(old.getType());
239         }
240
241         copy.setUserOrdered(old.isUserOrdered());
242
243         return copy;
244     }
245
246     private static ListSchemaNodeBuilder copy(final ListSchemaNodeBuilder old, final Builder newParent, final boolean updateQName) {
247         DataBean data = getdata(old, newParent, updateQName);
248         QName newQName = data.qname;
249         SchemaPath newSchemaPath = data.schemaPath;
250
251         ListSchemaNodeBuilder copy = new ListSchemaNodeBuilder(newParent.getModuleName(), newParent.getLine(),
252                 newQName, newSchemaPath);
253         copyConstraints(copy.getConstraints(), old.getConstraints());
254         copy.setParent(newParent);
255         copy.setDescription(old.getDescription());
256         copy.setReference(old.getReference());
257         copy.setStatus(old.getStatus());
258         copy.setAugmenting(old.isAugmenting());
259         copy.setAddedByUses(old.isAddedByUses());
260         copy.setConfiguration(old.isConfiguration());
261         for (DataSchemaNodeBuilder childNode : old.getChildNodeBuilders()) {
262             copy.addChildNode(copy(childNode, copy, updateQName));
263         }
264         copy.getGroupings().addAll(old.getGroupings());
265         for (GroupingBuilder grouping : old.getGroupingBuilders()) {
266             copy.addGrouping(copy(grouping, copy, updateQName));
267         }
268         for (TypeDefinitionBuilder tdb : old.getTypeDefinitionBuilders()) {
269             copy.addTypedef(copy(tdb, copy, updateQName));
270         }
271         for (UsesNodeBuilder oldUses : old.getUsesNodeBuilders()) {
272             copy.addUsesNode(copyUses(oldUses, copy));
273         }
274         for (AugmentationSchemaBuilder augment : old.getAugmentationBuilders()) {
275             copy.addAugmentation(copyAugment(augment, copy));
276         }
277         for (UnknownSchemaNodeBuilder un : old.getUnknownNodes()) {
278             copy.addUnknownNodeBuilder((copy(un, copy, updateQName)));
279         }
280
281         copy.setUserOrdered(old.isUserOrdered());
282         copy.setKeys(old.getKeys());
283
284         return copy;
285     }
286
287     public static GroupingBuilder copy(final GroupingBuilder old, final Builder newParent, final boolean updateQName) {
288         DataBean data = getdata(old, newParent, updateQName);
289         QName newQName = data.qname;
290         SchemaPath newSchemaPath = data.schemaPath;
291
292         GroupingBuilderImpl copy = new GroupingBuilderImpl(newParent.getModuleName(), newParent.getLine(), newQName, newSchemaPath);
293         copy.setParent(newParent);
294         copy.setDescription(old.getDescription());
295         copy.setReference(old.getReference());
296         copy.setStatus(old.getStatus());
297         copy.setAddedByUses(old.isAddedByUses());
298         for (DataSchemaNodeBuilder childNode : old.getChildNodeBuilders()) {
299             copy.addChildNode(copy(childNode, copy, updateQName));
300         }
301         copy.getGroupings().addAll(old.getGroupings());
302         for (GroupingBuilder grouping : old.getGroupingBuilders()) {
303             copy.addGrouping(copy(grouping, copy, updateQName));
304         }
305         for (TypeDefinitionBuilder tdb : old.getTypeDefinitionBuilders()) {
306             copy.addTypedef(copy(tdb, copy, updateQName));
307         }
308         for (UsesNodeBuilder oldUses : old.getUsesNodeBuilders()) {
309             copy.addUsesNode(copyUses(oldUses, copy));
310         }
311         for (UnknownSchemaNodeBuilder un : old.getUnknownNodes()) {
312             copy.addUnknownNodeBuilder((copy(un, copy, updateQName)));
313         }
314
315         return copy;
316     }
317
318     public static TypeDefinitionBuilder copy(final TypeDefinitionBuilder old, final Builder newParent, final boolean updateQName) {
319         DataBean data = getdata(old, newParent, updateQName);
320         QName newQName = data.qname;
321         SchemaPath newSchemaPath = data.schemaPath;
322         TypeDefinitionBuilder type;
323
324         if (old instanceof UnionTypeBuilder) {
325             UnionTypeBuilder oldUnion = (UnionTypeBuilder) old;
326             type = new UnionTypeBuilder(newParent.getModuleName(), newParent.getLine());
327             type.setParent(newParent);
328             for (TypeDefinition<?> td : oldUnion.getTypes()) {
329                 type.setType(td);
330             }
331             for (TypeDefinitionBuilder tdb : oldUnion.getTypedefs()) {
332                 type.setTypedef(copy(tdb, type, updateQName));
333             }
334         } else if (old instanceof IdentityrefTypeBuilder) {
335             type = new IdentityrefTypeBuilder(newParent.getModuleName(), newParent.getLine(),
336                     ((IdentityrefTypeBuilder) old).getBaseString(), newSchemaPath);
337             type.setParent(newParent);
338         } else {
339             type = new TypeDefinitionBuilderImpl(old.getModuleName(), newParent.getLine(), newQName, old.getPath());
340             type.setParent(newParent);
341
342             if (old.getType() == null) {
343                 type.setTypedef(copy(old.getTypedef(), type, updateQName));
344             } else {
345                 type.setType(old.getType());
346             }
347
348             for (UnknownSchemaNodeBuilder un : old.getUnknownNodes()) {
349                 type.addUnknownNodeBuilder((copy(un, type, updateQName)));
350             }
351
352             type.setRanges(old.getRanges());
353             type.setLengths(old.getLengths());
354             type.setPatterns(old.getPatterns());
355             type.setFractionDigits(old.getFractionDigits());
356             type.setDescription(old.getDescription());
357             type.setReference(old.getReference());
358             type.setStatus(old.getStatus());
359             type.setUnits(old.getUnits());
360             type.setDefaultValue(old.getDefaultValue());
361             type.setAddedByUses(old.isAddedByUses());
362         }
363
364         return type;
365     }
366
367     private static ConstraintsBuilder copyConstraints(final ConstraintsBuilder newConstraints, final ConstraintsBuilder old) {
368         newConstraints.getMustDefinitions().addAll(old.getMustDefinitions());
369         newConstraints.addWhenCondition(old.getWhenCondition());
370         newConstraints.setMandatory(old.isMandatory());
371         newConstraints.setMinElements(old.getMinElements());
372         newConstraints.setMaxElements(old.getMaxElements());
373         return newConstraints;
374     }
375
376     private static UsesNodeBuilder copyUses(final UsesNodeBuilder old, final Builder newParent) {
377         UsesNodeBuilder copy = new UsesNodeBuilderImpl(newParent.getModuleName(), newParent.getLine(),
378                 old.getGroupingPathAsString());
379         copy.setParent(newParent);
380         copy.setGroupingDefinition(old.getGroupingDefinition());
381         copy.setGrouping(old.getGroupingBuilder());
382         copy.setAddedByUses(old.isAddedByUses());
383         copy.getAugmentations().addAll(old.getAugmentations());
384         copy.getRefineNodes().addAll(old.getRefineNodes());
385         copy.getRefines().addAll(old.getRefines());
386         copy.setAugmenting(old.isAugmenting());
387         return copy;
388     }
389
390     private static AugmentationSchemaBuilder copyAugment(final AugmentationSchemaBuilder old, final Builder newParent) {
391         AugmentationSchemaBuilderImpl copy = new AugmentationSchemaBuilderImpl(newParent.getModuleName(),
392                 newParent.getLine(), old.getTargetPathAsString(), old.getOrder());
393         copy.setParent(newParent);
394         copy.setCopyOf(old);
395         copy.setDescription(old.getDescription());
396         copy.setReference(old.getReference());
397         copy.setStatus(old.getStatus());
398         copy.addWhenCondition(old.getWhenCondition());
399         copy.setTargetNodeSchemaPath(old.getTargetNodeSchemaPath());
400         for (DataSchemaNodeBuilder childNode : old.getChildNodeBuilders()) {
401             copy.addChildNode(copy(childNode, copy, false));
402         }
403         for (UsesNodeBuilder oldUses : old.getUsesNodeBuilders()) {
404             copy.addUsesNode(copyUses(oldUses, copy));
405         }
406         for (UnknownSchemaNodeBuilder un : old.getUnknownNodes()) {
407             copy.addUnknownNodeBuilder((copy(un, copy, false)));
408         }
409
410         return copy;
411     }
412
413     public static UnknownSchemaNodeBuilderImpl copy(final UnknownSchemaNodeBuilder old, final Builder newParent, final boolean updateQName) {
414         DataBean data = getdata(old, newParent, updateQName);
415         QName newQName = data.qname;
416         SchemaPath newSchemaPath = data.schemaPath;
417
418         UnknownSchemaNodeBuilderImpl c = new UnknownSchemaNodeBuilderImpl(newParent.getModuleName(), newParent.getLine(),
419                 newQName, newSchemaPath);
420
421         c.setNodeType(old.getNodeType());
422         c.setNodeParameter(old.getNodeParameter());
423         c.setParent(newParent);
424         c.setDescription(old.getDescription());
425         c.setReference(old.getReference());
426         c.setStatus(old.getStatus());
427         c.setAddedByUses(old.isAddedByUses());
428         for (UnknownSchemaNodeBuilder un : old.getUnknownNodes()) {
429             c.addUnknownNodeBuilder((copy(un, c, updateQName)));
430         }
431         c.setExtensionBuilder(old.getExtensionBuilder());
432         c.setExtensionDefinition(old.getExtensionDefinition());
433
434         return c;
435     }
436
437     private static DataBean getdata(final SchemaNodeBuilder old, final Builder newParent, final boolean updateQName) {
438         final SchemaPath newSchemaPath;
439         QName newQName = null;
440         if (newParent instanceof ModuleBuilder) {
441             ModuleBuilder parent = (ModuleBuilder) newParent;
442             if (updateQName) {
443                 newQName = new QName(parent.getNamespace(), parent.getRevision(), parent.getPrefix(), old.getQName()
444                         .getLocalName());
445             } else {
446                 newQName = old.getQName();
447             }
448             newSchemaPath = SchemaPath.create(true, newQName);
449         } else if (newParent instanceof AugmentationSchemaBuilder) {
450             AugmentationSchemaBuilder augment = (AugmentationSchemaBuilder) newParent;
451             ModuleBuilder parent = BuilderUtils.getParentModule(newParent);
452             if (updateQName) {
453                 newQName = new QName(parent.getNamespace(), parent.getRevision(), parent.getPrefix(), old.getQName()
454                         .getLocalName());
455             } else {
456                 newQName = old.getQName();
457             }
458             newSchemaPath = augment.getTargetNodeSchemaPath().createChild(newQName);
459         } else if (newParent instanceof SchemaNodeBuilder) {
460             SchemaNodeBuilder parent = (SchemaNodeBuilder) newParent;
461             QName parentQName = parent.getQName();
462             if (updateQName) {
463                 newQName = new QName(parentQName.getNamespace(), parentQName.getRevision(), parentQName.getPrefix(),
464                         old.getQName().getLocalName());
465             } else {
466                 newQName = old.getQName();
467             }
468             newSchemaPath = parent.getPath().createChild(newQName);
469         } else {
470             newSchemaPath = SchemaPath.ROOT;
471         }
472
473         return new DataBean(newQName, newSchemaPath);
474     }
475
476     private static final class DataBean {
477         private final QName qname;
478         private final SchemaPath schemaPath;
479
480         private DataBean(final QName qname, final SchemaPath schemaPath) {
481             this.qname = qname;
482             this.schemaPath = schemaPath;
483         }
484     }
485
486 }