2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.yangtools.yang.parser.builder.impl;
10 import static org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils.findBaseIdentity;
13 import java.util.Date;
16 import java.util.TreeMap;
17 import org.opendaylight.yangtools.yang.common.QName;
18 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
19 import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition;
20 import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
21 import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
22 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
23 import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
24 import org.opendaylight.yangtools.yang.model.util.ExtendedType;
25 import org.opendaylight.yangtools.yang.parser.builder.api.Builder;
26 import org.opendaylight.yangtools.yang.parser.builder.api.DataNodeContainerBuilder;
27 import org.opendaylight.yangtools.yang.parser.builder.api.TypeAwareBuilder;
28 import org.opendaylight.yangtools.yang.parser.builder.api.TypeDefinitionBuilder;
29 import org.opendaylight.yangtools.yang.parser.util.TypeConstraints;
30 import org.opendaylight.yangtools.yang.parser.util.YangParseException;
33 * Utility class which contains helper methods for dealing with type operations.
35 public final class TypeUtils {
41 * Resolve unknown type of node. It is assumed that type of node is either
42 * UnknownType or ExtendedType with UnknownType as base type.
44 * @param nodeToResolve
45 * node with type to resolve
51 public static void resolveType(final TypeAwareBuilder nodeToResolve,
52 final Map<URI, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
53 QName unknownTypeQName = nodeToResolve.getTypeQName();
54 final ModuleBuilder dependentModuleBuilder = BuilderUtils.findModule(unknownTypeQName, modules);
55 if (dependentModuleBuilder == null) {
56 throw new YangParseException(module.getName(), nodeToResolve.getLine(), "Type not found: "
59 TypeDefinitionBuilder resolvedType = findUnknownTypeDefinition(nodeToResolve, dependentModuleBuilder, modules,
61 nodeToResolve.setTypedef(resolvedType);
65 * Resolve union type which contains one or more unresolved types.
68 * union type builder to resolve
74 public static void resolveTypeUnion(final UnionTypeBuilder union,
75 final Map<URI, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
76 // special handling for identityref types under union
77 for (TypeDefinitionBuilder unionType : union.getTypedefs()) {
78 if (unionType instanceof IdentityrefTypeBuilder) {
79 IdentityrefTypeBuilder idref = (IdentityrefTypeBuilder) unionType;
80 IdentitySchemaNodeBuilder identity = findBaseIdentity(module, idref.getBaseString(),
82 if (identity == null) {
83 throw new YangParseException(module.getName(), idref.getLine(), "Failed to find base identity");
85 idref.setBaseIdentity(identity);
88 for (QName unknownTypeQName : union.getBaseTypeQNames()) {
89 final ModuleBuilder dependentModuleBuilder = BuilderUtils.findModule(unknownTypeQName, modules);
90 if (dependentModuleBuilder == null) {
91 throw new YangParseException(module.getName(), union.getLine(), "Type not found: " + unknownTypeQName);
94 final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(union, dependentModuleBuilder,
95 unknownTypeQName.getLocalName(), module.getName(), union.getLine());
96 union.setTypedef(targetTypeBuilder);
101 * Find type definition of type of unresolved node.
103 * @param nodeToResolve
104 * node with unresolved type
105 * @param dependentModuleBuilder
106 * module in which type definition is present
111 * @return TypeDefinitionBuilder of node type
113 private static TypeDefinitionBuilder findUnknownTypeDefinition(final TypeAwareBuilder nodeToResolve,
114 final ModuleBuilder dependentModuleBuilder, final Map<URI, TreeMap<Date, ModuleBuilder>> modules,
115 final ModuleBuilder module) {
116 final int line = nodeToResolve.getLine();
117 final QName unknownTypeQName = nodeToResolve.getTypeQName();
118 final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(nodeToResolve,
119 dependentModuleBuilder, unknownTypeQName.getLocalName(), module.getName(), line);
121 // validate constraints
122 final TypeConstraints constraints = findConstraintsFromTypeBuilder(nodeToResolve,
123 new TypeConstraints(module.getName(), nodeToResolve.getLine()), modules, module);
124 constraints.validateConstraints();
126 return targetTypeBuilder;
130 * Search types for type with given name.
136 * @return type with given name if present in collection, null otherwise
138 private static TypeDefinitionBuilder findTypedefBuilderByName(Set<TypeDefinitionBuilder> types, String name) {
139 for (TypeDefinitionBuilder td : types) {
140 if (td.getQName().getLocalName().equals(name)) {
148 * Pull restriction from type and add them to constraints.
151 * type from which constraints will be read
153 * constraints object to which constraints will be added
155 private static TypeConstraints mergeConstraints(final TypeDefinition<?> type, final TypeConstraints constraints) {
156 if (type instanceof DecimalTypeDefinition) {
157 constraints.addRanges(((DecimalTypeDefinition) type).getRangeConstraints());
158 constraints.addFractionDigits(((DecimalTypeDefinition) type).getFractionDigits());
159 } else if (type instanceof IntegerTypeDefinition) {
160 constraints.addRanges(((IntegerTypeDefinition) type).getRangeConstraints());
161 } else if (type instanceof UnsignedIntegerTypeDefinition) {
162 constraints.addRanges(((UnsignedIntegerTypeDefinition) type).getRangeConstraints());
163 } else if (type instanceof StringTypeDefinition) {
164 constraints.addPatterns(((StringTypeDefinition) type).getPatternConstraints());
165 constraints.addLengths(((StringTypeDefinition) type).getLengthConstraints());
166 } else if (type instanceof BinaryTypeDefinition) {
167 constraints.addLengths(((BinaryTypeDefinition) type).getLengthConstraints());
168 } else if (type instanceof ExtendedType) {
169 constraints.addFractionDigits(((ExtendedType) type).getFractionDigits());
170 constraints.addLengths(((ExtendedType) type).getLengthConstraints());
171 constraints.addPatterns(((ExtendedType) type).getPatternConstraints());
172 constraints.addRanges(((ExtendedType) type).getRangeConstraints());
177 private static TypeConstraints findConstraintsFromTypeBuilder(final TypeAwareBuilder nodeToResolve,
178 final TypeConstraints constraints, final Map<URI, TreeMap<Date, ModuleBuilder>> modules,
179 final ModuleBuilder builder) {
181 // union and identityref types cannot be restricted
182 if (nodeToResolve instanceof UnionTypeBuilder || nodeToResolve instanceof IdentityrefTypeBuilder) {
186 if (nodeToResolve instanceof TypeDefinitionBuilder) {
187 TypeDefinitionBuilder typedefToResolve = (TypeDefinitionBuilder) nodeToResolve;
188 constraints.addFractionDigits(typedefToResolve.getFractionDigits());
189 constraints.addLengths(typedefToResolve.getLengths());
190 constraints.addPatterns(typedefToResolve.getPatterns());
191 constraints.addRanges(typedefToResolve.getRanges());
194 TypeDefinition<?> type = nodeToResolve.getType();
196 final QName unknownTypeQName = nodeToResolve.getTypeQName();
197 if (unknownTypeQName == null) {
200 final ModuleBuilder dependentModuleBuilder = BuilderUtils.findModule(unknownTypeQName, modules);
201 final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(nodeToResolve,
202 dependentModuleBuilder, unknownTypeQName.getLocalName(), builder.getName(), 0);
203 return findConstraintsFromTypeBuilder(targetTypeBuilder, constraints, modules, dependentModuleBuilder);
205 if (type instanceof ExtendedType) {
206 mergeConstraints(type, constraints);
207 // it has to be base yang type
208 return mergeConstraints(type, constraints);
210 // it is base yang type
211 return mergeConstraints(type, constraints);
217 * Search for type definition builder by name.
219 * @param nodeToResolve
220 * node which contains unresolved type
221 * @param dependentModule
222 * module which should contains referenced type
224 * name of type definition
225 * @param currentModuleName
226 * name of current module
228 * current line in module
229 * @return typeDefinitionBuilder
231 private static TypeDefinitionBuilder findTypeDefinitionBuilder(final TypeAwareBuilder nodeToResolve,
232 final ModuleBuilder dependentModule, final String typeName, final String currentModuleName, final int line) {
233 Set<TypeDefinitionBuilder> typedefs = dependentModule.getTypeDefinitionBuilders();
234 TypeDefinitionBuilder result = findTypedefBuilderByName(typedefs, typeName);
235 if (result != null) {
239 Builder parent = nodeToResolve.getParent();
240 while (parent != null) {
241 if (parent instanceof DataNodeContainerBuilder) {
242 typedefs = ((DataNodeContainerBuilder) parent).getTypeDefinitionBuilders();
243 } else if (parent instanceof RpcDefinitionBuilder) {
244 typedefs = ((RpcDefinitionBuilder) parent).getTypeDefinitions();
246 result = findTypedefBuilderByName(typedefs, typeName);
247 if (result == null) {
248 parent = parent.getParent();
254 if (result == null) {
255 throw new YangParseException(currentModuleName, line, "Referenced type '" + typeName + "' not found.");