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 Set<TypeAwareBuilder> dirtyNodes = module.getDirtyNodes();
385 if (!dirtyNodes.isEmpty()) {
386 for (TypeAwareBuilder nodeToResolve : dirtyNodes) {
387 if (nodeToResolve instanceof UnionTypeBuilder) {
388 // special handling for union types
389 resolveTypeUnion((UnionTypeBuilder) nodeToResolve, modules, module);
390 } else if (nodeToResolve.getTypedef() instanceof IdentityrefTypeBuilder) {
391 // special handling for identityref types
392 IdentityrefTypeBuilder idref = (IdentityrefTypeBuilder) nodeToResolve.getTypedef();
393 nodeToResolve.setType(new IdentityrefType(findFullQName(modules, module, idref), idref.getPath()));
395 resolveType(nodeToResolve, modules, module);
401 private void resolveDirtyNodesWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
402 final ModuleBuilder module, SchemaContext context) {
403 final Set<TypeAwareBuilder> dirtyNodes = module.getDirtyNodes();
404 if (!dirtyNodes.isEmpty()) {
405 for (TypeAwareBuilder nodeToResolve : dirtyNodes) {
406 if (nodeToResolve instanceof UnionTypeBuilder) {
407 // special handling for union types
408 resolveTypeUnionWithContext((UnionTypeBuilder) nodeToResolve, modules, module, context);
409 } else if (nodeToResolve.getTypedef() instanceof IdentityrefTypeBuilder) {
410 // special handling for identityref types
411 IdentityrefTypeBuilder idref = (IdentityrefTypeBuilder) nodeToResolve.getTypedef();
412 nodeToResolve.setType(new IdentityrefType(findFullQName(modules, module, idref), idref.getPath()));
414 resolveTypeWithContext(nodeToResolve, modules, module, context);
421 * Resolve unknown type of node. It is assumed that type of node is either
422 * UnknownType or ExtendedType with UnknownType as base type.
424 * @param nodeToResolve
425 * node with type to resolve
431 private void resolveType(final TypeAwareBuilder nodeToResolve,
432 final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
433 TypeDefinitionBuilder resolvedType = null;
434 final int line = nodeToResolve.getLine();
435 final TypeDefinition<?> nodeToResolveType = nodeToResolve.getType();
436 final QName unknownTypeQName = nodeToResolveType.getBaseType().getQName();
437 final ModuleBuilder dependentModule = findDependentModuleBuilder(modules, module, unknownTypeQName.getPrefix(),
440 final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(nodeToResolve, dependentModule,
441 unknownTypeQName.getLocalName(), module.getName(), line);
443 if (nodeToResolveType instanceof ExtendedType) {
444 final ExtendedType extType = (ExtendedType) nodeToResolveType;
445 final TypeDefinitionBuilder newType = extendedTypeWithNewBaseTypeBuilder(targetTypeBuilder, extType,
446 modules, module, nodeToResolve.getLine());
447 resolvedType = newType;
449 resolvedType = targetTypeBuilder;
452 // validate constraints
453 final TypeConstraints constraints = findConstraintsFromTypeBuilder(nodeToResolve,
454 new TypeConstraints(module.getName(), nodeToResolve.getLine()), modules, module, null);
455 constraints.validateConstraints();
457 nodeToResolve.setTypedef(resolvedType);
461 * Resolve unknown type of node. It is assumed that type of node is either
462 * UnknownType or ExtendedType with UnknownType as base type.
464 * @param nodeToResolve
465 * node with type to resolve
471 * SchemaContext containing already resolved modules
473 private void resolveTypeWithContext(final TypeAwareBuilder nodeToResolve,
474 final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module,
475 final SchemaContext context) {
476 TypeDefinitionBuilder resolvedType = null;
477 final int line = nodeToResolve.getLine();
478 final TypeDefinition<?> nodeToResolveType = nodeToResolve.getType();
479 final QName unknownTypeQName = nodeToResolveType.getBaseType().getQName();
480 final ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module,
481 unknownTypeQName.getPrefix(), line);
483 if (dependentModuleBuilder == null) {
484 final Module dependentModule = findModuleFromContext(context, module, unknownTypeQName.getPrefix(), line);
485 final Set<TypeDefinition<?>> types = dependentModule.getTypeDefinitions();
486 final TypeDefinition<?> type = findTypeByName(types, unknownTypeQName.getLocalName());
488 if (nodeToResolveType instanceof ExtendedType) {
489 final ExtendedType extType = (ExtendedType) nodeToResolveType;
490 final TypeDefinitionBuilder newType = extendedTypeWithNewBaseType(type, extType, module,
491 nodeToResolve.getLine());
493 nodeToResolve.setTypedef(newType);
495 if (nodeToResolve instanceof TypeDefinitionBuilder) {
496 TypeDefinitionBuilder tdb = (TypeDefinitionBuilder) nodeToResolve;
497 TypeConstraints tc = findConstraintsFromTypeBuilder(nodeToResolve,
498 new TypeConstraints(module.getName(), nodeToResolve.getLine()), modules, module, context);
499 tdb.setLengths(tc.getLength());
500 tdb.setPatterns(tc.getPatterns());
501 tdb.setRanges(tc.getRange());
502 tdb.setFractionDigits(tc.getFractionDigits());
504 nodeToResolve.setType(type);
508 final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(nodeToResolve,
509 dependentModuleBuilder, unknownTypeQName.getLocalName(), module.getName(), line);
511 if (nodeToResolveType instanceof ExtendedType) {
512 final ExtendedType extType = (ExtendedType) nodeToResolveType;
513 final TypeDefinitionBuilder newType = extendedTypeWithNewBaseTypeBuilder(targetTypeBuilder, extType,
514 modules, module, nodeToResolve.getLine());
515 resolvedType = newType;
517 resolvedType = targetTypeBuilder;
520 // validate constraints
521 final TypeConstraints constraints = findConstraintsFromTypeBuilder(nodeToResolve, new TypeConstraints(
522 module.getName(), nodeToResolve.getLine()), modules, module, context);
523 constraints.validateConstraints();
525 nodeToResolve.setTypedef(resolvedType);
529 private void resolveTypeUnion(final UnionTypeBuilder union,
530 final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder builder) {
532 final List<TypeDefinition<?>> unionTypes = union.getTypes();
533 final List<TypeDefinition<?>> toRemove = new ArrayList<TypeDefinition<?>>();
534 for (TypeDefinition<?> unionType : unionTypes) {
535 if (unionType instanceof UnknownType) {
536 final UnknownType ut = (UnknownType) unionType;
537 final ModuleBuilder dependentModule = findDependentModuleBuilder(modules, builder, ut.getQName()
538 .getPrefix(), union.getLine());
539 final TypeDefinitionBuilder resolvedType = findTypeDefinitionBuilder(union, dependentModule, ut
540 .getQName().getLocalName(), builder.getName(), union.getLine());
541 union.setTypedef(resolvedType);
543 } else if (unionType instanceof ExtendedType) {
544 final ExtendedType extType = (ExtendedType) unionType;
545 final TypeDefinition<?> extTypeBase = extType.getBaseType();
546 if (extTypeBase instanceof UnknownType) {
547 final UnknownType ut = (UnknownType) extTypeBase;
548 final ModuleBuilder dependentModule = findDependentModuleBuilder(modules, builder, ut.getQName()
549 .getPrefix(), union.getLine());
550 final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(union, dependentModule,
551 ut.getQName().getLocalName(), builder.getName(), union.getLine());
553 final TypeDefinitionBuilder newType = extendedTypeWithNewBaseTypeBuilder(targetTypeBuilder,
554 extType, modules, builder, union.getLine());
556 union.setTypedef(newType);
557 toRemove.add(extType);
561 unionTypes.removeAll(toRemove);
564 private void resolveTypeUnionWithContext(final UnionTypeBuilder union,
565 final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder builder,
566 final SchemaContext context) {
568 final List<TypeDefinition<?>> unionTypes = union.getTypes();
569 final List<TypeDefinition<?>> toRemove = new ArrayList<TypeDefinition<?>>();
570 for (TypeDefinition<?> unionType : unionTypes) {
571 if (unionType instanceof UnknownType) {
572 final UnknownType ut = (UnknownType) unionType;
573 final QName utQName = ut.getQName();
574 final ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, builder,
575 utQName.getPrefix(), union.getLine());
577 if (dependentModuleBuilder == null) {
578 Module dependentModule = findModuleFromContext(context, builder, utQName.getPrefix(),
580 Set<TypeDefinition<?>> types = dependentModule.getTypeDefinitions();
581 TypeDefinition<?> type = findTypeByName(types, utQName.getLocalName());
585 final TypeDefinitionBuilder resolvedType = findTypeDefinitionBuilder(union, dependentModuleBuilder,
586 utQName.getLocalName(), builder.getName(), union.getLine());
587 union.setTypedef(resolvedType);
591 } else if (unionType instanceof ExtendedType) {
592 final ExtendedType extType = (ExtendedType) unionType;
593 TypeDefinition<?> extTypeBase = extType.getBaseType();
594 if (extTypeBase instanceof UnknownType) {
595 final UnknownType ut = (UnknownType) extTypeBase;
596 final QName utQName = ut.getQName();
597 final ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, builder,
598 utQName.getPrefix(), union.getLine());
600 if (dependentModuleBuilder == null) {
601 final Module dependentModule = findModuleFromContext(context, builder, utQName.getPrefix(),
603 Set<TypeDefinition<?>> types = dependentModule.getTypeDefinitions();
604 TypeDefinition<?> type = findTypeByName(types, utQName.getLocalName());
605 final TypeDefinitionBuilder newType = extendedTypeWithNewBaseType(type, extType, builder, 0);
607 union.setTypedef(newType);
608 toRemove.add(extType);
610 final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(union,
611 dependentModuleBuilder, utQName.getLocalName(), builder.getName(), union.getLine());
613 final TypeDefinitionBuilder newType = extendedTypeWithNewBaseTypeBuilder(targetTypeBuilder,
614 extType, modules, builder, union.getLine());
616 union.setTypedef(newType);
617 toRemove.add(extType);
622 unionTypes.removeAll(toRemove);
626 * Go through all augment definitions and resolve them. It is expected that
627 * modules are already sorted by their dependencies. This method also finds
628 * augment target node and add child nodes to it.
631 * all available modules
633 private void resolveAugments(final Map<String, TreeMap<Date, ModuleBuilder>> modules) {
634 final List<ModuleBuilder> allModulesList = new ArrayList<ModuleBuilder>();
635 final Set<ModuleBuilder> allModulesSet = new HashSet<ModuleBuilder>();
636 for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
637 for (Map.Entry<Date, ModuleBuilder> inner : entry.getValue().entrySet()) {
638 allModulesList.add(inner.getValue());
639 allModulesSet.add(inner.getValue());
643 for (int i = 0; i < allModulesList.size(); i++) {
644 final ModuleBuilder module = allModulesList.get(i);
645 // try to resolve augments in module
646 resolveAugment(modules, module);
647 // while all augments are not resolved
648 final Iterator<ModuleBuilder> allModulesIterator = allModulesSet.iterator();
649 while (!(module.getAugmentsResolved() == module.getAllAugments().size())) {
650 ModuleBuilder nextModule = null;
651 // try resolve other module augments
653 nextModule = allModulesIterator.next();
654 resolveAugment(modules, nextModule);
655 } catch (NoSuchElementException e) {
656 throw new YangParseException("Failed to resolve augments in module '" + module.getName() + "'.", e);
658 // then try to resolve first module again
659 resolveAugment(modules, module);
665 * Tries to resolve augments in given module. If augment target node is not
669 * all available modules
673 private void resolveAugment(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
674 if (module.getAugmentsResolved() < module.getAllAugments().size()) {
675 for (AugmentationSchemaBuilder augmentBuilder : module.getAllAugments()) {
677 if (!augmentBuilder.isResolved()) {
678 final SchemaPath augmentTargetSchemaPath = augmentBuilder.getTargetPath();
679 final List<QName> path = augmentTargetSchemaPath.getPath();
681 final QName qname = path.get(0);
682 String prefix = qname.getPrefix();
683 if (prefix == null) {
684 prefix = module.getPrefix();
687 final ModuleBuilder dependentModule = findDependentModuleBuilder(modules, module, prefix,
688 augmentBuilder.getLine());
689 processAugmentation(augmentBuilder, path, module, dependentModule);
697 * Go through all augment definitions and resolve them. This method works in
698 * same way as {@link #resolveAugments(Map)} except that if target node is
699 * not found in loaded modules, it search for target node in given context.
704 * SchemaContext containing already resolved modules
706 private void resolveAugmentsWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
707 final SchemaContext context) {
708 final List<ModuleBuilder> allModulesList = new ArrayList<ModuleBuilder>();
709 final Set<ModuleBuilder> allModulesSet = new HashSet<ModuleBuilder>();
710 for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
711 for (Map.Entry<Date, ModuleBuilder> inner : entry.getValue().entrySet()) {
712 allModulesList.add(inner.getValue());
713 allModulesSet.add(inner.getValue());
717 for (int i = 0; i < allModulesList.size(); i++) {
718 final ModuleBuilder module = allModulesList.get(i);
719 // try to resolve augments in module
720 resolveAugmentWithContext(modules, module, context);
721 // while all augments are not resolved
722 final Iterator<ModuleBuilder> allModulesIterator = allModulesSet.iterator();
723 while (!(module.getAugmentsResolved() == module.getAllAugments().size())) {
724 ModuleBuilder nextModule = null;
725 // try resolve other module augments
727 nextModule = allModulesIterator.next();
728 resolveAugmentWithContext(modules, nextModule, context);
729 } catch (NoSuchElementException e) {
730 throw new YangParseException("Failed to resolve augments in module '" + module.getName() + "'.", e);
732 // then try to resolve first module again
733 resolveAugmentWithContext(modules, module, context);
739 * Tries to resolve augments in given module. If augment target node is not
743 * all available modules
747 private void resolveAugmentWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
748 final ModuleBuilder module, final SchemaContext context) {
749 if (module.getAugmentsResolved() < module.getAllAugments().size()) {
751 for (AugmentationSchemaBuilder augmentBuilder : module.getAllAugments()) {
752 final int line = augmentBuilder.getLine();
754 if (!augmentBuilder.isResolved()) {
755 final List<QName> path = augmentBuilder.getTargetPath().getPath();
756 final QName qname = path.get(0);
757 String prefix = qname.getPrefix();
758 if (prefix == null) {
759 prefix = module.getPrefix();
762 // try to find augment target module in loaded modules...
763 final ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module, prefix,
765 if (dependentModuleBuilder == null) {
766 // perform augmentation on module from context and
767 // continue to next augment
768 processAugmentationOnContext(augmentBuilder, path, module, prefix, line, context);
771 processAugmentation(augmentBuilder, path, module, dependentModuleBuilder);
780 * Go through identity statements defined in current module and resolve
781 * their 'base' statement if present.
786 * module being resolved
788 private void resolveIdentities(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
789 final Set<IdentitySchemaNodeBuilder> identities = module.getIdentities();
790 for (IdentitySchemaNodeBuilder identity : identities) {
791 final String baseIdentityName = identity.getBaseIdentityName();
792 if (baseIdentityName != null) {
793 String baseIdentityPrefix = null;
794 String baseIdentityLocalName = null;
795 if (baseIdentityName.contains(":")) {
796 final String[] splitted = baseIdentityName.split(":");
797 baseIdentityPrefix = splitted[0];
798 baseIdentityLocalName = splitted[1];
800 baseIdentityPrefix = module.getPrefix();
801 baseIdentityLocalName = baseIdentityName;
803 final ModuleBuilder dependentModule = findDependentModuleBuilder(modules, module, baseIdentityPrefix,
806 final Set<IdentitySchemaNodeBuilder> dependentModuleIdentities = dependentModule.getIdentities();
807 for (IdentitySchemaNodeBuilder idBuilder : dependentModuleIdentities) {
808 if (idBuilder.getQName().getLocalName().equals(baseIdentityLocalName)) {
809 identity.setBaseIdentity(idBuilder);
817 * Go through identity statements defined in current module and resolve
818 * their 'base' statement. Method tries to find base identity in given
819 * modules. If base identity is not found, method will search it in context.
826 * SchemaContext containing already resolved modules
828 private void resolveIdentitiesWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
829 final ModuleBuilder module, final SchemaContext context) {
830 final Set<IdentitySchemaNodeBuilder> identities = module.getIdentities();
831 for (IdentitySchemaNodeBuilder identity : identities) {
832 final String baseIdentityName = identity.getBaseIdentityName();
833 if (baseIdentityName != null) {
834 String baseIdentityPrefix = null;
835 String baseIdentityLocalName = null;
836 if (baseIdentityName.contains(":")) {
837 final String[] splitted = baseIdentityName.split(":");
838 baseIdentityPrefix = splitted[0];
839 baseIdentityLocalName = splitted[1];
841 baseIdentityPrefix = module.getPrefix();
842 baseIdentityLocalName = baseIdentityName;
844 final ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module,
845 baseIdentityPrefix, identity.getLine());
847 if (dependentModuleBuilder == null) {
848 final Module dependentModule = findModuleFromContext(context, module, baseIdentityPrefix,
850 final Set<IdentitySchemaNode> dependentModuleIdentities = dependentModule.getIdentities();
851 for (IdentitySchemaNode idNode : dependentModuleIdentities) {
852 if (idNode.getQName().getLocalName().equals(baseIdentityLocalName)) {
853 identity.setBaseIdentity(idNode);
857 final Set<IdentitySchemaNodeBuilder> dependentModuleIdentities = dependentModuleBuilder
859 for (IdentitySchemaNodeBuilder idBuilder : dependentModuleIdentities) {
860 if (idBuilder.getQName().getLocalName().equals(baseIdentityLocalName)) {
861 identity.setBaseIdentity(idBuilder);
870 * Go through uses statements defined in current module and resolve their
876 * module being resolved
878 private void resolveUsesRefine(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
879 final List<UsesNodeBuilder> allModuleUses = module.getAllUsesNodes();
880 for (UsesNodeBuilder usesNode : allModuleUses) {
882 final int line = usesNode.getLine();
883 final GroupingBuilder targetGrouping = getTargetGroupingFromModules(usesNode, modules, module);
884 usesNode.setGroupingPath(targetGrouping.getPath());
885 for (RefineHolder refine : usesNode.getRefines()) {
886 final SchemaNodeBuilder nodeToRefine = RefineUtils.getRefineNodeFromGroupingBuilder(targetGrouping,
887 refine, module.getName());
888 if (nodeToRefine instanceof GroupingMember) {
889 ((GroupingMember) nodeToRefine).setAddedByUses(true);
891 RefineUtils.performRefine(nodeToRefine, refine, line);
892 usesNode.addRefineNode(nodeToRefine);
896 processUsesNode(usesNode, targetGrouping);
901 * Tries to search target grouping in given modules and resolve refine
902 * nodes. If grouping is not found in modules, method tries to find it in
903 * modules from context.
910 * SchemaContext containing already resolved modules
912 private void resolveUsesRefineWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
913 final ModuleBuilder module, final SchemaContext context) {
914 final List<UsesNodeBuilder> moduleUses = module.getAllUsesNodes();
915 for (UsesNodeBuilder usesNode : moduleUses) {
916 final int line = usesNode.getLine();
918 final GroupingBuilder targetGroupingBuilder = getTargetGroupingFromModules(usesNode, modules, module);
919 if (targetGroupingBuilder == null) {
920 final GroupingDefinition targetGrouping = getTargetGroupingFromContext(usesNode, module, context);
921 usesNode.setGroupingPath(targetGrouping.getPath());
922 for (RefineHolder refine : usesNode.getRefines()) {
923 final SchemaNodeBuilder nodeToRefine = RefineUtils.getRefineNodeFromGroupingDefinition(
924 targetGrouping, refine, module.getName());
925 if (nodeToRefine instanceof GroupingMember) {
926 ((GroupingMember) nodeToRefine).setAddedByUses(true);
928 RefineUtils.performRefine(nodeToRefine, refine, line);
929 usesNode.addRefineNode(nodeToRefine);
932 processUsesNode(usesNode, targetGrouping);
934 usesNode.setGroupingPath(targetGroupingBuilder.getPath());
935 for (RefineHolder refine : usesNode.getRefines()) {
936 final SchemaNodeBuilder nodeToRefine = RefineUtils.getRefineNodeFromGroupingBuilder(
937 targetGroupingBuilder, refine, module.getName());
938 if (nodeToRefine instanceof GroupingMember) {
939 ((GroupingMember) nodeToRefine).setAddedByUses(true);
941 RefineUtils.performRefine(nodeToRefine, refine, line);
942 usesNode.addRefineNode(nodeToRefine);
945 processUsesNode(usesNode, targetGroupingBuilder);
951 * Search given modules for grouping by name defined in uses node.
954 * builder of uses statement
959 * @return grouping with given name if found, null otherwise
961 private GroupingBuilder getTargetGroupingFromModules(final UsesNodeBuilder usesBuilder,
962 final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
963 final int line = usesBuilder.getLine();
964 final String groupingString = usesBuilder.getGroupingName();
965 String groupingPrefix;
968 if (groupingString.contains(":")) {
969 String[] splitted = groupingString.split(":");
970 if (splitted.length != 2 || groupingString.contains("/")) {
971 throw new YangParseException(module.getName(), line, "Invalid name of target grouping");
973 groupingPrefix = splitted[0];
974 groupingName = splitted[1];
976 groupingPrefix = module.getPrefix();
977 groupingName = groupingString;
980 ModuleBuilder dependentModule = null;
981 if (groupingPrefix.equals(module.getPrefix())) {
982 dependentModule = module;
984 dependentModule = findDependentModuleBuilder(modules, module, groupingPrefix, line);
987 if (dependentModule == null) {
991 GroupingBuilder result = null;
992 Set<GroupingBuilder> groupings = dependentModule.getGroupingBuilders();
993 result = findGroupingBuilder(groupings, groupingName);
994 if (result != null) {
998 Builder parent = usesBuilder.getParent();
1000 while (parent != null) {
1001 if (parent instanceof DataNodeContainerBuilder) {
1002 groupings = ((DataNodeContainerBuilder) parent).getGroupingBuilders();
1003 } else if (parent instanceof RpcDefinitionBuilder) {
1004 groupings = ((RpcDefinitionBuilder) parent).getGroupings();
1006 result = findGroupingBuilder(groupings, groupingName);
1007 if (result == null) {
1008 parent = parent.getParent();
1014 if (result == null) {
1015 throw new YangParseException(module.getName(), line, "Referenced grouping '" + groupingName
1022 * Search context for grouping by name defined in uses node.
1024 * @param usesBuilder
1025 * builder of uses statement
1029 * SchemaContext containing already resolved modules
1030 * @return grouping with given name if found, null otherwise
1032 private GroupingDefinition getTargetGroupingFromContext(final UsesNodeBuilder usesBuilder,
1033 final ModuleBuilder module, final SchemaContext context) {
1034 final int line = usesBuilder.getLine();
1035 String groupingString = usesBuilder.getGroupingName();
1036 String groupingPrefix;
1037 String groupingName;
1039 if (groupingString.contains(":")) {
1040 String[] splitted = groupingString.split(":");
1041 if (splitted.length != 2 || groupingString.contains("/")) {
1042 throw new YangParseException(module.getName(), line, "Invalid name of target grouping");
1044 groupingPrefix = splitted[0];
1045 groupingName = splitted[1];
1047 groupingPrefix = module.getPrefix();
1048 groupingName = groupingString;
1051 Module dependentModule = findModuleFromContext(context, module, groupingPrefix, line);
1052 return findGroupingDefinition(dependentModule.getGroupings(), groupingName);
1056 * Add nodes defined in target grouping to current context.
1059 * @param targetGrouping
1061 private void processUsesNode(final UsesNodeBuilder usesNode, final GroupingBuilder targetGrouping) {
1062 List<SchemaNodeBuilder> refineNodes = usesNode.getRefineNodes();
1063 DataNodeContainerBuilder parent = usesNode.getParent();
1064 SchemaPath parentPath = parent.getPath();
1065 for (DataSchemaNodeBuilder child : targetGrouping.getChildNodeBuilders()) {
1066 if (child != null) {
1067 // if node is refined, take it from refined nodes and continue
1068 SchemaNodeBuilder refined = getRefined(child.getQName(), refineNodes);
1069 if (refined != null) {
1070 refined.setPath(createSchemaPath(parentPath, refined.getQName().getLocalName()));
1071 parent.addChildNode((DataSchemaNodeBuilder) refined);
1075 DataSchemaNodeBuilder newChild = null;
1076 if (child instanceof AnyXmlBuilder) {
1077 newChild = new AnyXmlBuilder((AnyXmlBuilder) child);
1078 } else if (child instanceof ChoiceBuilder) {
1079 newChild = new ChoiceBuilder((ChoiceBuilder) child);
1080 } else if (child instanceof ContainerSchemaNodeBuilder) {
1081 newChild = new ContainerSchemaNodeBuilder((ContainerSchemaNodeBuilder) child);
1082 } else if (child instanceof LeafListSchemaNodeBuilder) {
1083 newChild = new LeafListSchemaNodeBuilder((LeafListSchemaNodeBuilder) child);
1084 } else if (child instanceof LeafSchemaNodeBuilder) {
1085 newChild = new LeafSchemaNodeBuilder((LeafSchemaNodeBuilder) child);
1086 } else if (child instanceof ListSchemaNodeBuilder) {
1087 newChild = new ListSchemaNodeBuilder((ListSchemaNodeBuilder) child);
1090 if (newChild == null) {
1091 throw new YangParseException(usesNode.getLine(),
1092 "Unknown member of target grouping while resolving uses node.");
1095 if (newChild instanceof GroupingMember) {
1096 ((GroupingMember) newChild).setAddedByUses(true);
1099 newChild.setPath(createSchemaPath(parentPath, newChild.getQName().getLocalName()));
1100 parent.addChildNode(newChild);
1103 for (GroupingBuilder g : targetGrouping.getGroupingBuilders()) {
1104 GroupingBuilder newGrouping = new GroupingBuilderImpl(g);
1105 newGrouping.setAddedByUses(true);
1106 newGrouping.setPath(createSchemaPath(parentPath, newGrouping.getQName().getLocalName()));
1107 parent.addGrouping(newGrouping);
1109 for (TypeDefinitionBuilder td : targetGrouping.getTypeDefinitionBuilders()) {
1110 TypeDefinitionBuilder newType = new TypeDefinitionBuilderImpl(td);
1111 newType.setAddedByUses(true);
1112 newType.setPath(createSchemaPath(parentPath, newType.getQName().getLocalName()));
1113 parent.addTypedef(newType);
1115 for (UsesNodeBuilder un : targetGrouping.getUses()) {
1116 UsesNodeBuilder newUses = new UsesNodeBuilderImpl(un);
1117 newUses.setAddedByUses(true);
1118 // uses has not path
1119 parent.addUsesNode(newUses);
1121 for (UnknownSchemaNodeBuilder un : targetGrouping.getUnknownNodes()) {
1122 UnknownSchemaNodeBuilder newUn = new UnknownSchemaNodeBuilder(un);
1123 newUn.setAddedByUses(true);
1124 newUn.setPath(createSchemaPath(parentPath, un.getQName().getLocalName()));
1125 parent.addUnknownSchemaNode(newUn);
1129 private void processUsesNode(final UsesNodeBuilder usesNode, final GroupingDefinition targetGrouping) {
1130 final int line = usesNode.getLine();
1131 List<SchemaNodeBuilder> refineNodes = usesNode.getRefineNodes();
1132 DataNodeContainerBuilder parent = usesNode.getParent();
1133 SchemaPath parentPath = parent.getPath();
1134 for (DataSchemaNode child : targetGrouping.getChildNodes()) {
1135 if (child != null) {
1136 // if node is refined, take it from refined nodes and continue
1137 SchemaNodeBuilder refined = getRefined(child.getQName(), refineNodes);
1138 if (refined != null) {
1139 refined.setPath(createSchemaPath(parentPath, refined.getQName().getLocalName()));
1140 parent.addChildNode((DataSchemaNodeBuilder) refined);
1144 DataSchemaNodeBuilder newChild = null;
1145 if (child instanceof AnyXmlSchemaNode) {
1146 newChild = createAnyXml((AnyXmlSchemaNode) child, line);
1147 } else if (child instanceof ChoiceNode) {
1148 newChild = createChoice((ChoiceNode) child, line);
1149 } else if (child instanceof ContainerSchemaNode) {
1150 newChild = createContainer((ContainerSchemaNode) child, line);
1151 } else if (child instanceof LeafListSchemaNode) {
1152 newChild = createLeafList((LeafListSchemaNode) child, line);
1153 } else if (child instanceof LeafSchemaNode) {
1154 newChild = createLeafBuilder((LeafSchemaNode) child, line);
1155 } else if (child instanceof ListSchemaNode) {
1156 newChild = createList((ListSchemaNode) child, line);
1159 if (newChild == null) {
1160 throw new YangParseException(usesNode.getLine(),
1161 "Unknown member of target grouping while resolving uses node.");
1164 if (newChild instanceof GroupingMember) {
1165 ((GroupingMember) newChild).setAddedByUses(true);
1167 newChild.setPath(createSchemaPath(parentPath, newChild.getQName().getLocalName()));
1168 parent.addChildNode(newChild);
1171 for (GroupingDefinition g : targetGrouping.getGroupings()) {
1172 GroupingBuilder newGrouping = createGrouping(g, line);
1173 newGrouping.setAddedByUses(true);
1174 newGrouping.setPath(createSchemaPath(parentPath, newGrouping.getQName().getLocalName()));
1175 parent.addGrouping(newGrouping);
1177 for (TypeDefinition<?> td : targetGrouping.getTypeDefinitions()) {
1178 TypeDefinitionBuilder newType = createTypedef((ExtendedType) td, line);
1179 newType.setAddedByUses(true);
1180 newType.setPath(createSchemaPath(parentPath, newType.getQName().getLocalName()));
1181 parent.addTypedef(newType);
1183 for (UsesNode un : targetGrouping.getUses()) {
1184 if (un instanceof UsesNodeImpl) {
1185 UsesNodeBuilder newUses = new UsesNodeBuilderImpl(((UsesNodeImpl) un).toBuilder());
1186 newUses.setAddedByUses(true);
1187 // uses has not path
1188 parent.addUsesNode(newUses);
1191 for (UnknownSchemaNode un : targetGrouping.getUnknownSchemaNodes()) {
1192 UnknownSchemaNodeBuilder newNode = createUnknownSchemaNode(un, line);
1193 newNode.setAddedByUses(true);
1194 newNode.setPath(createSchemaPath(parentPath, un.getQName().getLocalName()));
1195 parent.addUnknownSchemaNode(newNode);
1199 private QName findFullQName(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module,
1200 final IdentityrefTypeBuilder idref) {
1201 QName result = null;
1202 String baseString = idref.getBaseString();
1203 if (baseString.contains(":")) {
1204 String[] splittedBase = baseString.split(":");
1205 if (splittedBase.length > 2) {
1206 throw new YangParseException(module.getName(), idref.getLine(), "Failed to parse identityref base: "
1209 String prefix = splittedBase[0];
1210 String name = splittedBase[1];
1211 ModuleBuilder dependentModule = findDependentModuleBuilder(modules, module, prefix, idref.getLine());
1212 result = new QName(dependentModule.getNamespace(), dependentModule.getRevision(), prefix, name);
1214 result = new QName(module.getNamespace(), module.getRevision(), module.getPrefix(), baseString);
1219 private void resolveUnknownNodes(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
1220 for (UnknownSchemaNodeBuilder usnb : module.getAllUnknownNodes()) {
1221 QName nodeType = usnb.getNodeType();
1222 if (nodeType.getNamespace() == null || nodeType.getRevision() == null) {
1224 ModuleBuilder dependentModule = findDependentModuleBuilder(modules, module, nodeType.getPrefix(),
1226 QName newNodeType = new QName(dependentModule.getNamespace(), dependentModule.getRevision(),
1227 nodeType.getPrefix(), nodeType.getLocalName());
1228 usnb.setNodeType(newNodeType);
1229 } catch (YangParseException e) {
1230 logger.debug(module.getName(), usnb.getLine(), "Failed to find unknown node type: " + nodeType);
1236 private void resolveUnknownNodesWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
1237 final ModuleBuilder module, final SchemaContext context) {
1238 for (UnknownSchemaNodeBuilder unknownNodeBuilder : module.getAllUnknownNodes()) {
1239 QName nodeType = unknownNodeBuilder.getNodeType();
1240 if (nodeType.getNamespace() == null || nodeType.getRevision() == null) {
1242 ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module,
1243 nodeType.getPrefix(), unknownNodeBuilder.getLine());
1245 QName newNodeType = null;
1246 if (dependentModuleBuilder == null) {
1247 Module dependentModule = findModuleFromContext(context, module, nodeType.getPrefix(),
1248 unknownNodeBuilder.getLine());
1249 newNodeType = new QName(dependentModule.getNamespace(), dependentModule.getRevision(),
1250 nodeType.getPrefix(), nodeType.getLocalName());
1252 newNodeType = new QName(dependentModuleBuilder.getNamespace(),
1253 dependentModuleBuilder.getRevision(), nodeType.getPrefix(), nodeType.getLocalName());
1256 unknownNodeBuilder.setNodeType(newNodeType);
1257 } catch (YangParseException e) {
1258 logger.debug(module.getName(), unknownNodeBuilder.getLine(), "Failed to find unknown node type: "
1265 private void resolveDeviations(final Map<String, TreeMap<Date, ModuleBuilder>> modules) {
1266 for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
1267 for (Map.Entry<Date, ModuleBuilder> inner : entry.getValue().entrySet()) {
1268 ModuleBuilder b = inner.getValue();
1269 resolveDeviation(modules, b);
1274 private void resolveDeviation(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
1275 for (DeviationBuilder dev : module.getDeviations()) {
1276 int line = dev.getLine();
1277 SchemaPath targetPath = dev.getTargetPath();
1278 List<QName> path = targetPath.getPath();
1279 QName q0 = path.get(0);
1280 String prefix = q0.getPrefix();
1281 if (prefix == null) {
1282 prefix = module.getPrefix();
1285 ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module, prefix, line);
1286 processDeviation(dev, dependentModuleBuilder, path, module);
1290 private void resolveDeviationsWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
1291 final SchemaContext context) {
1292 for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
1293 for (Map.Entry<Date, ModuleBuilder> inner : entry.getValue().entrySet()) {
1294 ModuleBuilder b = inner.getValue();
1295 resolveDeviationWithContext(modules, b, context);
1300 private void resolveDeviationWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
1301 final ModuleBuilder module, final SchemaContext context) {
1302 for (DeviationBuilder dev : module.getDeviations()) {
1303 int line = dev.getLine();
1304 SchemaPath targetPath = dev.getTargetPath();
1305 List<QName> path = targetPath.getPath();
1306 QName q0 = path.get(0);
1307 String prefix = q0.getPrefix();
1308 if (prefix == null) {
1309 prefix = module.getPrefix();
1313 ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module, prefix, line);
1314 if (dependentModuleBuilder == null) {
1315 Module dependentModule = findModuleFromContext(context, module, prefix, line);
1316 Object currentParent = dependentModule;
1318 for (int i = 0; i < path.size(); i++) {
1319 if (currentParent == null) {
1320 throw new YangParseException(module.getName(), line, "Failed to find deviation target.");
1322 QName q = path.get(i);
1323 name = q.getLocalName();
1324 if (currentParent instanceof DataNodeContainer) {
1325 currentParent = ((DataNodeContainer) currentParent).getDataChildByName(name);
1329 if (currentParent == null) {
1330 throw new YangParseException(module.getName(), line, "Failed to find deviation target.");
1332 if (currentParent instanceof SchemaNode) {
1333 dev.setTargetPath(((SchemaNode) currentParent).getPath());
1337 processDeviation(dev, dependentModuleBuilder, path, module);
1343 * Correct deviation target path in deviation builder.
1347 * @param dependentModuleBuilder
1348 * module containing deviation target
1350 * current deviation target path
1354 private void processDeviation(final DeviationBuilder dev, final ModuleBuilder dependentModuleBuilder,
1355 final List<QName> path, final ModuleBuilder module) {
1356 final int line = dev.getLine();
1357 Builder currentParent = dependentModuleBuilder;
1359 for (int i = 0; i < path.size(); i++) {
1360 if (currentParent == null) {
1361 throw new YangParseException(module.getName(), line, "Failed to find deviation target.");
1363 QName q = path.get(i);
1364 String name = q.getLocalName();
1365 if (currentParent instanceof DataNodeContainerBuilder) {
1366 currentParent = ((DataNodeContainerBuilder) currentParent).getDataChildByName(name);
1370 if (currentParent == null || !(currentParent instanceof SchemaNodeBuilder)) {
1371 throw new YangParseException(module.getName(), line, "Failed to find deviation target.");
1373 dev.setTargetPath(((SchemaNodeBuilder) currentParent).getPath());