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