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;
12 import java.util.Date;
14 import java.util.NavigableMap;
16 import org.opendaylight.yangtools.yang.common.QName;
17 import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
18 import org.opendaylight.yangtools.yang.model.api.type.BinaryTypeDefinition;
19 import org.opendaylight.yangtools.yang.model.api.type.DecimalTypeDefinition;
20 import org.opendaylight.yangtools.yang.model.api.type.IntegerTypeDefinition;
21 import org.opendaylight.yangtools.yang.model.api.type.StringTypeDefinition;
22 import org.opendaylight.yangtools.yang.model.api.type.UnsignedIntegerTypeDefinition;
23 import org.opendaylight.yangtools.yang.model.util.ExtendedType;
24 import org.opendaylight.yangtools.yang.parser.builder.api.Builder;
25 import org.opendaylight.yangtools.yang.parser.builder.api.DataNodeContainerBuilder;
26 import org.opendaylight.yangtools.yang.parser.builder.api.TypeAwareBuilder;
27 import org.opendaylight.yangtools.yang.parser.builder.api.TypeDefinitionBuilder;
28 import org.opendaylight.yangtools.yang.parser.util.TypeConstraints;
29 import org.opendaylight.yangtools.yang.parser.util.YangParseException;
32 * Utility class which contains helper methods for dealing with type operations.
34 * @deprecated Pre-Beryllium implementation, scheduled for removal.
37 public final class TypeUtils {
43 * Resolve unknown type of node. It is assumed that type of node is either
44 * UnknownType or ExtendedType with UnknownType as base type.
46 * @param nodeToResolve
47 * node with type to resolve
53 public static void resolveType(final TypeAwareBuilder nodeToResolve,
54 final Map<URI, NavigableMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
55 QName unknownTypeQName = nodeToResolve.getTypeQName();
56 final ModuleBuilder dependentModuleBuilder = BuilderUtils.findModule(unknownTypeQName, modules);
57 if (dependentModuleBuilder == null) {
58 throw new YangParseException(module.getName(), nodeToResolve.getLine(), "Type not found: "
61 TypeDefinitionBuilder resolvedType = findUnknownTypeDefinition(nodeToResolve, dependentModuleBuilder, modules,
63 nodeToResolve.setTypedef(resolvedType);
67 * Resolve union type which contains one or more unresolved types.
70 * union type builder to resolve
76 public static void resolveTypeUnion(final UnionTypeBuilder union,
77 final Map<URI, NavigableMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
78 // special handling for identityref types under union
79 for (TypeDefinitionBuilder unionType : union.getTypedefs()) {
80 if (unionType instanceof IdentityrefTypeBuilder) {
81 IdentityrefTypeBuilder idref = (IdentityrefTypeBuilder) unionType;
82 IdentitySchemaNodeBuilder identity = findBaseIdentity(module, idref.getBaseString(),
84 if (identity == null) {
85 throw new YangParseException(module.getName(), idref.getLine(), "Failed to find base identity");
87 idref.setBaseIdentity(identity);
90 for (QName unknownTypeQName : union.getBaseTypeQNames()) {
91 final ModuleBuilder dependentModuleBuilder = BuilderUtils.findModule(unknownTypeQName, modules);
92 if (dependentModuleBuilder == null) {
93 throw new YangParseException(module.getName(), union.getLine(), "Type not found: " + unknownTypeQName);
96 final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(union, dependentModuleBuilder,
97 unknownTypeQName.getLocalName(), module.getName(), union.getLine());
98 union.setTypedef(targetTypeBuilder);
103 * Find type definition of type of unresolved node.
105 * @param nodeToResolve
106 * node with unresolved type
107 * @param dependentModuleBuilder
108 * module in which type definition is present
113 * @return TypeDefinitionBuilder of node type
115 private static TypeDefinitionBuilder findUnknownTypeDefinition(final TypeAwareBuilder nodeToResolve,
116 final ModuleBuilder dependentModuleBuilder, final Map<URI, NavigableMap<Date, ModuleBuilder>> modules,
117 final ModuleBuilder module) {
118 final int line = nodeToResolve.getLine();
119 final QName unknownTypeQName = nodeToResolve.getTypeQName();
120 final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(nodeToResolve,
121 dependentModuleBuilder, unknownTypeQName.getLocalName(), module.getName(), line);
123 // validate constraints
124 final TypeConstraints constraints = findConstraintsFromTypeBuilder(nodeToResolve,
125 new TypeConstraints(module.getName(), nodeToResolve.getLine()), modules, module);
126 constraints.validateConstraints();
128 return targetTypeBuilder;
132 * Search types for type with given name.
138 * @return type with given name if present in collection, null otherwise
140 private static TypeDefinitionBuilder findTypedefBuilderByName(final Set<TypeDefinitionBuilder> types, final String name) {
141 for (TypeDefinitionBuilder td : types) {
142 if (td.getQName().getLocalName().equals(name)) {
150 * Pull restriction from type and add them to constraints.
153 * type from which constraints will be read
155 * constraints object to which constraints will be added
157 private static TypeConstraints mergeConstraints(final TypeDefinition<?> type, final TypeConstraints constraints) {
158 if (type instanceof DecimalTypeDefinition) {
159 constraints.addRanges(((DecimalTypeDefinition) type).getRangeConstraints());
160 constraints.addFractionDigits(((DecimalTypeDefinition) type).getFractionDigits());
161 } else if (type instanceof IntegerTypeDefinition) {
162 constraints.addRanges(((IntegerTypeDefinition) type).getRangeConstraints());
163 } else if (type instanceof UnsignedIntegerTypeDefinition) {
164 constraints.addRanges(((UnsignedIntegerTypeDefinition) type).getRangeConstraints());
165 } else if (type instanceof StringTypeDefinition) {
166 constraints.addPatterns(((StringTypeDefinition) type).getPatternConstraints());
167 constraints.addLengths(((StringTypeDefinition) type).getLengthConstraints());
168 } else if (type instanceof BinaryTypeDefinition) {
169 constraints.addLengths(((BinaryTypeDefinition) type).getLengthConstraints());
170 } else if (type instanceof ExtendedType) {
171 constraints.addFractionDigits(((ExtendedType) type).getFractionDigits());
172 constraints.addLengths(((ExtendedType) type).getLengthConstraints());
173 constraints.addPatterns(((ExtendedType) type).getPatternConstraints());
174 constraints.addRanges(((ExtendedType) type).getRangeConstraints());
179 private static TypeConstraints findConstraintsFromTypeBuilder(final TypeAwareBuilder nodeToResolve,
180 final TypeConstraints constraints, final Map<URI, NavigableMap<Date, ModuleBuilder>> modules,
181 final ModuleBuilder builder) {
183 // union and identityref types cannot be restricted
184 if (nodeToResolve instanceof UnionTypeBuilder || nodeToResolve instanceof IdentityrefTypeBuilder) {
188 if (nodeToResolve instanceof TypeDefinitionBuilder) {
189 TypeDefinitionBuilder typedefToResolve = (TypeDefinitionBuilder) nodeToResolve;
190 constraints.addFractionDigits(typedefToResolve.getFractionDigits());
191 constraints.addLengths(typedefToResolve.getLengths());
192 constraints.addPatterns(typedefToResolve.getPatterns());
193 constraints.addRanges(typedefToResolve.getRanges());
196 TypeDefinition<?> type = nodeToResolve.getType();
198 final QName unknownTypeQName = nodeToResolve.getTypeQName();
199 if (unknownTypeQName == null) {
202 final ModuleBuilder dependentModuleBuilder = BuilderUtils.findModule(unknownTypeQName, modules);
203 final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(nodeToResolve,
204 dependentModuleBuilder, unknownTypeQName.getLocalName(), builder.getName(), 0);
205 return findConstraintsFromTypeBuilder(targetTypeBuilder, constraints, modules, dependentModuleBuilder);
207 if (type instanceof ExtendedType) {
208 mergeConstraints(type, constraints);
209 // it has to be base yang type
210 return mergeConstraints(type, constraints);
212 // it is base yang type
213 return mergeConstraints(type, constraints);
219 * Search for type definition builder by name.
221 * @param nodeToResolve
222 * node which contains unresolved type
223 * @param dependentModule
224 * module which should contains referenced type
226 * name of type definition
227 * @param currentModuleName
228 * name of current module
230 * current line in module
231 * @return typeDefinitionBuilder
233 private static TypeDefinitionBuilder findTypeDefinitionBuilder(final TypeAwareBuilder nodeToResolve,
234 final ModuleBuilder dependentModule, final String typeName, final String currentModuleName, final int line) {
235 Set<TypeDefinitionBuilder> typedefs = dependentModule.getTypeDefinitionBuilders();
236 TypeDefinitionBuilder result = findTypedefBuilderByName(typedefs, typeName);
237 if (result != null) {
241 Builder parent = nodeToResolve.getParent();
242 while (parent != null) {
243 if (parent instanceof DataNodeContainerBuilder) {
244 typedefs = ((DataNodeContainerBuilder) parent).getTypeDefinitionBuilders();
245 } else if (parent instanceof RpcDefinitionBuilder) {
246 typedefs = ((RpcDefinitionBuilder) parent).getTypeDefinitions();
248 result = findTypedefBuilderByName(typedefs, typeName);
249 if (result == null) {
250 parent = parent.getParent();
256 if (result == null) {
257 throw new YangParseException(currentModuleName, line, "Referenced type '" + typeName + "' not found.");