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.controller.yang.parser.impl;
10 import static org.opendaylight.controller.yang.parser.util.ParserUtils.*;
13 import java.io.FileInputStream;
14 import java.io.FileNotFoundException;
15 import java.io.IOException;
16 import java.io.InputStream;
17 import java.util.ArrayList;
18 import java.util.Collections;
19 import java.util.Date;
20 import java.util.HashMap;
21 import java.util.HashSet;
22 import java.util.Iterator;
23 import java.util.LinkedHashMap;
24 import java.util.LinkedHashSet;
25 import java.util.List;
27 import java.util.Map.Entry;
28 import java.util.NoSuchElementException;
30 import java.util.TreeMap;
32 import org.antlr.v4.runtime.ANTLRInputStream;
33 import org.antlr.v4.runtime.CommonTokenStream;
34 import org.antlr.v4.runtime.tree.ParseTree;
35 import org.antlr.v4.runtime.tree.ParseTreeWalker;
36 import org.opendaylight.controller.antlrv4.code.gen.YangLexer;
37 import org.opendaylight.controller.antlrv4.code.gen.YangParser;
38 import org.opendaylight.controller.yang.common.QName;
39 import org.opendaylight.controller.yang.model.api.AnyXmlSchemaNode;
40 import org.opendaylight.controller.yang.model.api.ChoiceNode;
41 import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
42 import org.opendaylight.controller.yang.model.api.DataNodeContainer;
43 import org.opendaylight.controller.yang.model.api.DataSchemaNode;
44 import org.opendaylight.controller.yang.model.api.GroupingDefinition;
45 import org.opendaylight.controller.yang.model.api.IdentitySchemaNode;
46 import org.opendaylight.controller.yang.model.api.LeafListSchemaNode;
47 import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
48 import org.opendaylight.controller.yang.model.api.ListSchemaNode;
49 import org.opendaylight.controller.yang.model.api.Module;
50 import org.opendaylight.controller.yang.model.api.SchemaContext;
51 import org.opendaylight.controller.yang.model.api.SchemaNode;
52 import org.opendaylight.controller.yang.model.api.SchemaPath;
53 import org.opendaylight.controller.yang.model.api.TypeDefinition;
54 import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
55 import org.opendaylight.controller.yang.model.api.UsesNode;
56 import org.opendaylight.controller.yang.model.parser.api.YangModelParser;
57 import org.opendaylight.controller.yang.model.util.ExtendedType;
58 import org.opendaylight.controller.yang.model.util.IdentityrefType;
59 import org.opendaylight.controller.yang.model.util.UnknownType;
60 import org.opendaylight.controller.yang.parser.builder.api.AugmentationSchemaBuilder;
61 import org.opendaylight.controller.yang.parser.builder.api.Builder;
62 import org.opendaylight.controller.yang.parser.builder.api.DataNodeContainerBuilder;
63 import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
64 import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
65 import org.opendaylight.controller.yang.parser.builder.api.GroupingMember;
66 import org.opendaylight.controller.yang.parser.builder.api.SchemaNodeBuilder;
67 import org.opendaylight.controller.yang.parser.builder.api.TypeAwareBuilder;
68 import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
69 import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
70 import org.opendaylight.controller.yang.parser.builder.impl.AnyXmlBuilder;
71 import org.opendaylight.controller.yang.parser.builder.impl.ChoiceBuilder;
72 import org.opendaylight.controller.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
73 import org.opendaylight.controller.yang.parser.builder.impl.DeviationBuilder;
74 import org.opendaylight.controller.yang.parser.builder.impl.GroupingBuilderImpl;
75 import org.opendaylight.controller.yang.parser.builder.impl.IdentitySchemaNodeBuilder;
76 import org.opendaylight.controller.yang.parser.builder.impl.IdentityrefTypeBuilder;
77 import org.opendaylight.controller.yang.parser.builder.impl.LeafListSchemaNodeBuilder;
78 import org.opendaylight.controller.yang.parser.builder.impl.LeafSchemaNodeBuilder;
79 import org.opendaylight.controller.yang.parser.builder.impl.ListSchemaNodeBuilder;
80 import org.opendaylight.controller.yang.parser.builder.impl.ModuleBuilder;
81 import org.opendaylight.controller.yang.parser.builder.impl.RpcDefinitionBuilder;
82 import org.opendaylight.controller.yang.parser.builder.impl.TypeDefinitionBuilderImpl;
83 import org.opendaylight.controller.yang.parser.builder.impl.UnionTypeBuilder;
84 import org.opendaylight.controller.yang.parser.builder.impl.UnknownSchemaNodeBuilder;
85 import org.opendaylight.controller.yang.parser.builder.impl.UsesNodeBuilderImpl;
86 import org.opendaylight.controller.yang.parser.builder.impl.UsesNodeBuilderImpl.UsesNodeImpl;
87 import org.opendaylight.controller.yang.parser.util.ModuleDependencySort;
88 import org.opendaylight.controller.yang.parser.util.RefineHolder;
89 import org.opendaylight.controller.yang.parser.util.RefineUtils;
90 import org.opendaylight.controller.yang.parser.util.TypeConstraints;
91 import org.opendaylight.controller.yang.parser.util.YangParseException;
92 import org.opendaylight.controller.yang.validator.YangModelBasicValidator;
93 import org.slf4j.Logger;
94 import org.slf4j.LoggerFactory;
96 import com.google.common.collect.Lists;
97 import com.google.common.collect.Maps;
98 import com.google.common.collect.Sets;
100 public final class YangParserImpl implements YangModelParser {
101 private static final Logger logger = LoggerFactory.getLogger(YangParserImpl.class);
104 public Set<Module> parseYangModels(final List<File> yangFiles) {
105 return Sets.newLinkedHashSet(parseYangModelsMapped(yangFiles).values());
109 public Set<Module> parseYangModels(final List<File> yangFiles, final SchemaContext context) {
110 if (yangFiles != null) {
111 final Map<InputStream, File> inputStreams = Maps.newHashMap();
113 for (final File yangFile : yangFiles) {
115 inputStreams.put(new FileInputStream(yangFile), yangFile);
116 } catch (FileNotFoundException e) {
117 logger.warn("Exception while reading yang file: " + yangFile.getName(), e);
121 Map<ModuleBuilder, InputStream> builderToStreamMap = Maps.newHashMap();
123 final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuilders(
124 Lists.newArrayList(inputStreams.keySet()), builderToStreamMap);
126 for (InputStream is : inputStreams.keySet()) {
129 } catch (IOException e) {
130 logger.debug("Failed to close stream.");
134 return new LinkedHashSet<Module>(buildWithContext(modules, context).values());
136 return Collections.emptySet();
140 public Set<Module> parseYangModelsFromStreams(final List<InputStream> yangModelStreams) {
141 return Sets.newHashSet(parseYangModelsFromStreamsMapped(yangModelStreams).values());
145 public Set<Module> parseYangModelsFromStreams(final List<InputStream> yangModelStreams, SchemaContext context) {
146 if (yangModelStreams != null) {
147 Map<ModuleBuilder, InputStream> builderToStreamMap = Maps.newHashMap();
148 final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuildersWithContext(
149 yangModelStreams, builderToStreamMap, context);
150 return new LinkedHashSet<Module>(buildWithContext(modules, context).values());
152 return Collections.emptySet();
156 public Map<File, Module> parseYangModelsMapped(List<File> yangFiles) {
157 if (yangFiles != null) {
158 final Map<InputStream, File> inputStreams = Maps.newHashMap();
160 for (final File yangFile : yangFiles) {
162 inputStreams.put(new FileInputStream(yangFile), yangFile);
163 } catch (FileNotFoundException e) {
164 logger.warn("Exception while reading yang file: " + yangFile.getName(), e);
168 Map<ModuleBuilder, InputStream> builderToStreamMap = Maps.newHashMap();
169 final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuilders(
170 Lists.newArrayList(inputStreams.keySet()), builderToStreamMap);
172 for (InputStream is : inputStreams.keySet()) {
175 } catch (IOException e) {
176 logger.debug("Failed to close stream.");
180 Map<File, Module> retVal = Maps.newLinkedHashMap();
181 Map<ModuleBuilder, Module> builderToModuleMap = build(modules);
183 for (Entry<ModuleBuilder, Module> builderToModule : builderToModuleMap.entrySet()) {
184 retVal.put(inputStreams.get(builderToStreamMap.get(builderToModule.getKey())),
185 builderToModule.getValue());
190 return Collections.emptyMap();
194 public Map<InputStream, Module> parseYangModelsFromStreamsMapped(final List<InputStream> yangModelStreams) {
195 Map<ModuleBuilder, InputStream> builderToStreamMap = Maps.newHashMap();
197 final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuilders(yangModelStreams,
199 Map<InputStream, Module> retVal = Maps.newLinkedHashMap();
200 Map<ModuleBuilder, Module> builderToModuleMap = build(modules);
202 for (Entry<ModuleBuilder, Module> builderToModule : builderToModuleMap.entrySet()) {
203 retVal.put(builderToStreamMap.get(builderToModule.getKey()), builderToModule.getValue());
209 public SchemaContext resolveSchemaContext(final Set<Module> modules) {
210 return new SchemaContextImpl(modules);
213 private ModuleBuilder[] parseModuleBuilders(List<InputStream> inputStreams,
214 Map<ModuleBuilder, InputStream> streamToBuilderMap) {
216 final ParseTreeWalker walker = new ParseTreeWalker();
217 final List<ParseTree> trees = parseStreams(inputStreams);
218 final ModuleBuilder[] builders = new ModuleBuilder[trees.size()];
221 new YangModelBasicValidator(walker).validate(trees);
223 YangParserListenerImpl yangModelParser = null;
224 for (int i = 0; i < trees.size(); i++) {
225 yangModelParser = new YangParserListenerImpl();
226 walker.walk(yangModelParser, trees.get(i));
227 ModuleBuilder moduleBuilder = yangModelParser.getModuleBuilder();
229 // We expect the order of trees and streams has to be the same
230 streamToBuilderMap.put(moduleBuilder, inputStreams.get(i));
231 builders[i] = moduleBuilder;
236 private Map<String, TreeMap<Date, ModuleBuilder>> resolveModuleBuilders(final List<InputStream> yangFileStreams,
237 Map<ModuleBuilder, InputStream> streamToBuilderMap) {
238 return resolveModuleBuildersWithContext(yangFileStreams, streamToBuilderMap, null);
241 private Map<String, TreeMap<Date, ModuleBuilder>> resolveModuleBuildersWithContext(
242 final List<InputStream> yangFileStreams, final Map<ModuleBuilder, InputStream> streamToBuilderMap,
243 final SchemaContext context) {
244 final ModuleBuilder[] builders = parseModuleBuilders(yangFileStreams, streamToBuilderMap);
246 // Linked Hash Map MUST be used because Linked Hash Map preserves ORDER
247 // of items stored in map.
248 final LinkedHashMap<String, TreeMap<Date, ModuleBuilder>> modules = new LinkedHashMap<String, TreeMap<Date, ModuleBuilder>>();
250 // module dependency graph sorted
251 List<ModuleBuilder> sorted = null;
252 if (context == null) {
253 sorted = ModuleDependencySort.sort(builders);
255 sorted = ModuleDependencySort.sortWithContext(context, builders);
258 for (final ModuleBuilder builder : sorted) {
259 if (builder == null) {
262 final String builderName = builder.getName();
263 Date builderRevision = builder.getRevision();
264 if (builderRevision == null) {
265 builderRevision = new Date(0L);
267 TreeMap<Date, ModuleBuilder> builderByRevision = modules.get(builderName);
268 if (builderByRevision == null) {
269 builderByRevision = new TreeMap<Date, ModuleBuilder>();
271 builderByRevision.put(builderRevision, builder);
272 modules.put(builderName, builderByRevision);
277 private List<ParseTree> parseStreams(final List<InputStream> yangStreams) {
278 final List<ParseTree> trees = new ArrayList<ParseTree>();
279 for (InputStream yangStream : yangStreams) {
280 trees.add(parseStream(yangStream));
285 private ParseTree parseStream(final InputStream yangStream) {
286 ParseTree result = null;
288 final ANTLRInputStream input = new ANTLRInputStream(yangStream);
289 final YangLexer lexer = new YangLexer(input);
290 final CommonTokenStream tokens = new CommonTokenStream(lexer);
291 final YangParser parser = new YangParser(tokens);
292 parser.removeErrorListeners();
293 parser.addErrorListener(new YangErrorListener());
295 result = parser.yang();
296 } catch (IOException e) {
297 logger.warn("Exception while reading yang file: " + yangStream, e);
302 private Map<ModuleBuilder, Module> build(final Map<String, TreeMap<Date, ModuleBuilder>> modules) {
303 // fix unresolved nodes
304 for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
305 for (Map.Entry<Date, ModuleBuilder> childEntry : entry.getValue().entrySet()) {
306 final ModuleBuilder moduleBuilder = childEntry.getValue();
307 fixUnresolvedNodes(modules, moduleBuilder);
310 resolveAugments(modules);
311 resolveDeviations(modules);
314 // LinkedHashMap MUST be used otherwise the values will not maintain
316 // http://docs.oracle.com/javase/6/docs/api/java/util/LinkedHashMap.html
317 final Map<ModuleBuilder, Module> result = new LinkedHashMap<ModuleBuilder, Module>();
318 for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
319 final Map<Date, Module> modulesByRevision = new HashMap<Date, Module>();
320 for (Map.Entry<Date, ModuleBuilder> childEntry : entry.getValue().entrySet()) {
321 final ModuleBuilder moduleBuilder = childEntry.getValue();
322 final Module module = moduleBuilder.build();
323 modulesByRevision.put(childEntry.getKey(), module);
324 result.put(moduleBuilder, module);
330 private Map<ModuleBuilder, Module> buildWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
331 SchemaContext context) {
332 // fix unresolved nodes
333 for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
334 for (Map.Entry<Date, ModuleBuilder> childEntry : entry.getValue().entrySet()) {
335 final ModuleBuilder moduleBuilder = childEntry.getValue();
336 fixUnresolvedNodesWithContext(modules, moduleBuilder, context);
339 resolveAugmentsWithContext(modules, context);
340 resolveDeviationsWithContext(modules, context);
343 // LinkedHashMap MUST be used otherwise the values will not maintain
345 // http://docs.oracle.com/javase/6/docs/api/java/util/LinkedHashMap.html
346 final Map<ModuleBuilder, Module> result = new LinkedHashMap<ModuleBuilder, Module>();
347 for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
348 final Map<Date, Module> modulesByRevision = new HashMap<Date, Module>();
349 for (Map.Entry<Date, ModuleBuilder> childEntry : entry.getValue().entrySet()) {
350 final ModuleBuilder moduleBuilder = childEntry.getValue();
351 final Module module = moduleBuilder.build();
352 modulesByRevision.put(childEntry.getKey(), module);
353 result.put(moduleBuilder, module);
359 private void fixUnresolvedNodes(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder builder) {
360 resolveDirtyNodes(modules, builder);
361 resolveIdentities(modules, builder);
362 resolveUsesRefine(modules, builder);
363 resolveUnknownNodes(modules, builder);
366 private void fixUnresolvedNodesWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
367 final ModuleBuilder builder, final SchemaContext context) {
368 resolveDirtyNodesWithContext(modules, builder, context);
369 resolveIdentitiesWithContext(modules, builder, context);
370 resolveUsesRefineWithContext(modules, builder, context);
371 resolveUnknownNodesWithContext(modules, builder, context);
375 * Search for dirty nodes (node which contains UnknownType) and resolve
379 * all available modules
383 private void resolveDirtyNodes(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
384 final Map<List<String>, TypeAwareBuilder> dirtyNodes = module.getDirtyNodes();
385 if (!dirtyNodes.isEmpty()) {
386 for (Map.Entry<List<String>, TypeAwareBuilder> entry : dirtyNodes.entrySet()) {
387 final TypeAwareBuilder nodeToResolve = entry.getValue();
389 if (nodeToResolve instanceof UnionTypeBuilder) {
390 // special handling for union types
391 resolveTypeUnion((UnionTypeBuilder) nodeToResolve, modules, module);
392 } else if (nodeToResolve.getTypedef() instanceof IdentityrefTypeBuilder) {
393 // special handling for identityref types
394 IdentityrefTypeBuilder idref = (IdentityrefTypeBuilder) nodeToResolve.getTypedef();
395 nodeToResolve.setType(new IdentityrefType(findFullQName(modules, module, idref), idref.getPath()));
397 resolveType(nodeToResolve, modules, module);
403 private void resolveDirtyNodesWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
404 final ModuleBuilder module, SchemaContext context) {
405 final Map<List<String>, TypeAwareBuilder> dirtyNodes = module.getDirtyNodes();
406 if (!dirtyNodes.isEmpty()) {
407 for (Map.Entry<List<String>, TypeAwareBuilder> entry : dirtyNodes.entrySet()) {
408 final TypeAwareBuilder nodeToResolve = entry.getValue();
410 if (nodeToResolve instanceof UnionTypeBuilder) {
411 // special handling for union types
412 resolveTypeUnionWithContext((UnionTypeBuilder) nodeToResolve, modules, module, context);
413 } else if (nodeToResolve.getTypedef() instanceof IdentityrefTypeBuilder) {
414 // special handling for identityref types
415 IdentityrefTypeBuilder idref = (IdentityrefTypeBuilder) nodeToResolve.getTypedef();
416 nodeToResolve.setType(new IdentityrefType(findFullQName(modules, module, idref), idref.getPath()));
418 resolveTypeWithContext(nodeToResolve, modules, module, context);
425 * Resolve unknown type of node. It is assumed that type of node is either
426 * UnknownType or ExtendedType with UnknownType as base type.
428 * @param nodeToResolve
429 * node with type to resolve
435 private void resolveType(final TypeAwareBuilder nodeToResolve,
436 final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
437 TypeDefinitionBuilder resolvedType = null;
438 final int line = nodeToResolve.getLine();
439 final TypeDefinition<?> nodeToResolveType = nodeToResolve.getType();
440 final QName unknownTypeQName = nodeToResolveType.getBaseType().getQName();
441 final ModuleBuilder dependentModule = findDependentModuleBuilder(modules, module, unknownTypeQName.getPrefix(),
444 final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(nodeToResolve, dependentModule,
445 unknownTypeQName.getLocalName(), module.getName(), line);
447 if (nodeToResolveType instanceof ExtendedType) {
448 final ExtendedType extType = (ExtendedType) nodeToResolveType;
449 final TypeDefinitionBuilder newType = extendedTypeWithNewBaseTypeBuilder(targetTypeBuilder, extType,
450 modules, module, nodeToResolve.getLine());
451 resolvedType = newType;
453 resolvedType = targetTypeBuilder;
456 // validate constraints
457 final TypeConstraints constraints = findConstraintsFromTypeBuilder(nodeToResolve,
458 new TypeConstraints(module.getName(), nodeToResolve.getLine()), modules, module, null);
459 constraints.validateConstraints();
461 nodeToResolve.setTypedef(resolvedType);
465 * Resolve unknown type of node. It is assumed that type of node is either
466 * UnknownType or ExtendedType with UnknownType as base type.
468 * @param nodeToResolve
469 * node with type to resolve
475 * SchemaContext containing already resolved modules
477 private void resolveTypeWithContext(final TypeAwareBuilder nodeToResolve,
478 final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module,
479 final SchemaContext context) {
480 TypeDefinitionBuilder resolvedType = null;
481 final int line = nodeToResolve.getLine();
482 final TypeDefinition<?> nodeToResolveType = nodeToResolve.getType();
483 final QName unknownTypeQName = nodeToResolveType.getBaseType().getQName();
484 final ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module,
485 unknownTypeQName.getPrefix(), line);
487 if (dependentModuleBuilder == null) {
488 final Module dependentModule = findModuleFromContext(context, module, unknownTypeQName.getPrefix(), line);
489 final Set<TypeDefinition<?>> types = dependentModule.getTypeDefinitions();
490 final TypeDefinition<?> type = findTypeByName(types, unknownTypeQName.getLocalName());
492 if (nodeToResolveType instanceof ExtendedType) {
493 final ExtendedType extType = (ExtendedType) nodeToResolveType;
494 final TypeDefinitionBuilder newType = extendedTypeWithNewBaseType(type, extType, module,
495 nodeToResolve.getLine());
497 nodeToResolve.setTypedef(newType);
499 if (nodeToResolve instanceof TypeDefinitionBuilder) {
500 TypeDefinitionBuilder tdb = (TypeDefinitionBuilder) nodeToResolve;
501 TypeConstraints tc = findConstraintsFromTypeBuilder(nodeToResolve,
502 new TypeConstraints(module.getName(), nodeToResolve.getLine()), modules, module, context);
503 tdb.setLengths(tc.getLength());
504 tdb.setPatterns(tc.getPatterns());
505 tdb.setRanges(tc.getRange());
506 tdb.setFractionDigits(tc.getFractionDigits());
508 nodeToResolve.setType(type);
512 final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(nodeToResolve,
513 dependentModuleBuilder, unknownTypeQName.getLocalName(), module.getName(), line);
515 if (nodeToResolveType instanceof ExtendedType) {
516 final ExtendedType extType = (ExtendedType) nodeToResolveType;
517 final TypeDefinitionBuilder newType = extendedTypeWithNewBaseTypeBuilder(targetTypeBuilder, extType,
518 modules, module, nodeToResolve.getLine());
519 resolvedType = newType;
521 resolvedType = targetTypeBuilder;
524 // validate constraints
525 final TypeConstraints constraints = findConstraintsFromTypeBuilder(nodeToResolve, new TypeConstraints(
526 module.getName(), nodeToResolve.getLine()), modules, module, context);
527 constraints.validateConstraints();
529 nodeToResolve.setTypedef(resolvedType);
533 private void resolveTypeUnion(final UnionTypeBuilder union,
534 final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder builder) {
536 final List<TypeDefinition<?>> unionTypes = union.getTypes();
537 final List<TypeDefinition<?>> toRemove = new ArrayList<TypeDefinition<?>>();
538 for (TypeDefinition<?> unionType : unionTypes) {
539 if (unionType instanceof UnknownType) {
540 final UnknownType ut = (UnknownType) unionType;
541 final ModuleBuilder dependentModule = findDependentModuleBuilder(modules, builder, ut.getQName()
542 .getPrefix(), union.getLine());
543 final TypeDefinitionBuilder resolvedType = findTypeDefinitionBuilder(union, dependentModule, ut
544 .getQName().getLocalName(), builder.getName(), union.getLine());
545 union.setTypedef(resolvedType);
547 } else if (unionType instanceof ExtendedType) {
548 final ExtendedType extType = (ExtendedType) unionType;
549 final TypeDefinition<?> extTypeBase = extType.getBaseType();
550 if (extTypeBase instanceof UnknownType) {
551 final UnknownType ut = (UnknownType) extTypeBase;
552 final ModuleBuilder dependentModule = findDependentModuleBuilder(modules, builder, ut.getQName()
553 .getPrefix(), union.getLine());
554 final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(union, dependentModule,
555 ut.getQName().getLocalName(), builder.getName(), union.getLine());
557 final TypeDefinitionBuilder newType = extendedTypeWithNewBaseTypeBuilder(targetTypeBuilder,
558 extType, modules, builder, union.getLine());
560 union.setTypedef(newType);
561 toRemove.add(extType);
565 unionTypes.removeAll(toRemove);
568 private void resolveTypeUnionWithContext(final UnionTypeBuilder union,
569 final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder builder,
570 final SchemaContext context) {
572 final List<TypeDefinition<?>> unionTypes = union.getTypes();
573 final List<TypeDefinition<?>> toRemove = new ArrayList<TypeDefinition<?>>();
574 for (TypeDefinition<?> unionType : unionTypes) {
575 if (unionType instanceof UnknownType) {
576 final UnknownType ut = (UnknownType) unionType;
577 final QName utQName = ut.getQName();
578 final ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, builder,
579 utQName.getPrefix(), union.getLine());
581 if (dependentModuleBuilder == null) {
582 Module dependentModule = findModuleFromContext(context, builder, utQName.getPrefix(),
584 Set<TypeDefinition<?>> types = dependentModule.getTypeDefinitions();
585 TypeDefinition<?> type = findTypeByName(types, utQName.getLocalName());
589 final TypeDefinitionBuilder resolvedType = findTypeDefinitionBuilder(union, dependentModuleBuilder,
590 utQName.getLocalName(), builder.getName(), union.getLine());
591 union.setTypedef(resolvedType);
595 } else if (unionType instanceof ExtendedType) {
596 final ExtendedType extType = (ExtendedType) unionType;
597 TypeDefinition<?> extTypeBase = extType.getBaseType();
598 if (extTypeBase instanceof UnknownType) {
599 final UnknownType ut = (UnknownType) extTypeBase;
600 final QName utQName = ut.getQName();
601 final ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, builder,
602 utQName.getPrefix(), union.getLine());
604 if (dependentModuleBuilder == null) {
605 final Module dependentModule = findModuleFromContext(context, builder, utQName.getPrefix(),
607 Set<TypeDefinition<?>> types = dependentModule.getTypeDefinitions();
608 TypeDefinition<?> type = findTypeByName(types, utQName.getLocalName());
609 final TypeDefinitionBuilder newType = extendedTypeWithNewBaseType(type, extType, builder, 0);
611 union.setTypedef(newType);
612 toRemove.add(extType);
614 final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(union,
615 dependentModuleBuilder, utQName.getLocalName(), builder.getName(), union.getLine());
617 final TypeDefinitionBuilder newType = extendedTypeWithNewBaseTypeBuilder(targetTypeBuilder,
618 extType, modules, builder, union.getLine());
620 union.setTypedef(newType);
621 toRemove.add(extType);
626 unionTypes.removeAll(toRemove);
630 * Go through all augment definitions and resolve them. It is expected that
631 * modules are already sorted by their dependencies. This method also finds
632 * augment target node and add child nodes to it.
635 * all available modules
637 private void resolveAugments(final Map<String, TreeMap<Date, ModuleBuilder>> modules) {
638 final List<ModuleBuilder> allModulesList = new ArrayList<ModuleBuilder>();
639 final Set<ModuleBuilder> allModulesSet = new HashSet<ModuleBuilder>();
640 for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
641 for (Map.Entry<Date, ModuleBuilder> inner : entry.getValue().entrySet()) {
642 allModulesList.add(inner.getValue());
643 allModulesSet.add(inner.getValue());
647 for (int i = 0; i < allModulesList.size(); i++) {
648 final ModuleBuilder module = allModulesList.get(i);
649 // try to resolve augments in module
650 resolveAugment(modules, module);
651 // while all augments are not resolved
652 final Iterator<ModuleBuilder> allModulesIterator = allModulesSet.iterator();
653 while (!(module.getAugmentsResolved() == module.getAllAugments().size())) {
654 ModuleBuilder nextModule = null;
655 // try resolve other module augments
657 nextModule = allModulesIterator.next();
658 resolveAugment(modules, nextModule);
659 } catch (NoSuchElementException e) {
660 throw new YangParseException("Failed to resolve augments in module '" + module.getName() + "'.", e);
662 // then try to resolve first module again
663 resolveAugment(modules, module);
669 * Tries to resolve augments in given module. If augment target node is not
673 * all available modules
677 private void resolveAugment(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
678 if (module.getAugmentsResolved() < module.getAllAugments().size()) {
679 for (AugmentationSchemaBuilder augmentBuilder : module.getAllAugments()) {
681 if (!augmentBuilder.isResolved()) {
682 final SchemaPath augmentTargetSchemaPath = augmentBuilder.getTargetPath();
683 final List<QName> path = augmentTargetSchemaPath.getPath();
685 final QName qname = path.get(0);
686 String prefix = qname.getPrefix();
687 if (prefix == null) {
688 prefix = module.getPrefix();
691 final ModuleBuilder dependentModule = findDependentModuleBuilder(modules, module, prefix,
692 augmentBuilder.getLine());
693 processAugmentation(augmentBuilder, path, module, dependentModule);
701 * Go through all augment definitions and resolve them. This method works in
702 * same way as {@link #resolveAugments(Map)} except that if target node is
703 * not found in loaded modules, it search for target node in given context.
708 * SchemaContext containing already resolved modules
710 private void resolveAugmentsWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
711 final SchemaContext context) {
712 final List<ModuleBuilder> allModulesList = new ArrayList<ModuleBuilder>();
713 final Set<ModuleBuilder> allModulesSet = new HashSet<ModuleBuilder>();
714 for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
715 for (Map.Entry<Date, ModuleBuilder> inner : entry.getValue().entrySet()) {
716 allModulesList.add(inner.getValue());
717 allModulesSet.add(inner.getValue());
721 for (int i = 0; i < allModulesList.size(); i++) {
722 final ModuleBuilder module = allModulesList.get(i);
723 // try to resolve augments in module
724 resolveAugmentWithContext(modules, module, context);
725 // while all augments are not resolved
726 final Iterator<ModuleBuilder> allModulesIterator = allModulesSet.iterator();
727 while (!(module.getAugmentsResolved() == module.getAllAugments().size())) {
728 ModuleBuilder nextModule = null;
729 // try resolve other module augments
731 nextModule = allModulesIterator.next();
732 resolveAugmentWithContext(modules, nextModule, context);
733 } catch (NoSuchElementException e) {
734 throw new YangParseException("Failed to resolve augments in module '" + module.getName() + "'.", e);
736 // then try to resolve first module again
737 resolveAugmentWithContext(modules, module, context);
743 * Tries to resolve augments in given module. If augment target node is not
747 * all available modules
751 private void resolveAugmentWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
752 final ModuleBuilder module, final SchemaContext context) {
753 if (module.getAugmentsResolved() < module.getAllAugments().size()) {
755 for (AugmentationSchemaBuilder augmentBuilder : module.getAllAugments()) {
756 final int line = augmentBuilder.getLine();
758 if (!augmentBuilder.isResolved()) {
759 final List<QName> path = augmentBuilder.getTargetPath().getPath();
760 final QName qname = path.get(0);
761 String prefix = qname.getPrefix();
762 if (prefix == null) {
763 prefix = module.getPrefix();
766 // try to find augment target module in loaded modules...
767 final ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module, prefix,
769 if (dependentModuleBuilder == null) {
770 // perform augmentation on module from context and
771 // continue to next augment
772 processAugmentationOnContext(augmentBuilder, path, module, prefix, line, context);
775 processAugmentation(augmentBuilder, path, module, dependentModuleBuilder);
784 * Go through identity statements defined in current module and resolve
785 * their 'base' statement if present.
790 * module being resolved
792 private void resolveIdentities(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
793 final Set<IdentitySchemaNodeBuilder> identities = module.getIdentities();
794 for (IdentitySchemaNodeBuilder identity : identities) {
795 final String baseIdentityName = identity.getBaseIdentityName();
796 if (baseIdentityName != null) {
797 String baseIdentityPrefix = null;
798 String baseIdentityLocalName = null;
799 if (baseIdentityName.contains(":")) {
800 final String[] splitted = baseIdentityName.split(":");
801 baseIdentityPrefix = splitted[0];
802 baseIdentityLocalName = splitted[1];
804 baseIdentityPrefix = module.getPrefix();
805 baseIdentityLocalName = baseIdentityName;
807 final ModuleBuilder dependentModule = findDependentModuleBuilder(modules, module, baseIdentityPrefix,
810 final Set<IdentitySchemaNodeBuilder> dependentModuleIdentities = dependentModule.getIdentities();
811 for (IdentitySchemaNodeBuilder idBuilder : dependentModuleIdentities) {
812 if (idBuilder.getQName().getLocalName().equals(baseIdentityLocalName)) {
813 identity.setBaseIdentity(idBuilder);
821 * Go through identity statements defined in current module and resolve
822 * their 'base' statement. Method tries to find base identity in given
823 * modules. If base identity is not found, method will search it in context.
830 * SchemaContext containing already resolved modules
832 private void resolveIdentitiesWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
833 final ModuleBuilder module, final SchemaContext context) {
834 final Set<IdentitySchemaNodeBuilder> identities = module.getIdentities();
835 for (IdentitySchemaNodeBuilder identity : identities) {
836 final String baseIdentityName = identity.getBaseIdentityName();
837 if (baseIdentityName != null) {
838 String baseIdentityPrefix = null;
839 String baseIdentityLocalName = null;
840 if (baseIdentityName.contains(":")) {
841 final String[] splitted = baseIdentityName.split(":");
842 baseIdentityPrefix = splitted[0];
843 baseIdentityLocalName = splitted[1];
845 baseIdentityPrefix = module.getPrefix();
846 baseIdentityLocalName = baseIdentityName;
848 final ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module,
849 baseIdentityPrefix, identity.getLine());
851 if (dependentModuleBuilder == null) {
852 final Module dependentModule = findModuleFromContext(context, module, baseIdentityPrefix,
854 final Set<IdentitySchemaNode> dependentModuleIdentities = dependentModule.getIdentities();
855 for (IdentitySchemaNode idNode : dependentModuleIdentities) {
856 if (idNode.getQName().getLocalName().equals(baseIdentityLocalName)) {
857 identity.setBaseIdentity(idNode);
861 final Set<IdentitySchemaNodeBuilder> dependentModuleIdentities = dependentModuleBuilder
863 for (IdentitySchemaNodeBuilder idBuilder : dependentModuleIdentities) {
864 if (idBuilder.getQName().getLocalName().equals(baseIdentityLocalName)) {
865 identity.setBaseIdentity(idBuilder);
874 * Go through uses statements defined in current module and resolve their
880 * module being resolved
882 private void resolveUsesRefine(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
883 final List<UsesNodeBuilder> allModuleUses = module.getAllUsesNodes();
884 for (UsesNodeBuilder usesNode : allModuleUses) {
886 final int line = usesNode.getLine();
887 final GroupingBuilder targetGrouping = getTargetGroupingFromModules(usesNode, modules, module);
888 usesNode.setGroupingPath(targetGrouping.getPath());
889 for (RefineHolder refine : usesNode.getRefines()) {
890 final SchemaNodeBuilder nodeToRefine = RefineUtils.getRefineNodeFromGroupingBuilder(targetGrouping,
891 refine, module.getName());
892 if (nodeToRefine instanceof GroupingMember) {
893 ((GroupingMember) nodeToRefine).setAddedByUses(true);
895 RefineUtils.performRefine(nodeToRefine, refine, line);
896 usesNode.addRefineNode(nodeToRefine);
900 processUsesNode(usesNode, targetGrouping);
905 * Tries to search target grouping in given modules and resolve refine
906 * nodes. If grouping is not found in modules, method tries to find it in
907 * modules from context.
914 * SchemaContext containing already resolved modules
916 private void resolveUsesRefineWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
917 final ModuleBuilder module, final SchemaContext context) {
918 final List<UsesNodeBuilder> moduleUses = module.getAllUsesNodes();
919 for (UsesNodeBuilder usesNode : moduleUses) {
920 final int line = usesNode.getLine();
922 final GroupingBuilder targetGroupingBuilder = getTargetGroupingFromModules(usesNode, modules, module);
923 if (targetGroupingBuilder == null) {
924 final GroupingDefinition targetGrouping = getTargetGroupingFromContext(usesNode, module, context);
925 usesNode.setGroupingPath(targetGrouping.getPath());
926 for (RefineHolder refine : usesNode.getRefines()) {
927 final SchemaNodeBuilder nodeToRefine = RefineUtils.getRefineNodeFromGroupingDefinition(
928 targetGrouping, refine, module.getName());
929 if (nodeToRefine instanceof GroupingMember) {
930 ((GroupingMember) nodeToRefine).setAddedByUses(true);
932 RefineUtils.performRefine(nodeToRefine, refine, line);
933 usesNode.addRefineNode(nodeToRefine);
936 processUsesNode(usesNode, targetGrouping);
938 usesNode.setGroupingPath(targetGroupingBuilder.getPath());
939 for (RefineHolder refine : usesNode.getRefines()) {
940 final SchemaNodeBuilder nodeToRefine = RefineUtils.getRefineNodeFromGroupingBuilder(
941 targetGroupingBuilder, refine, module.getName());
942 if (nodeToRefine instanceof GroupingMember) {
943 ((GroupingMember) nodeToRefine).setAddedByUses(true);
945 RefineUtils.performRefine(nodeToRefine, refine, line);
946 usesNode.addRefineNode(nodeToRefine);
949 processUsesNode(usesNode, targetGroupingBuilder);
955 * Search given modules for grouping by name defined in uses node.
958 * builder of uses statement
963 * @return grouping with given name if found, null otherwise
965 private GroupingBuilder getTargetGroupingFromModules(final UsesNodeBuilder usesBuilder,
966 final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
967 final int line = usesBuilder.getLine();
968 final String groupingString = usesBuilder.getGroupingName();
969 String groupingPrefix;
972 if (groupingString.contains(":")) {
973 String[] splitted = groupingString.split(":");
974 if (splitted.length != 2 || groupingString.contains("/")) {
975 throw new YangParseException(module.getName(), line, "Invalid name of target grouping");
977 groupingPrefix = splitted[0];
978 groupingName = splitted[1];
980 groupingPrefix = module.getPrefix();
981 groupingName = groupingString;
984 ModuleBuilder dependentModule = null;
985 if (groupingPrefix.equals(module.getPrefix())) {
986 dependentModule = module;
988 dependentModule = findDependentModuleBuilder(modules, module, groupingPrefix, line);
991 if (dependentModule == null) {
995 GroupingBuilder result = null;
996 Set<GroupingBuilder> groupings = dependentModule.getGroupingBuilders();
997 result = findGroupingBuilder(groupings, groupingName);
998 if (result != null) {
1002 Builder parent = usesBuilder.getParent();
1004 while (parent != null) {
1005 if (parent instanceof DataNodeContainerBuilder) {
1006 groupings = ((DataNodeContainerBuilder) parent).getGroupingBuilders();
1007 } else if (parent instanceof RpcDefinitionBuilder) {
1008 groupings = ((RpcDefinitionBuilder) parent).getGroupings();
1010 result = findGroupingBuilder(groupings, groupingName);
1011 if (result == null) {
1012 parent = parent.getParent();
1018 if (result == null) {
1019 throw new YangParseException(module.getName(), line, "Referenced grouping '" + groupingName
1026 * Search context for grouping by name defined in uses node.
1028 * @param usesBuilder
1029 * builder of uses statement
1033 * SchemaContext containing already resolved modules
1034 * @return grouping with given name if found, null otherwise
1036 private GroupingDefinition getTargetGroupingFromContext(final UsesNodeBuilder usesBuilder,
1037 final ModuleBuilder module, final SchemaContext context) {
1038 final int line = usesBuilder.getLine();
1039 String groupingString = usesBuilder.getGroupingName();
1040 String groupingPrefix;
1041 String groupingName;
1043 if (groupingString.contains(":")) {
1044 String[] splitted = groupingString.split(":");
1045 if (splitted.length != 2 || groupingString.contains("/")) {
1046 throw new YangParseException(module.getName(), line, "Invalid name of target grouping");
1048 groupingPrefix = splitted[0];
1049 groupingName = splitted[1];
1051 groupingPrefix = module.getPrefix();
1052 groupingName = groupingString;
1055 Module dependentModule = findModuleFromContext(context, module, groupingPrefix, line);
1056 return findGroupingDefinition(dependentModule.getGroupings(), groupingName);
1060 * Add nodes defined in target grouping to current context.
1063 * @param targetGrouping
1065 private void processUsesNode(final UsesNodeBuilder usesNode, final GroupingBuilder targetGrouping) {
1066 List<SchemaNodeBuilder> refineNodes = usesNode.getRefineNodes();
1067 DataNodeContainerBuilder parent = usesNode.getParent();
1068 SchemaPath parentPath = parent.getPath();
1069 for (DataSchemaNodeBuilder child : targetGrouping.getChildNodeBuilders()) {
1070 // if node is refined, take it from refined nodes and continue
1071 SchemaNodeBuilder refined = getRefined(child.getQName(), refineNodes);
1072 if (refined != null) {
1073 refined.setPath(createSchemaPath(parentPath, refined.getQName().getLocalName()));
1074 parent.addChildNode((DataSchemaNodeBuilder) refined);
1078 DataSchemaNodeBuilder newChild = null;
1079 if (child instanceof AnyXmlBuilder) {
1080 newChild = new AnyXmlBuilder((AnyXmlBuilder) child);
1081 } else if (child instanceof ChoiceBuilder) {
1082 newChild = new ChoiceBuilder((ChoiceBuilder) child);
1083 } else if (child instanceof ContainerSchemaNodeBuilder) {
1084 newChild = new ContainerSchemaNodeBuilder((ContainerSchemaNodeBuilder) child);
1085 } else if (child instanceof LeafListSchemaNodeBuilder) {
1086 newChild = new LeafListSchemaNodeBuilder((LeafListSchemaNodeBuilder) child);
1087 } else if (child instanceof LeafSchemaNodeBuilder) {
1088 newChild = new LeafSchemaNodeBuilder((LeafSchemaNodeBuilder) child);
1089 } else if (child instanceof ListSchemaNodeBuilder) {
1090 newChild = new ListSchemaNodeBuilder((ListSchemaNodeBuilder) child);
1093 if (newChild instanceof GroupingMember) {
1094 ((GroupingMember) newChild).setAddedByUses(true);
1096 newChild.setPath(createSchemaPath(parentPath, newChild.getQName().getLocalName()));
1097 parent.addChildNode(newChild);
1099 for (GroupingBuilder g : targetGrouping.getGroupingBuilders()) {
1100 GroupingBuilder newGrouping = new GroupingBuilderImpl(g);
1101 newGrouping.setAddedByUses(true);
1102 newGrouping.setPath(createSchemaPath(parentPath, newGrouping.getQName().getLocalName()));
1103 parent.addGrouping(newGrouping);
1105 for (TypeDefinitionBuilder td : targetGrouping.getTypeDefinitionBuilders()) {
1106 TypeDefinitionBuilder newType = new TypeDefinitionBuilderImpl(td);
1107 newType.setAddedByUses(true);
1108 newType.setPath(createSchemaPath(parentPath, newType.getQName().getLocalName()));
1109 parent.addTypedef(newType);
1111 for (UsesNodeBuilder un : targetGrouping.getUses()) {
1112 UsesNodeBuilder newUses = new UsesNodeBuilderImpl(un);
1113 newUses.setAddedByUses(true);
1114 // uses has not path
1115 parent.addUsesNode(newUses);
1117 for (UnknownSchemaNodeBuilder un : targetGrouping.getUnknownNodes()) {
1118 UnknownSchemaNodeBuilder newUn = new UnknownSchemaNodeBuilder(un);
1119 newUn.setAddedByUses(true);
1120 newUn.setPath(createSchemaPath(parentPath, un.getQName().getLocalName()));
1121 parent.addUnknownSchemaNode(newUn);
1125 private void processUsesNode(final UsesNodeBuilder usesNode, final GroupingDefinition targetGrouping) {
1126 final int line = usesNode.getLine();
1127 List<SchemaNodeBuilder> refineNodes = usesNode.getRefineNodes();
1128 DataNodeContainerBuilder parent = usesNode.getParent();
1129 SchemaPath parentPath = parent.getPath();
1130 for (DataSchemaNode child : targetGrouping.getChildNodes()) {
1131 // if node is refined, take it from refined nodes and continue
1132 SchemaNodeBuilder refined = getRefined(child.getQName(), refineNodes);
1133 if (refined != null) {
1134 refined.setPath(createSchemaPath(parentPath, refined.getQName().getLocalName()));
1135 parent.addChildNode((DataSchemaNodeBuilder) refined);
1139 DataSchemaNodeBuilder newChild = null;
1140 if (child instanceof AnyXmlSchemaNode) {
1141 newChild = createAnyXml((AnyXmlSchemaNode) child, line);
1142 } else if (child instanceof ChoiceNode) {
1143 newChild = createChoice((ChoiceNode) child, line);
1144 } else if (child instanceof ContainerSchemaNode) {
1145 newChild = createContainer((ContainerSchemaNode) child, line);
1146 } else if (child instanceof LeafListSchemaNode) {
1147 newChild = createLeafList((LeafListSchemaNode) child, line);
1148 } else if (child instanceof LeafSchemaNode) {
1149 newChild = createLeafBuilder((LeafSchemaNode) child, line);
1150 } else if (child instanceof ListSchemaNode) {
1151 newChild = createList((ListSchemaNode) child, line);
1154 if (newChild instanceof GroupingMember) {
1155 ((GroupingMember) newChild).setAddedByUses(true);
1157 newChild.setPath(createSchemaPath(parentPath, newChild.getQName().getLocalName()));
1158 parent.addChildNode(newChild);
1160 for (GroupingDefinition g : targetGrouping.getGroupings()) {
1161 GroupingBuilder newGrouping = createGrouping(g, line);
1162 newGrouping.setAddedByUses(true);
1163 newGrouping.setPath(createSchemaPath(parentPath, newGrouping.getQName().getLocalName()));
1164 parent.addGrouping(newGrouping);
1166 for (TypeDefinition<?> td : targetGrouping.getTypeDefinitions()) {
1167 TypeDefinitionBuilder newType = createTypedef((ExtendedType) td, line);
1168 newType.setAddedByUses(true);
1169 newType.setPath(createSchemaPath(parentPath, newType.getQName().getLocalName()));
1170 parent.addTypedef(newType);
1172 for (UsesNode un : targetGrouping.getUses()) {
1173 if (un instanceof UsesNodeImpl) {
1174 UsesNodeBuilder newUses = new UsesNodeBuilderImpl(((UsesNodeImpl) un).toBuilder());
1175 newUses.setAddedByUses(true);
1176 // uses has not path
1177 parent.addUsesNode(newUses);
1180 for (UnknownSchemaNode un : targetGrouping.getUnknownSchemaNodes()) {
1181 UnknownSchemaNodeBuilder newNode = createUnknownSchemaNode(un, line);
1182 newNode.setAddedByUses(true);
1183 newNode.setPath(createSchemaPath(parentPath, un.getQName().getLocalName()));
1184 parent.addUnknownSchemaNode(newNode);
1188 private QName findFullQName(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module,
1189 final IdentityrefTypeBuilder idref) {
1190 QName result = null;
1191 String baseString = idref.getBaseString();
1192 if (baseString.contains(":")) {
1193 String[] splittedBase = baseString.split(":");
1194 if (splittedBase.length > 2) {
1195 throw new YangParseException(module.getName(), idref.getLine(), "Failed to parse identityref base: "
1198 String prefix = splittedBase[0];
1199 String name = splittedBase[1];
1200 ModuleBuilder dependentModule = findDependentModuleBuilder(modules, module, prefix, idref.getLine());
1201 result = new QName(dependentModule.getNamespace(), dependentModule.getRevision(), prefix, name);
1203 result = new QName(module.getNamespace(), module.getRevision(), module.getPrefix(), baseString);
1208 private void resolveUnknownNodes(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
1209 for (UnknownSchemaNodeBuilder usnb : module.getUnknownNodes()) {
1210 QName nodeType = usnb.getNodeType();
1211 if (nodeType.getNamespace() == null || nodeType.getRevision() == null) {
1213 ModuleBuilder dependentModule = findDependentModuleBuilder(modules, module, nodeType.getPrefix(),
1215 QName newNodeType = new QName(dependentModule.getNamespace(), dependentModule.getRevision(),
1216 nodeType.getPrefix(), nodeType.getLocalName());
1217 usnb.setNodeType(newNodeType);
1218 } catch (YangParseException e) {
1219 logger.debug(module.getName(), usnb.getLine(), "Failed to find unknown node type: " + nodeType);
1225 private void resolveUnknownNodesWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
1226 final ModuleBuilder module, final SchemaContext context) {
1227 for (UnknownSchemaNodeBuilder unknownNodeBuilder : module.getUnknownNodes()) {
1228 QName nodeType = unknownNodeBuilder.getNodeType();
1229 if (nodeType.getNamespace() == null || nodeType.getRevision() == null) {
1231 ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module,
1232 nodeType.getPrefix(), unknownNodeBuilder.getLine());
1234 QName newNodeType = null;
1235 if (dependentModuleBuilder == null) {
1236 Module dependentModule = findModuleFromContext(context, module, nodeType.getPrefix(),
1237 unknownNodeBuilder.getLine());
1238 newNodeType = new QName(dependentModule.getNamespace(), dependentModule.getRevision(),
1239 nodeType.getPrefix(), nodeType.getLocalName());
1241 newNodeType = new QName(dependentModuleBuilder.getNamespace(),
1242 dependentModuleBuilder.getRevision(), nodeType.getPrefix(), nodeType.getLocalName());
1245 unknownNodeBuilder.setNodeType(newNodeType);
1246 } catch (YangParseException e) {
1247 logger.debug(module.getName(), unknownNodeBuilder.getLine(), "Failed to find unknown node type: "
1254 private void resolveDeviations(final Map<String, TreeMap<Date, ModuleBuilder>> modules) {
1255 for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
1256 for (Map.Entry<Date, ModuleBuilder> inner : entry.getValue().entrySet()) {
1257 ModuleBuilder b = inner.getValue();
1258 resolveDeviation(modules, b);
1263 private void resolveDeviation(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
1264 for (DeviationBuilder dev : module.getDeviations()) {
1265 int line = dev.getLine();
1266 SchemaPath targetPath = dev.getTargetPath();
1267 List<QName> path = targetPath.getPath();
1268 QName q0 = path.get(0);
1269 String prefix = q0.getPrefix();
1270 if (prefix == null) {
1271 prefix = module.getPrefix();
1274 ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module, prefix, line);
1275 processDeviation(dev, dependentModuleBuilder, path, module);
1279 private void resolveDeviationsWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
1280 final SchemaContext context) {
1281 for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
1282 for (Map.Entry<Date, ModuleBuilder> inner : entry.getValue().entrySet()) {
1283 ModuleBuilder b = inner.getValue();
1284 resolveDeviationWithContext(modules, b, context);
1289 private void resolveDeviationWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
1290 final ModuleBuilder module, final SchemaContext context) {
1291 for (DeviationBuilder dev : module.getDeviations()) {
1292 int line = dev.getLine();
1293 SchemaPath targetPath = dev.getTargetPath();
1294 List<QName> path = targetPath.getPath();
1295 QName q0 = path.get(0);
1296 String prefix = q0.getPrefix();
1297 if (prefix == null) {
1298 prefix = module.getPrefix();
1302 ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module, prefix, line);
1303 if (dependentModuleBuilder == null) {
1304 Module dependentModule = findModuleFromContext(context, module, prefix, line);
1305 Object currentParent = dependentModule;
1307 for (int i = 0; i < path.size(); i++) {
1308 if (currentParent == null) {
1309 throw new YangParseException(module.getName(), line, "Failed to find deviation target.");
1311 QName q = path.get(i);
1312 name = q.getLocalName();
1313 if (currentParent instanceof DataNodeContainer) {
1314 currentParent = ((DataNodeContainer) currentParent).getDataChildByName(name);
1318 if (currentParent == null) {
1319 throw new YangParseException(module.getName(), line, "Failed to find deviation target.");
1321 if (currentParent instanceof SchemaNode) {
1322 dev.setTargetPath(((SchemaNode) currentParent).getPath());
1326 processDeviation(dev, dependentModuleBuilder, path, module);
1332 * Correct deviation target path in deviation builder.
1336 * @param dependentModuleBuilder
1337 * module containing deviation target
1339 * current deviation target path
1343 private void processDeviation(final DeviationBuilder dev, final ModuleBuilder dependentModuleBuilder,
1344 final List<QName> path, final ModuleBuilder module) {
1345 final int line = dev.getLine();
1346 Builder currentParent = dependentModuleBuilder;
1348 for (int i = 0; i < path.size(); i++) {
1349 if (currentParent == null) {
1350 throw new YangParseException(module.getName(), line, "Failed to find deviation target.");
1352 QName q = path.get(i);
1353 String name = q.getLocalName();
1354 if (currentParent instanceof DataNodeContainerBuilder) {
1355 currentParent = ((DataNodeContainerBuilder) currentParent).getDataChildByName(name);
1359 if (currentParent == null || !(currentParent instanceof SchemaNodeBuilder)) {
1360 throw new YangParseException(module.getName(), line, "Failed to find deviation target.");
1362 dev.setTargetPath(((SchemaNodeBuilder) currentParent).getPath());