2e3f0cc860ba80d22cef4d01b33b47d531626e10
[controller.git] / opendaylight / sal / yang-prototype / code-generator / yang-model-parser-impl / src / main / java / org / opendaylight / controller / yang / parser / util / ParserUtils.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.controller.yang.parser.util;
9
10 import java.lang.reflect.Method;
11 import java.math.BigDecimal;
12 import java.util.ArrayList;
13 import java.util.List;
14
15 import org.opendaylight.controller.yang.common.QName;
16 import org.opendaylight.controller.yang.model.api.ModuleImport;
17 import org.opendaylight.controller.yang.model.api.MustDefinition;
18 import org.opendaylight.controller.yang.model.api.SchemaPath;
19 import org.opendaylight.controller.yang.model.api.TypeDefinition;
20 import org.opendaylight.controller.yang.model.api.type.BinaryTypeDefinition;
21 import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition;
22 import org.opendaylight.controller.yang.model.api.type.BooleanTypeDefinition;
23 import org.opendaylight.controller.yang.model.api.type.DecimalTypeDefinition;
24 import org.opendaylight.controller.yang.model.api.type.EmptyTypeDefinition;
25 import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition;
26 import org.opendaylight.controller.yang.model.api.type.EnumTypeDefinition.EnumPair;
27 import org.opendaylight.controller.yang.model.api.type.IdentityrefTypeDefinition;
28 import org.opendaylight.controller.yang.model.api.type.InstanceIdentifierTypeDefinition;
29 import org.opendaylight.controller.yang.model.api.type.IntegerTypeDefinition;
30 import org.opendaylight.controller.yang.model.api.type.LeafrefTypeDefinition;
31 import org.opendaylight.controller.yang.model.api.type.LengthConstraint;
32 import org.opendaylight.controller.yang.model.api.type.PatternConstraint;
33 import org.opendaylight.controller.yang.model.api.type.RangeConstraint;
34 import org.opendaylight.controller.yang.model.api.type.StringTypeDefinition;
35 import org.opendaylight.controller.yang.model.api.type.UnionTypeDefinition;
36 import org.opendaylight.controller.yang.model.api.type.UnsignedIntegerTypeDefinition;
37 import org.opendaylight.controller.yang.model.util.BinaryType;
38 import org.opendaylight.controller.yang.model.util.BitsType;
39 import org.opendaylight.controller.yang.model.util.BooleanType;
40 import org.opendaylight.controller.yang.model.util.Decimal64;
41 import org.opendaylight.controller.yang.model.util.EmptyType;
42 import org.opendaylight.controller.yang.model.util.EnumerationType;
43 import org.opendaylight.controller.yang.model.util.IdentityrefType;
44 import org.opendaylight.controller.yang.model.util.InstanceIdentifier;
45 import org.opendaylight.controller.yang.model.util.Int16;
46 import org.opendaylight.controller.yang.model.util.Int32;
47 import org.opendaylight.controller.yang.model.util.Int64;
48 import org.opendaylight.controller.yang.model.util.Int8;
49 import org.opendaylight.controller.yang.model.util.Leafref;
50 import org.opendaylight.controller.yang.model.util.StringType;
51 import org.opendaylight.controller.yang.model.util.UnionType;
52 import org.opendaylight.controller.yang.parser.builder.api.AugmentationSchemaBuilder;
53 import org.opendaylight.controller.yang.parser.builder.api.Builder;
54 import org.opendaylight.controller.yang.parser.builder.api.DataNodeContainerBuilder;
55 import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
56 import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
57 import org.opendaylight.controller.yang.parser.builder.api.SchemaNodeBuilder;
58 import org.opendaylight.controller.yang.parser.builder.api.TypeAwareBuilder;
59 import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
60 import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
61 import org.opendaylight.controller.yang.parser.builder.impl.AnyXmlBuilder;
62 import org.opendaylight.controller.yang.parser.builder.impl.ChoiceBuilder;
63 import org.opendaylight.controller.yang.parser.builder.impl.ChoiceCaseBuilder;
64 import org.opendaylight.controller.yang.parser.builder.impl.ConstraintsBuilder;
65 import org.opendaylight.controller.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
66 import org.opendaylight.controller.yang.parser.builder.impl.GroupingBuilderImpl;
67 import org.opendaylight.controller.yang.parser.builder.impl.LeafListSchemaNodeBuilder;
68 import org.opendaylight.controller.yang.parser.builder.impl.LeafSchemaNodeBuilder;
69 import org.opendaylight.controller.yang.parser.builder.impl.ListSchemaNodeBuilder;
70 import org.opendaylight.controller.yang.parser.builder.impl.ModuleBuilder;
71 import org.opendaylight.controller.yang.parser.builder.impl.TypeDefinitionBuilderImpl;
72 import org.opendaylight.controller.yang.parser.builder.impl.UnknownSchemaNodeBuilder;
73 import org.opendaylight.controller.yang.parser.builder.impl.UsesNodeBuilderImpl;
74
75 public final class ParserUtils {
76
77     private ParserUtils() {
78     }
79
80     /**
81      * Get module import referenced by given prefix.
82      *
83      * @param builder
84      *            module to search
85      * @param prefix
86      *            prefix associated with import
87      * @return ModuleImport based on given prefix
88      */
89     public static ModuleImport getModuleImport(final ModuleBuilder builder,
90             final String prefix) {
91         ModuleImport moduleImport = null;
92         for (ModuleImport mi : builder.getModuleImports()) {
93             if (mi.getPrefix().equals(prefix)) {
94                 moduleImport = mi;
95                 break;
96             }
97         }
98         return moduleImport;
99     }
100
101     /**
102      * Parse uses path.
103      *
104      * @param usesPath
105      *            as String
106      * @return SchemaPath from given String
107      */
108     public static SchemaPath parseUsesPath(final String usesPath) {
109         final boolean absolute = usesPath.startsWith("/");
110         final String[] splittedPath = usesPath.split("/");
111         final List<QName> path = new ArrayList<QName>();
112         QName name;
113         for (String pathElement : splittedPath) {
114             if (pathElement.length() > 0) {
115                 final String[] splittedElement = pathElement.split(":");
116                 if (splittedElement.length == 1) {
117                     name = new QName(null, null, null, splittedElement[0]);
118                 } else {
119                     name = new QName(null, null, splittedElement[0],
120                             splittedElement[1]);
121                 }
122                 path.add(name);
123             }
124         }
125         return new SchemaPath(path, absolute);
126     }
127
128     /**
129      * Add all augment's child nodes to given target.
130      *
131      * @param augment
132      * @param target
133      */
134     public static void fillAugmentTarget(
135             final AugmentationSchemaBuilder augment,
136             final DataNodeContainerBuilder target) {
137         for (DataSchemaNodeBuilder builder : augment.getChildNodes()) {
138             builder.setAugmenting(true);
139             correctAugmentChildPath(augment, target.getPath());
140             target.addChildNode(builder);
141         }
142     }
143
144     public static void fillAugmentTarget(
145             final AugmentationSchemaBuilder augment,
146             final ChoiceBuilder target) {
147         for (DataSchemaNodeBuilder builder : augment.getChildNodes()) {
148             builder.setAugmenting(true);
149             correctAugmentChildPath(augment, target.getPath());
150             target.addChildNode(builder);
151         }
152     }
153
154     private static void correctAugmentChildPath(final DataNodeContainerBuilder node,
155             final SchemaPath parentSchemaPath) {
156         for (DataSchemaNodeBuilder builder : node.getChildNodes()) {
157
158             // add correct path
159             List<QName> targetNodePath = new ArrayList<QName>(
160                     parentSchemaPath.getPath());
161             targetNodePath.add(builder.getQName());
162             builder.setPath(new SchemaPath(targetNodePath, true));
163
164             if (builder instanceof DataNodeContainerBuilder) {
165                 DataNodeContainerBuilder cnb = (DataNodeContainerBuilder) builder;
166                 correctAugmentChildPath(cnb, builder.getPath());
167             }
168
169             // if child can contains type, correct path for this type too
170             if (builder instanceof TypeAwareBuilder) {
171                 TypeAwareBuilder nodeBuilder = (TypeAwareBuilder) builder;
172                 QName nodeBuilderQName = nodeBuilder.getQName();
173                 TypeDefinition<?> nodeBuilderType = nodeBuilder.getType();
174                 if (nodeBuilderType != null) {
175                     TypeDefinition<?> newType = createCorrectTypeDefinition(
176                             parentSchemaPath, nodeBuilderQName, nodeBuilderType);
177                     nodeBuilder.setType(newType);
178                 } else {
179                     TypeDefinitionBuilder nodeBuilderTypedef = nodeBuilder
180                             .getTypedef();
181                     SchemaPath newSchemaPath = createNewSchemaPath(
182                             nodeBuilderTypedef.getPath(), nodeBuilderQName,
183                             nodeBuilderTypedef.getQName());
184                     nodeBuilderTypedef.setPath(newSchemaPath);
185                 }
186             }
187         }
188     }
189
190     private static TypeDefinition<?> createCorrectTypeDefinition(
191             SchemaPath parentSchemaPath, QName nodeQName,
192             TypeDefinition<?> nodeType) {
193         TypeDefinition<?> result = null;
194         SchemaPath newSchemaPath = null;
195         if (nodeType != null) {
196             if (nodeType instanceof BinaryTypeDefinition) {
197                 BinaryTypeDefinition binType = (BinaryTypeDefinition) nodeType;
198                 newSchemaPath = createNewSchemaPath(parentSchemaPath,
199                         nodeQName, binType.getQName());
200                 List<Byte> bytes = (List<Byte>) binType.getDefaultValue();
201                 result = new BinaryType(newSchemaPath, bytes,
202                         binType.getLengthConstraints(), binType.getUnits());
203             } else if (nodeType instanceof BitsTypeDefinition) {
204                 BitsTypeDefinition bitsType = (BitsTypeDefinition) nodeType;
205                 newSchemaPath = createNewSchemaPath(parentSchemaPath,
206                         nodeQName, nodeType.getQName());
207                 result = new BitsType(newSchemaPath, bitsType.getBits(),
208                         bitsType.getUnits());
209             } else if (nodeType instanceof BooleanTypeDefinition) {
210                 BooleanTypeDefinition booleanType = (BooleanTypeDefinition) nodeType;
211                 newSchemaPath = createNewSchemaPath(parentSchemaPath,
212                         nodeQName, booleanType.getQName());
213                 result = new BooleanType(newSchemaPath,
214                         (Boolean) booleanType.getDefaultValue(),
215                         booleanType.getUnits());
216             } else if (nodeType instanceof DecimalTypeDefinition) {
217                 DecimalTypeDefinition decimalType = (DecimalTypeDefinition) nodeType;
218                 newSchemaPath = createNewSchemaPath(parentSchemaPath,
219                         nodeQName, decimalType.getQName());
220                 BigDecimal defaultValue = (BigDecimal) decimalType
221                         .getDefaultValue();
222                 result = new Decimal64(newSchemaPath, decimalType.getUnits(),
223                         defaultValue, decimalType.getRangeStatements(),
224                         decimalType.getFractionDigits());
225             } else if (nodeType instanceof EmptyTypeDefinition) {
226                 newSchemaPath = createNewSchemaPath(parentSchemaPath,
227                         nodeQName, nodeType.getQName());
228                 result = new EmptyType(newSchemaPath);
229             } else if (nodeType instanceof EnumTypeDefinition) {
230                 EnumTypeDefinition enumType = (EnumTypeDefinition) nodeType;
231                 newSchemaPath = createNewSchemaPath(parentSchemaPath,
232                         nodeQName, enumType.getQName());
233                 result = new EnumerationType(newSchemaPath,
234                         (EnumPair) enumType.getDefaultValue(),
235                         enumType.getValues(), enumType.getUnits());
236             } else if (nodeType instanceof IdentityrefTypeDefinition) {
237                 IdentityrefTypeDefinition idrefType = (IdentityrefTypeDefinition) nodeType;
238                 newSchemaPath = createNewSchemaPath(parentSchemaPath,
239                         nodeQName, idrefType.getQName());
240                 result = new IdentityrefType(idrefType.getIdentity(),
241                         newSchemaPath);
242             } else if (nodeType instanceof InstanceIdentifierTypeDefinition) {
243                 InstanceIdentifierTypeDefinition instIdType = (InstanceIdentifierTypeDefinition) nodeType;
244                 newSchemaPath = createNewSchemaPath(parentSchemaPath,
245                         nodeQName, instIdType.getQName());
246                 return new InstanceIdentifier(newSchemaPath,
247                         instIdType.getPathStatement(),
248                         instIdType.requireInstance());
249             } else if (nodeType instanceof StringTypeDefinition) {
250                 result = copyStringType(parentSchemaPath, nodeQName,
251                         (StringTypeDefinition) nodeType);
252             } else if (nodeType instanceof IntegerTypeDefinition) {
253                 result = copyIntType(parentSchemaPath, nodeQName,
254                         (IntegerTypeDefinition) nodeType);
255             } else if (nodeType instanceof UnsignedIntegerTypeDefinition) {
256                 result = copyUIntType(parentSchemaPath, nodeQName,
257                         (UnsignedIntegerTypeDefinition) nodeType);
258             } else if (nodeType instanceof LeafrefTypeDefinition) {
259                 newSchemaPath = createNewSchemaPath(parentSchemaPath,
260                         nodeQName, nodeType.getQName());
261                 result = new Leafref(newSchemaPath,
262                         ((LeafrefTypeDefinition) nodeType).getPathStatement());
263             } else if (nodeType instanceof UnionTypeDefinition) {
264                 UnionTypeDefinition unionType = (UnionTypeDefinition) nodeType;
265                 newSchemaPath = createNewSchemaPath(parentSchemaPath,
266                         nodeQName, unionType.getQName());
267                 return new UnionType(newSchemaPath, unionType.getTypes());
268             }
269         }
270         return result;
271     }
272
273     private static TypeDefinition<?> copyStringType(SchemaPath schemaPath,
274             QName nodeQName, StringTypeDefinition nodeType) {
275         List<QName> path = schemaPath.getPath();
276         List<QName> newPath = new ArrayList<QName>(path);
277         newPath.add(nodeQName);
278         newPath.add(nodeType.getQName());
279         SchemaPath newSchemaPath = new SchemaPath(newPath,
280                 schemaPath.isAbsolute());
281
282         String newDefault = nodeType.getDefaultValue().toString();
283         String newUnits = nodeType.getUnits();
284         List<LengthConstraint> lengths = nodeType.getLengthStatements();
285         List<PatternConstraint> patterns = nodeType.getPatterns();
286
287         return new StringType(newSchemaPath, newDefault, lengths, patterns,
288                 newUnits);
289     }
290
291     private static TypeDefinition<?> copyIntType(SchemaPath schemaPath,
292             QName nodeQName, IntegerTypeDefinition type) {
293         QName typeQName = type.getQName();
294         SchemaPath newSchemaPath = createNewSchemaPath(schemaPath, nodeQName,
295                 typeQName);
296
297         String localName = typeQName.getLocalName();
298         List<RangeConstraint> ranges = type.getRangeStatements();
299         String units = type.getUnits();
300
301         if ("int8".equals(localName)) {
302             Byte defaultValue = (Byte) type.getDefaultValue();
303             return new Int8(newSchemaPath, ranges, units, defaultValue);
304         } else if ("int16".equals(localName)) {
305             Short defaultValue = (Short) type.getDefaultValue();
306             return new Int16(newSchemaPath, ranges, units, defaultValue);
307         } else if ("int32".equals(localName)) {
308             Integer defaultValue = (Integer) type.getDefaultValue();
309             return new Int32(newSchemaPath, ranges, units, defaultValue);
310         } else if ("int64".equals(localName)) {
311             Long defaultValue = (Long) type.getDefaultValue();
312             return new Int64(newSchemaPath, ranges, units, defaultValue);
313         } else {
314             return null;
315         }
316     }
317
318     private static TypeDefinition<?> copyUIntType(SchemaPath schemaPath,
319             QName nodeQName, UnsignedIntegerTypeDefinition type) {
320         QName typeQName = type.getQName();
321         SchemaPath newSchemaPath = createNewSchemaPath(schemaPath, nodeQName,
322                 typeQName);
323
324         String localName = typeQName.getLocalName();
325         List<RangeConstraint> ranges = type.getRangeStatements();
326         String units = type.getUnits();
327
328         if ("uint8".equals(localName)) {
329             Byte defaultValue = (Byte) type.getDefaultValue();
330             return new Int8(newSchemaPath, ranges, units, defaultValue);
331         } else if ("uint16".equals(localName)) {
332             Short defaultValue = (Short) type.getDefaultValue();
333             return new Int16(newSchemaPath, ranges, units, defaultValue);
334         } else if ("uint32".equals(localName)) {
335             Integer defaultValue = (Integer) type.getDefaultValue();
336             return new Int32(newSchemaPath, ranges, units, defaultValue);
337         } else if ("uint64".equals(localName)) {
338             Long defaultValue = (Long) type.getDefaultValue();
339             return new Int64(newSchemaPath, ranges, units, defaultValue);
340         } else {
341             return null;
342         }
343     }
344
345     private static SchemaPath createNewSchemaPath(SchemaPath schemaPath,
346             QName currentQName, QName qname) {
347         List<QName> newPath = new ArrayList<QName>(schemaPath.getPath());
348         newPath.add(currentQName);
349         newPath.add(qname);
350         return new SchemaPath(newPath, schemaPath.isAbsolute());
351     }
352
353     public static void refineLeaf(LeafSchemaNodeBuilder leaf,
354             RefineHolder refine, int line) {
355         String defaultStr = refine.getDefaultStr();
356         Boolean mandatory = refine.isMandatory();
357         MustDefinition must = refine.getMust();
358         List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodes();
359
360         if (defaultStr != null && !("".equals(defaultStr))) {
361             leaf.setDefaultStr(defaultStr);
362         }
363         if (mandatory != null) {
364             leaf.getConstraints().setMandatory(mandatory);
365         }
366         if (must != null) {
367             leaf.getConstraints().addMustDefinition(must);
368         }
369         if (unknownNodes != null) {
370             for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
371                 leaf.addUnknownSchemaNode(unknown);
372             }
373         }
374     }
375
376     public static void refineContainer(ContainerSchemaNodeBuilder container,
377             RefineHolder refine, int line) {
378         Boolean presence = refine.isPresence();
379         MustDefinition must = refine.getMust();
380         List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodes();
381
382         if (presence != null) {
383             container.setPresence(presence);
384         }
385         if (must != null) {
386             container.getConstraints().addMustDefinition(must);
387         }
388         if (unknownNodes != null) {
389             for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
390                 container.addUnknownSchemaNode(unknown);
391             }
392         }
393     }
394
395     public static void refineList(ListSchemaNodeBuilder list,
396             RefineHolder refine, int line) {
397         MustDefinition must = refine.getMust();
398         Integer min = refine.getMinElements();
399         Integer max = refine.getMaxElements();
400         List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodes();
401
402         if (must != null) {
403             list.getConstraints().addMustDefinition(must);
404         }
405         if (min != null) {
406             list.getConstraints().setMinElements(min);
407         }
408         if (max != null) {
409             list.getConstraints().setMaxElements(max);
410         }
411         if (unknownNodes != null) {
412             for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
413                 list.addUnknownSchemaNode(unknown);
414             }
415         }
416     }
417
418     public static void refineLeafList(LeafListSchemaNodeBuilder leafList,
419             RefineHolder refine, int line) {
420         MustDefinition must = refine.getMust();
421         Integer min = refine.getMinElements();
422         Integer max = refine.getMaxElements();
423         List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodes();
424
425         if (must != null) {
426             leafList.getConstraints().addMustDefinition(must);
427         }
428         if (min != null) {
429             leafList.getConstraints().setMinElements(min);
430         }
431         if (max != null) {
432             leafList.getConstraints().setMaxElements(max);
433         }
434         if (unknownNodes != null) {
435             for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
436                 leafList.addUnknownSchemaNode(unknown);
437             }
438         }
439     }
440
441     public static void refineChoice(ChoiceBuilder choice, RefineHolder refine,
442             int line) {
443         String defaultStr = refine.getDefaultStr();
444         Boolean mandatory = refine.isMandatory();
445         List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodes();
446
447         if (defaultStr != null) {
448             choice.setDefaultCase(defaultStr);
449         }
450         if (mandatory != null) {
451             choice.getConstraints().setMandatory(mandatory);
452         }
453         if (unknownNodes != null) {
454             for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
455                 choice.addUnknownSchemaNode(unknown);
456             }
457         }
458     }
459
460     public static void refineAnyxml(AnyXmlBuilder anyXml, RefineHolder refine,
461             int line) {
462         Boolean mandatory = refine.isMandatory();
463         MustDefinition must = refine.getMust();
464         List<UnknownSchemaNodeBuilder> unknownNodes = refine.getUnknownNodes();
465
466         if (mandatory != null) {
467             anyXml.getConstraints().setMandatory(mandatory);
468         }
469         if (must != null) {
470             anyXml.getConstraints().addMustDefinition(must);
471         }
472         if (unknownNodes != null) {
473             for (UnknownSchemaNodeBuilder unknown : unknownNodes) {
474                 anyXml.addUnknownSchemaNode(unknown);
475             }
476         }
477     }
478
479     public static void checkRefine(SchemaNodeBuilder node, RefineHolder refine) {
480         String name = node.getQName().getLocalName();
481         int line = refine.getLine();
482
483         String defaultStr = refine.getDefaultStr();
484         Boolean mandatory = refine.isMandatory();
485         Boolean presence = refine.isPresence();
486         MustDefinition must = refine.getMust();
487         Integer min = refine.getMinElements();
488         Integer max = refine.getMaxElements();
489
490         if (node instanceof AnyXmlBuilder) {
491             checkRefineDefault(node, defaultStr, line);
492             checkRefinePresence(node, presence, line);
493             checkRefineMinMax(name, line, min, max);
494         } else if (node instanceof ChoiceBuilder) {
495             checkRefinePresence(node, presence, line);
496             checkRefineMust(node, must, line);
497             checkRefineMinMax(name, line, min, max);
498         } else if (node instanceof ContainerSchemaNodeBuilder) {
499             checkRefineDefault(node, defaultStr, line);
500             checkRefineMandatory(node, mandatory, line);
501             checkRefineMust(node, must, line);
502             checkRefineMinMax(name, line, min, max);
503         } else if (node instanceof LeafSchemaNodeBuilder) {
504             checkRefinePresence(node, presence, line);
505             checkRefineMinMax(name, line, min, max);
506         } else if (node instanceof LeafListSchemaNodeBuilder
507                 || node instanceof ListSchemaNodeBuilder) {
508             checkRefineDefault(node, defaultStr, line);
509             checkRefinePresence(node, presence, line);
510             checkRefineMandatory(node, mandatory, line);
511         } else if (node instanceof GroupingBuilder
512                 || node instanceof TypeDefinitionBuilder
513                 || node instanceof UsesNodeBuilder) {
514             checkRefineDefault(node, defaultStr, line);
515             checkRefinePresence(node, presence, line);
516             checkRefineMandatory(node, mandatory, line);
517             checkRefineMust(node, must, line);
518             checkRefineMinMax(name, line, min, max);
519         }
520     }
521
522     private static void checkRefineDefault(SchemaNodeBuilder node,
523             String defaultStr, int line) {
524         if (defaultStr != null) {
525             throw new YangParseException(line, "Can not refine 'default' for '"
526                     + node.getQName().getLocalName() + "'.");
527         }
528     }
529
530     private static void checkRefineMandatory(SchemaNodeBuilder node,
531             Boolean mandatory, int line) {
532         if (mandatory != null) {
533             throw new YangParseException(line,
534                     "Can not refine 'mandatory' for '"
535                             + node.getQName().getLocalName() + "'.");
536         }
537     }
538
539     private static void checkRefinePresence(SchemaNodeBuilder node,
540             Boolean presence, int line) {
541         if (presence != null) {
542             throw new YangParseException(line,
543                     "Can not refine 'presence' for '"
544                             + node.getQName().getLocalName() + "'.");
545         }
546     }
547
548     private static void checkRefineMust(SchemaNodeBuilder node,
549             MustDefinition must, int line) {
550         if (must != null) {
551             throw new YangParseException(line, "Can not refine 'must' for '"
552                     + node.getQName().getLocalName() + "'.");
553         }
554     }
555
556     private static void checkRefineMinMax(String refineTargetName,
557             int refineLine, Integer min, Integer max) {
558         if (min != null || max != null) {
559             throw new YangParseException(refineLine,
560                     "Can not refine 'min-elements' or 'max-elements' for '"
561                             + refineTargetName + "'.");
562         }
563     }
564
565     /**
566      * Perform refine operation of following parameters:
567      * <ul>
568      * <li>description</li>
569      * <li>reference</li>
570      * <li>config</li>
571      * </ul>
572      *
573      * These parameters may be refined for any node.
574      *
575      * @param node
576      *            node to refine
577      * @param refine
578      *            refine holder containing values to refine
579      * @param line
580      *            current line in yang model
581      */
582     public static void refineDefault(Builder node, RefineHolder refine, int line) {
583         Class<? extends Builder> cls = node.getClass();
584
585         String description = refine.getDescription();
586         if (description != null) {
587             try {
588                 Method method = cls.getDeclaredMethod("setDescription",
589                         String.class);
590                 method.invoke(node, description);
591             } catch (Exception e) {
592                 throw new YangParseException(line,
593                         "Cannot refine description in " + cls.getName(), e);
594             }
595         }
596
597         String reference = refine.getReference();
598         if (reference != null) {
599             try {
600                 Method method = cls.getDeclaredMethod("setReference",
601                         String.class);
602                 method.invoke(node, reference);
603             } catch (Exception e) {
604                 throw new YangParseException(line,
605                         "Cannot refine reference in " + cls.getName(), e);
606             }
607         }
608
609         Boolean config = refine.isConfig();
610         if (config != null) {
611             try {
612                 Method method = cls.getDeclaredMethod("setConfiguration",
613                         Boolean.TYPE);
614                 method.invoke(node, config);
615             } catch (Exception e) {
616                 throw new YangParseException(line, "Cannot refine config in "
617                         + cls.getName(), e);
618             }
619         }
620     }
621
622     public static LeafSchemaNodeBuilder copyLeafBuilder(
623             final LeafSchemaNodeBuilder old) {
624         final LeafSchemaNodeBuilder copy = new LeafSchemaNodeBuilder(
625                 old.getQName(), old.getLine());
626         final TypeDefinition<?> type = old.getType();
627
628         if (type == null) {
629             copy.setTypedef(old.getTypedef());
630         } else {
631             copy.setType(type);
632         }
633         copy.setPath(old.getPath());
634         copyConstraints(old, copy);
635         for (UnknownSchemaNodeBuilder unknown : old.getUnknownNodes()) {
636             copy.addUnknownSchemaNode(unknown);
637         }
638         copy.setDescription(old.getDescription());
639         copy.setReference(old.getReference());
640         copy.setStatus(old.getStatus());
641         copy.setAugmenting(old.isAugmenting());
642         copy.setConfiguration(old.isConfiguration());
643         copy.setDefaultStr(old.getDefaultStr());
644         copy.setUnits(old.getUnits());
645         return copy;
646     }
647
648     public static ContainerSchemaNodeBuilder copyContainerBuilder(
649             final ContainerSchemaNodeBuilder old) {
650         final ContainerSchemaNodeBuilder copy = new ContainerSchemaNodeBuilder(
651                 old.getQName(), old.getLine());
652         copy.setPath(old.getPath());
653         copyConstraints(old, copy);
654         for (UnknownSchemaNodeBuilder unknown : old.getUnknownNodes()) {
655             copy.addUnknownSchemaNode(unknown);
656         }
657         for (DataSchemaNodeBuilder child : old.getChildNodes()) {
658             copy.addChildNode(child);
659         }
660         for (GroupingBuilder grouping : old.getGroupings()) {
661             copy.addGrouping(grouping);
662         }
663         for (TypeDefinitionBuilder typedef : old.getTypeDefinitions()) {
664             copy.addTypedef(typedef);
665         }
666         for (AugmentationSchemaBuilder augment : old.getAugmentations()) {
667             copy.addAugmentation(augment);
668         }
669         for (UsesNodeBuilder use : old.getUsesNodes()) {
670             copy.addUsesNode(use);
671         }
672         copy.setDescription(old.getDescription());
673         copy.setReference(old.getReference());
674         copy.setStatus(old.getStatus());
675         copy.setAugmenting(old.isAugmenting());
676         copy.setConfiguration(old.isConfiguration());
677         copy.setPresence(old.isPresence());
678         return copy;
679     }
680
681     public static ListSchemaNodeBuilder copyListBuilder(
682             final ListSchemaNodeBuilder old) {
683         final ListSchemaNodeBuilder copy = new ListSchemaNodeBuilder(
684                 old.getQName(), old.getLine());
685         copy.setPath(old.getPath());
686         copyConstraints(old, copy);
687         for (UnknownSchemaNodeBuilder unknown : old.getUnknownNodes()) {
688             copy.addUnknownSchemaNode(unknown);
689         }
690         for (DataSchemaNodeBuilder child : old.getChildNodes()) {
691             copy.addChildNode(child);
692         }
693         for (GroupingBuilder grouping : old.getGroupings()) {
694             copy.addGrouping(grouping);
695         }
696         for (TypeDefinitionBuilder typedef : old.getTypeDefinitions()) {
697             copy.addTypedef(typedef);
698         }
699         for (AugmentationSchemaBuilder augment : old.getAugmentations()) {
700             copy.addAugmentation(augment);
701         }
702         for (UsesNodeBuilder use : old.getUsesNodes()) {
703             copy.addUsesNode(use);
704         }
705         copy.setDescription(old.getDescription());
706         copy.setReference(old.getReference());
707         copy.setStatus(old.getStatus());
708         copy.setAugmenting(old.isAugmenting());
709         copy.setConfiguration(old.isConfiguration());
710         copy.setUserOrdered(old.isUserOrdered());
711         return copy;
712     }
713
714     public static LeafListSchemaNodeBuilder copyLeafListBuilder(
715             final LeafListSchemaNodeBuilder old) {
716         final LeafListSchemaNodeBuilder copy = new LeafListSchemaNodeBuilder(
717                 old.getQName(), old.getLine());
718         copy.setPath(old.getPath());
719         copyConstraints(old, copy);
720         final TypeDefinition<?> type = old.getType();
721         if (type == null) {
722             copy.setTypedef(old.getTypedef());
723         } else {
724             copy.setType(type);
725         }
726         for (UnknownSchemaNodeBuilder unknown : old.getUnknownNodes()) {
727             copy.addUnknownSchemaNode(unknown);
728         }
729         copy.setDescription(old.getDescription());
730         copy.setReference(old.getReference());
731         copy.setStatus(old.getStatus());
732         copy.setAugmenting(old.isAugmenting());
733         copy.setConfiguration(old.isConfiguration());
734         copy.setUserOrdered(old.isUserOrdered());
735         return copy;
736     }
737
738     public static ChoiceBuilder copyChoiceBuilder(final ChoiceBuilder old) {
739         final ChoiceBuilder copy = new ChoiceBuilder(old.getQName(),
740                 old.getLine());
741         copy.setPath(old.getPath());
742         copyConstraints(old, copy);
743         for (ChoiceCaseBuilder caseBuilder : old.getCases()) {
744             copy.addChildNode(caseBuilder);
745         }
746         for (UnknownSchemaNodeBuilder unknown : old.getUnknownNodes()) {
747             copy.addUnknownSchemaNode(unknown);
748         }
749         copy.setDefaultCase(old.getDefaultCase());
750         copy.setDescription(old.getDescription());
751         copy.setReference(old.getReference());
752         copy.setStatus(old.getStatus());
753         copy.setAugmenting(old.isAugmenting());
754         copy.setConfiguration(old.isConfiguration());
755         return copy;
756     }
757
758     public static AnyXmlBuilder copyAnyXmlBuilder(final AnyXmlBuilder old) {
759         final AnyXmlBuilder copy = new AnyXmlBuilder(old.getQName(),
760                 old.getLine());
761         copy.setPath(old.getPath());
762         copyConstraints(old, copy);
763         for (UnknownSchemaNodeBuilder unknown : old.getUnknownNodes()) {
764             copy.addUnknownSchemaNode(unknown);
765         }
766         copy.setDescription(old.getDescription());
767         copy.setReference(old.getReference());
768         copy.setStatus(old.getStatus());
769         copy.setConfiguration(old.isConfiguration());
770         return copy;
771     }
772
773     public static GroupingBuilder copyGroupingBuilder(final GroupingBuilder old) {
774         final GroupingBuilder copy = new GroupingBuilderImpl(old.getQName(),
775                 old.getLine());
776         copy.setPath(old.getPath());
777         for (DataSchemaNodeBuilder child : old.getChildNodes()) {
778             copy.addChildNode(child);
779         }
780         for (GroupingBuilder grouping : old.getGroupings()) {
781             copy.addGrouping(grouping);
782         }
783         for (TypeDefinitionBuilder typedef : old.getTypeDefinitions()) {
784             copy.addTypedef(typedef);
785         }
786         for (UsesNodeBuilder use : old.getUses()) {
787             copy.addUsesNode(use);
788         }
789         for (UnknownSchemaNodeBuilder unknown : old.getUnknownNodes()) {
790             copy.addUnknownSchemaNode(unknown);
791         }
792         copy.setDescription(old.getDescription());
793         copy.setReference(old.getReference());
794         copy.setStatus(old.getStatus());
795         return copy;
796     }
797
798     public static TypeDefinitionBuilderImpl copyTypedefBuilder(
799             TypeDefinitionBuilderImpl old) {
800         final TypeDefinitionBuilderImpl copy = new TypeDefinitionBuilderImpl(
801                 old.getQName(), old.getLine());
802         copy.setPath(old.getPath());
803         copy.setDefaultValue(old.getDefaultValue());
804         copy.setUnits(old.getUnits());
805         copy.setDescription(old.getDescription());
806         copy.setReference(old.getReference());
807         copy.setStatus(old.getStatus());
808
809         copy.setRanges(old.getRanges());
810         copy.setLengths(old.getLengths());
811         copy.setPatterns(old.getPatterns());
812         copy.setFractionDigits(old.getFractionDigits());
813
814         TypeDefinition<?> type = old.getType();
815         if (type == null) {
816             copy.setTypedef(old.getTypedef());
817         } else {
818             copy.setType(old.getType());
819         }
820         copy.setUnits(old.getUnits());
821         for (UnknownSchemaNodeBuilder unknown : old.getUnknownNodes()) {
822             copy.addUnknownSchemaNode(unknown);
823         }
824         return copy;
825     }
826
827     public static UsesNodeBuilder copyUsesNodeBuilder(UsesNodeBuilder old) {
828         final UsesNodeBuilder copy = new UsesNodeBuilderImpl(
829                 old.getGroupingPathString(), old.getLine());
830         for (AugmentationSchemaBuilder augment : old.getAugmentations()) {
831             copy.addAugment(augment);
832         }
833         copy.setAugmenting(old.isAugmenting());
834         for (SchemaNodeBuilder refineNode : old.getRefineNodes()) {
835             copy.addRefineNode(refineNode);
836         }
837         return copy;
838     }
839
840     private static void copyConstraints(final DataSchemaNodeBuilder oldBuilder,
841             final DataSchemaNodeBuilder newBuilder) {
842         final ConstraintsBuilder oldConstraints = oldBuilder.getConstraints();
843         final ConstraintsBuilder newConstraints = newBuilder.getConstraints();
844         newConstraints.addWhenCondition(oldConstraints.getWhenCondition());
845         for (MustDefinition must : oldConstraints.getMustDefinitions()) {
846             newConstraints.addMustDefinition(must);
847         }
848         newConstraints.setMandatory(oldConstraints.isMandatory());
849         newConstraints.setMinElements(oldConstraints.getMinElements());
850         newConstraints.setMaxElements(oldConstraints.getMaxElements());
851     }
852
853 }