Merge "Fixed bug in uses statement resolving."
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / util / TypeUtils.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.util;
9
10 import static org.opendaylight.yangtools.yang.parser.util.ParserUtils.*;
11
12 import java.util.ArrayList;
13 import java.util.Date;
14 import java.util.List;
15 import java.util.Map;
16 import java.util.Set;
17 import java.util.TreeMap;
18
19 import org.opendaylight.yangtools.yang.common.QName;
20 import org.opendaylight.yangtools.yang.model.api.Module;
21 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
22 import org.opendaylight.yangtools.yang.model.api.SchemaPath;
23 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
24 import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition;
25 import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
26 import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
27 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
28 import org.opendaylight.yangtools.yang.model.api.type.UnionTypeDefinition;
29 import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
30 import org.opendaylight.yangtools.yang.model.util.ExtendedType;
31 import org.opendaylight.yangtools.yang.model.util.Int16;
32 import org.opendaylight.yangtools.yang.model.util.Int32;
33 import org.opendaylight.yangtools.yang.model.util.Int64;
34 import org.opendaylight.yangtools.yang.model.util.Int8;
35 import org.opendaylight.yangtools.yang.model.util.Uint16;
36 import org.opendaylight.yangtools.yang.model.util.Uint32;
37 import org.opendaylight.yangtools.yang.model.util.Uint64;
38 import org.opendaylight.yangtools.yang.model.util.Uint8;
39 import org.opendaylight.yangtools.yang.model.util.UnknownType;
40 import org.opendaylight.yangtools.yang.parser.builder.api.Builder;
41 import org.opendaylight.yangtools.yang.parser.builder.api.DataNodeContainerBuilder;
42 import org.opendaylight.yangtools.yang.parser.builder.api.TypeAwareBuilder;
43 import org.opendaylight.yangtools.yang.parser.builder.api.TypeDefinitionBuilder;
44 import org.opendaylight.yangtools.yang.parser.builder.impl.IdentityrefTypeBuilder;
45 import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleBuilder;
46 import org.opendaylight.yangtools.yang.parser.builder.impl.RpcDefinitionBuilder;
47 import org.opendaylight.yangtools.yang.parser.builder.impl.TypeDefinitionBuilderImpl;
48 import org.opendaylight.yangtools.yang.parser.builder.impl.UnionTypeBuilder;
49
50 /**
51  * Utility class which contains helper methods for dealing with type operations.
52  */
53 public class TypeUtils {
54
55     private TypeUtils() {
56     }
57
58     /**
59      * Resolve unknown type of node. It is assumed that type of node is either
60      * UnknownType or ExtendedType with UnknownType as base type.
61      *
62      * @param nodeToResolve
63      *            node with type to resolve
64      * @param modules
65      *            all loaded modules
66      * @param module
67      *            current module
68      */
69     public static void resolveType(final TypeAwareBuilder nodeToResolve,
70             final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
71         TypeDefinitionBuilder resolvedType = null;
72         final int line = nodeToResolve.getLine();
73         final TypeDefinition<?> nodeToResolveType = nodeToResolve.getType();
74         final QName unknownTypeQName = nodeToResolveType.getBaseType().getQName();
75         final ModuleBuilder dependentModule = findDependentModuleBuilder(modules, module, unknownTypeQName.getPrefix(),
76                 line);
77
78         final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(nodeToResolve, dependentModule,
79                 unknownTypeQName.getLocalName(), module.getName(), line);
80
81         if (nodeToResolveType instanceof ExtendedType) {
82             final ExtendedType extType = (ExtendedType) nodeToResolveType;
83             final TypeDefinitionBuilder newType = extendedTypeWithNewBaseTypeBuilder(targetTypeBuilder, extType,
84                     modules, module, nodeToResolve.getLine());
85             resolvedType = newType;
86         } else {
87             resolvedType = targetTypeBuilder;
88         }
89
90         // validate constraints
91         final TypeConstraints constraints = findConstraintsFromTypeBuilder(nodeToResolve,
92                 new TypeConstraints(module.getName(), nodeToResolve.getLine()), modules, module, null);
93         constraints.validateConstraints();
94
95         nodeToResolve.setTypedef(resolvedType);
96     }
97
98     /**
99      * Resolve unknown type of node. It is assumed that type of node is either
100      * UnknownType or ExtendedType with UnknownType as base type.
101      *
102      * @param nodeToResolve
103      *            node with type to resolve
104      * @param modules
105      *            all loaded modules
106      * @param module
107      *            current module
108      * @param context
109      *            SchemaContext containing already resolved modules
110      */
111     public static void resolveTypeWithContext(final TypeAwareBuilder nodeToResolve,
112             final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module,
113             final SchemaContext context) {
114         TypeDefinitionBuilder resolvedType = null;
115         final int line = nodeToResolve.getLine();
116         final TypeDefinition<?> nodeToResolveType = nodeToResolve.getType();
117         final QName unknownTypeQName = nodeToResolveType.getBaseType().getQName();
118         final ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module,
119                 unknownTypeQName.getPrefix(), line);
120
121         if (dependentModuleBuilder == null) {
122             final Module dependentModule = findModuleFromContext(context, module, unknownTypeQName.getPrefix(), line);
123             final Set<TypeDefinition<?>> types = dependentModule.getTypeDefinitions();
124             final TypeDefinition<?> type = findTypeByName(types, unknownTypeQName.getLocalName());
125
126             if (nodeToResolveType instanceof ExtendedType) {
127                 final ExtendedType extType = (ExtendedType) nodeToResolveType;
128                 final TypeDefinitionBuilder newType = extendedTypeWithNewBaseType(type, extType, module,
129                         nodeToResolve.getLine());
130
131                 nodeToResolve.setTypedef(newType);
132             } else {
133                 if (nodeToResolve instanceof TypeDefinitionBuilder) {
134                     TypeDefinitionBuilder tdb = (TypeDefinitionBuilder) nodeToResolve;
135                     TypeConstraints tc = findConstraintsFromTypeBuilder(nodeToResolve,
136                             new TypeConstraints(module.getName(), nodeToResolve.getLine()), modules, module, context);
137                     tdb.setLengths(tc.getLength());
138                     tdb.setPatterns(tc.getPatterns());
139                     tdb.setRanges(tc.getRange());
140                     tdb.setFractionDigits(tc.getFractionDigits());
141                 }
142                 nodeToResolve.setType(type);
143             }
144
145         } else {
146             final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(nodeToResolve,
147                     dependentModuleBuilder, unknownTypeQName.getLocalName(), module.getName(), line);
148
149             if (nodeToResolveType instanceof ExtendedType) {
150                 final ExtendedType extType = (ExtendedType) nodeToResolveType;
151                 final TypeDefinitionBuilder newType = extendedTypeWithNewBaseTypeBuilder(targetTypeBuilder, extType,
152                         modules, module, nodeToResolve.getLine());
153                 resolvedType = newType;
154             } else {
155                 resolvedType = targetTypeBuilder;
156             }
157
158             // validate constraints
159             final TypeConstraints constraints = findConstraintsFromTypeBuilder(nodeToResolve, new TypeConstraints(
160                     module.getName(), nodeToResolve.getLine()), modules, module, context);
161             constraints.validateConstraints();
162
163             nodeToResolve.setTypedef(resolvedType);
164         }
165     }
166
167     public static void resolveTypeUnion(final UnionTypeBuilder union,
168             final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder builder) {
169
170         final List<TypeDefinition<?>> unionTypes = union.getTypes();
171         final List<TypeDefinition<?>> toRemove = new ArrayList<TypeDefinition<?>>();
172         for (TypeDefinition<?> unionType : unionTypes) {
173             if (unionType instanceof UnknownType) {
174                 final UnknownType ut = (UnknownType) unionType;
175                 final ModuleBuilder dependentModule = findDependentModuleBuilder(modules, builder, ut.getQName()
176                         .getPrefix(), union.getLine());
177                 final TypeDefinitionBuilder resolvedType = findTypeDefinitionBuilder(union, dependentModule, ut
178                         .getQName().getLocalName(), builder.getName(), union.getLine());
179                 union.setTypedef(resolvedType);
180                 toRemove.add(ut);
181             } else if (unionType instanceof ExtendedType) {
182                 final ExtendedType extType = (ExtendedType) unionType;
183                 final TypeDefinition<?> extTypeBase = extType.getBaseType();
184                 if (extTypeBase instanceof UnknownType) {
185                     final UnknownType ut = (UnknownType) extTypeBase;
186                     final ModuleBuilder dependentModule = findDependentModuleBuilder(modules, builder, ut.getQName()
187                             .getPrefix(), union.getLine());
188                     final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(union, dependentModule,
189                             ut.getQName().getLocalName(), builder.getName(), union.getLine());
190
191                     final TypeDefinitionBuilder newType = extendedTypeWithNewBaseTypeBuilder(targetTypeBuilder,
192                             extType, modules, builder, union.getLine());
193
194                     union.setTypedef(newType);
195                     toRemove.add(extType);
196                 }
197             }
198         }
199         unionTypes.removeAll(toRemove);
200     }
201
202     public static void resolveTypeUnionWithContext(final UnionTypeBuilder union,
203             final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder builder,
204             final SchemaContext context) {
205
206         final List<TypeDefinition<?>> unionTypes = union.getTypes();
207         final List<TypeDefinition<?>> toRemove = new ArrayList<TypeDefinition<?>>();
208         for (TypeDefinition<?> unionType : unionTypes) {
209             if (unionType instanceof UnknownType) {
210                 final UnknownType ut = (UnknownType) unionType;
211                 final QName utQName = ut.getQName();
212                 final ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, builder,
213                         utQName.getPrefix(), union.getLine());
214
215                 if (dependentModuleBuilder == null) {
216                     Module dependentModule = findModuleFromContext(context, builder, utQName.getPrefix(),
217                             union.getLine());
218                     Set<TypeDefinition<?>> types = dependentModule.getTypeDefinitions();
219                     TypeDefinition<?> type = findTypeByName(types, utQName.getLocalName());
220                     union.setType(type);
221                     toRemove.add(ut);
222                 } else {
223                     final TypeDefinitionBuilder resolvedType = findTypeDefinitionBuilder(union, dependentModuleBuilder,
224                             utQName.getLocalName(), builder.getName(), union.getLine());
225                     union.setTypedef(resolvedType);
226                     toRemove.add(ut);
227                 }
228
229             } else if (unionType instanceof ExtendedType) {
230                 final ExtendedType extType = (ExtendedType) unionType;
231                 TypeDefinition<?> extTypeBase = extType.getBaseType();
232                 if (extTypeBase instanceof UnknownType) {
233                     final UnknownType ut = (UnknownType) extTypeBase;
234                     final QName utQName = ut.getQName();
235                     final ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, builder,
236                             utQName.getPrefix(), union.getLine());
237
238                     if (dependentModuleBuilder == null) {
239                         final Module dependentModule = findModuleFromContext(context, builder, utQName.getPrefix(),
240                                 union.getLine());
241                         Set<TypeDefinition<?>> types = dependentModule.getTypeDefinitions();
242                         TypeDefinition<?> type = findTypeByName(types, utQName.getLocalName());
243                         final TypeDefinitionBuilder newType = extendedTypeWithNewBaseType(type, extType, builder, 0);
244
245                         union.setTypedef(newType);
246                         toRemove.add(extType);
247                     } else {
248                         final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(union,
249                                 dependentModuleBuilder, utQName.getLocalName(), builder.getName(), union.getLine());
250
251                         final TypeDefinitionBuilder newType = extendedTypeWithNewBaseTypeBuilder(targetTypeBuilder,
252                                 extType, modules, builder, union.getLine());
253
254                         union.setTypedef(newType);
255                         toRemove.add(extType);
256                     }
257                 }
258             }
259         }
260         unionTypes.removeAll(toRemove);
261     }
262
263     /**
264      * Search types for type with given name.
265      *
266      * @param types
267      *            types to search
268      * @param name
269      *            name of type
270      * @return type with given name if present in collection, null otherwise
271      */
272     private static TypeDefinitionBuilder findTypedefBuilderByName(Set<TypeDefinitionBuilder> types, String name) {
273         for (TypeDefinitionBuilder td : types) {
274             if (td.getQName().getLocalName().equals(name)) {
275                 return td;
276             }
277         }
278         return null;
279     }
280
281     /**
282      * Find type by name.
283      *
284      * @param types
285      *            collection of types
286      * @param typeName
287      *            type name
288      * @return type with given name if it is present in collection, null
289      *         otherwise
290      */
291     private static TypeDefinition<?> findTypeByName(Set<TypeDefinition<?>> types, String typeName) {
292         for (TypeDefinition<?> type : types) {
293             if (type.getQName().getLocalName().equals(typeName)) {
294                 return type;
295             }
296         }
297         return null;
298     }
299
300     /**
301      * Pull restriction from type and add them to constraints.
302      *
303      * @param type
304      * @param constraints
305      */
306     private static void mergeConstraints(final TypeDefinition<?> type, final TypeConstraints constraints) {
307         if (type instanceof DecimalTypeDefinition) {
308             constraints.addRanges(((DecimalTypeDefinition) type).getRangeStatements());
309             constraints.addFractionDigits(((DecimalTypeDefinition) type).getFractionDigits());
310         } else if (type instanceof IntegerTypeDefinition) {
311             constraints.addRanges(((IntegerTypeDefinition) type).getRangeStatements());
312         } else if (type instanceof StringTypeDefinition) {
313             constraints.addPatterns(((StringTypeDefinition) type).getPatterns());
314             constraints.addLengths(((StringTypeDefinition) type).getLengthStatements());
315         } else if (type instanceof BinaryTypeDefinition) {
316             constraints.addLengths(((BinaryTypeDefinition) type).getLengthConstraints());
317         }
318     }
319
320     /**
321      * Create new ExtendedType based on given type and with schema path.
322      *
323      * @param newPath
324      *            schema path for new type
325      * @param oldType
326      *            type based
327      * @return
328      */
329     static ExtendedType createNewExtendedType(final ExtendedType oldType, final SchemaPath newPath) {
330         QName qname = oldType.getQName();
331         TypeDefinition<?> newBaseType = ParserUtils.createCorrectTypeDefinition(newPath, oldType.getBaseType());
332         String desc = oldType.getDescription();
333         String ref = oldType.getReference();
334         ExtendedType.Builder builder = new ExtendedType.Builder(qname, newBaseType, desc, ref, newPath);
335         builder.status(oldType.getStatus());
336         builder.lengths(oldType.getLengths());
337         builder.patterns(oldType.getPatterns());
338         builder.ranges(oldType.getRanges());
339         builder.fractionDigits(oldType.getFractionDigits());
340         builder.unknownSchemaNodes(oldType.getUnknownSchemaNodes());
341         return builder.build();
342     }
343
344     static IntegerTypeDefinition createNewIntType(final SchemaPath newSchemaPath,
345             final IntegerTypeDefinition type) {
346         final String localName = type.getQName().getLocalName();
347         if ("int8".equals(localName)) {
348             return new Int8(newSchemaPath);
349         } else if ("int16".equals(localName)) {
350             return new Int16(newSchemaPath);
351         } else if ("int32".equals(localName)) {
352             return new Int32(newSchemaPath);
353         } else if ("int64".equals(localName)) {
354             return new Int64(newSchemaPath);
355         } else {
356             return null;
357         }
358     }
359
360     static UnsignedIntegerTypeDefinition createNewUintType(final SchemaPath newSchemaPath,
361             final UnsignedIntegerTypeDefinition type) {
362         final String localName = type.getQName().getLocalName();
363         if ("uint8".equals(localName)) {
364             return new Uint8(newSchemaPath);
365         } else if ("uint16".equals(localName)) {
366             return new Uint16(newSchemaPath);
367         } else if ("uint32".equals(localName)) {
368             return new Uint32(newSchemaPath);
369         } else if ("uint64".equals(localName)) {
370             return new Uint64(newSchemaPath);
371         } else {
372             return null;
373         }
374     }
375
376     /**
377      * Create new type builder based on old type with new base type.
378      *
379      * @param newBaseType
380      *            new base type builder
381      * @param oldExtendedType
382      *            old type
383      * @param modules
384      *            all loaded modules
385      * @param module
386      *            current module
387      * @param line
388      *            current line in module
389      * @return new type builder based on old type with new base type
390      */
391     private static TypeDefinitionBuilder extendedTypeWithNewBaseTypeBuilder(final TypeDefinitionBuilder newBaseType,
392             final ExtendedType oldExtendedType, final Map<String, TreeMap<Date, ModuleBuilder>> modules,
393             final ModuleBuilder module, final int line) {
394         final TypeConstraints tc = new TypeConstraints(module.getName(), line);
395         tc.addFractionDigits(oldExtendedType.getFractionDigits());
396         tc.addLengths(oldExtendedType.getLengths());
397         tc.addPatterns(oldExtendedType.getPatterns());
398         tc.addRanges(oldExtendedType.getRanges());
399
400         final TypeConstraints constraints = findConstraintsFromTypeBuilder(newBaseType, tc, modules, module, null);
401         final TypeDefinitionBuilderImpl newType = new TypeDefinitionBuilderImpl(module.getModuleName(), line,
402                 oldExtendedType.getQName());
403         newType.setTypedef(newBaseType);
404         newType.setPath(oldExtendedType.getPath());
405         newType.setDescription(oldExtendedType.getDescription());
406         newType.setReference(oldExtendedType.getReference());
407         newType.setStatus(oldExtendedType.getStatus());
408         newType.setLengths(constraints.getLength());
409         newType.setPatterns(constraints.getPatterns());
410         newType.setRanges(constraints.getRange());
411         newType.setFractionDigits(constraints.getFractionDigits());
412         newType.setUnits(oldExtendedType.getUnits());
413         newType.setDefaultValue(oldExtendedType.getDefaultValue());
414         newType.setUnknownNodes(oldExtendedType.getUnknownSchemaNodes());
415         return newType;
416     }
417
418     /**
419      * Create new type builder based on old type with new base type.
420      *
421      * @param newBaseType
422      *            new base type
423      * @param oldExtendedType
424      *            old type
425      * @param modules
426      *            all loaded modules
427      * @param module
428      *            current module
429      * @param line
430      *            current line in module
431      * @return new type builder based on old type with new base type
432      */
433     private static TypeDefinitionBuilder extendedTypeWithNewBaseType(final TypeDefinition<?> newBaseType,
434             final ExtendedType oldExtendedType, final ModuleBuilder module, final int line) {
435         final TypeConstraints tc = new TypeConstraints(module.getName(), line);
436
437         final TypeConstraints constraints = findConstraintsFromTypeDefinition(newBaseType, tc);
438         final TypeDefinitionBuilderImpl newType = new TypeDefinitionBuilderImpl(module.getModuleName(), line,
439                 oldExtendedType.getQName());
440         newType.setType(newBaseType);
441         newType.setPath(oldExtendedType.getPath());
442         newType.setDescription(oldExtendedType.getDescription());
443         newType.setReference(oldExtendedType.getReference());
444         newType.setStatus(oldExtendedType.getStatus());
445         newType.setLengths(constraints.getLength());
446         newType.setPatterns(constraints.getPatterns());
447         newType.setRanges(constraints.getRange());
448         newType.setFractionDigits(constraints.getFractionDigits());
449         newType.setUnits(oldExtendedType.getUnits());
450         newType.setDefaultValue(oldExtendedType.getDefaultValue());
451         newType.setUnknownNodes(oldExtendedType.getUnknownSchemaNodes());
452         return newType;
453     }
454
455     /**
456      * Pull restrictions from type and add them to constraints.
457      *
458      * @param typeToResolve
459      *            type from which constraints will be read
460      * @param constraints
461      *            constraints object to which constraints will be added
462      * @return constraints contstraints object containing constraints from given
463      *         type
464      */
465     private static TypeConstraints findConstraintsFromTypeDefinition(final TypeDefinition<?> typeToResolve,
466             final TypeConstraints constraints) {
467         // union type cannot be restricted
468         if (typeToResolve instanceof UnionTypeDefinition) {
469             return constraints;
470         }
471         if (typeToResolve instanceof ExtendedType) {
472             ExtendedType extType = (ExtendedType) typeToResolve;
473             constraints.addFractionDigits(extType.getFractionDigits());
474             constraints.addLengths(extType.getLengths());
475             constraints.addPatterns(extType.getPatterns());
476             constraints.addRanges(extType.getRanges());
477             return findConstraintsFromTypeDefinition(extType.getBaseType(), constraints);
478         } else {
479             mergeConstraints(typeToResolve, constraints);
480             return constraints;
481         }
482     }
483
484     private static TypeConstraints findConstraintsFromTypeBuilder(final TypeAwareBuilder nodeToResolve,
485             final TypeConstraints constraints, final Map<String, TreeMap<Date, ModuleBuilder>> modules,
486             final ModuleBuilder builder, final SchemaContext context) {
487
488         // union and identityref types cannot be restricted
489         if (nodeToResolve instanceof UnionTypeBuilder || nodeToResolve instanceof IdentityrefTypeBuilder) {
490             return constraints;
491         }
492
493         if (nodeToResolve instanceof TypeDefinitionBuilder) {
494             TypeDefinitionBuilder typedefToResolve = (TypeDefinitionBuilder) nodeToResolve;
495             constraints.addFractionDigits(typedefToResolve.getFractionDigits());
496             constraints.addLengths(typedefToResolve.getLengths());
497             constraints.addPatterns(typedefToResolve.getPatterns());
498             constraints.addRanges(typedefToResolve.getRanges());
499         }
500
501         TypeDefinition<?> type = nodeToResolve.getType();
502         if (type == null) {
503             return findConstraintsFromTypeBuilder(nodeToResolve.getTypedef(), constraints, modules, builder, context);
504         } else {
505             QName qname = type.getQName();
506             if (type instanceof UnknownType) {
507                 ModuleBuilder dependentModuleBuilder = ParserUtils.findDependentModuleBuilder(modules, builder,
508                         qname.getPrefix(), nodeToResolve.getLine());
509                 if (dependentModuleBuilder == null) {
510                     if (context == null) {
511                         throw new YangParseException(builder.getName(), nodeToResolve.getLine(),
512                                 "Failed to resolved type constraints.");
513                     }
514                     Module dm = ParserUtils.findModuleFromContext(context, builder, qname.getPrefix(),
515                             nodeToResolve.getLine());
516                     TypeDefinition<?> t = findTypeByName(dm.getTypeDefinitions(), qname.getLocalName());
517                     if (t instanceof ExtendedType) {
518                         ExtendedType extType = (ExtendedType) t;
519                         constraints.addFractionDigits(extType.getFractionDigits());
520                         constraints.addLengths(extType.getLengths());
521                         constraints.addPatterns(extType.getPatterns());
522                         constraints.addRanges(extType.getRanges());
523                         return constraints;
524                     } else {
525                         mergeConstraints(t, constraints);
526                         return constraints;
527                     }
528                 } else {
529                     TypeDefinitionBuilder tdb = findTypeDefinitionBuilder(nodeToResolve, dependentModuleBuilder,
530                             qname.getLocalName(), builder.getName(), nodeToResolve.getLine());
531                     return findConstraintsFromTypeBuilder(tdb, constraints, modules, dependentModuleBuilder, context);
532                 }
533             } else if (type instanceof ExtendedType) {
534                 ExtendedType extType = (ExtendedType) type;
535                 constraints.addFractionDigits(extType.getFractionDigits());
536                 constraints.addLengths(extType.getLengths());
537                 constraints.addPatterns(extType.getPatterns());
538                 constraints.addRanges(extType.getRanges());
539
540                 TypeDefinition<?> base = extType.getBaseType();
541                 if (base instanceof UnknownType) {
542                     ModuleBuilder dependentModule = ParserUtils.findDependentModuleBuilder(modules, builder, base
543                             .getQName().getPrefix(), nodeToResolve.getLine());
544                     TypeDefinitionBuilder tdb = findTypeDefinitionBuilder(nodeToResolve, dependentModule, base
545                             .getQName().getLocalName(), builder.getName(), nodeToResolve.getLine());
546                     return findConstraintsFromTypeBuilder(tdb, constraints, modules, dependentModule, context);
547                 } else {
548                     // it has to be base yang type
549                     mergeConstraints(type, constraints);
550                     return constraints;
551                 }
552             } else {
553                 // it is base yang type
554                 mergeConstraints(type, constraints);
555                 return constraints;
556             }
557         }
558     }
559
560     /**
561      * Search for type definition builder by name.
562      *
563      * @param dirtyNodeSchemaPath
564      *            schema path of node which contains unresolved type
565      * @param dependentModule
566      *            module which should contains referenced type
567      * @param typeName
568      *            name of type definition
569      * @param currentModuleName
570      *            name of current module
571      * @param line
572      *            current line in module
573      * @return
574      */
575     private static TypeDefinitionBuilder findTypeDefinitionBuilder(final TypeAwareBuilder nodeToResolve,
576             final ModuleBuilder dependentModule, final String typeName, final String currentModuleName, final int line) {
577
578         TypeDefinitionBuilder result = null;
579
580         Set<TypeDefinitionBuilder> typedefs = dependentModule.getTypeDefinitionBuilders();
581         result = findTypedefBuilderByName(typedefs, typeName);
582         if (result != null) {
583             return result;
584         }
585
586         Builder parent = nodeToResolve.getParent();
587         while (parent != null) {
588             if (parent instanceof DataNodeContainerBuilder) {
589                 typedefs = ((DataNodeContainerBuilder) parent).getTypeDefinitionBuilders();
590             } else if (parent instanceof RpcDefinitionBuilder) {
591                 typedefs = ((RpcDefinitionBuilder) parent).getTypeDefinitions();
592             }
593             result = findTypedefBuilderByName(typedefs, typeName);
594             if (result == null) {
595                 parent = parent.getParent();
596             } else {
597                 break;
598             }
599         }
600
601         if (result == null) {
602             throw new YangParseException(currentModuleName, line, "Referenced type '" + typeName + "' not found.");
603         }
604         return result;
605     }
606
607 }