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;
18 import java.util.ArrayList;
19 import java.util.Collections;
20 import java.util.Date;
21 import java.util.HashMap;
22 import java.util.HashSet;
23 import java.util.Iterator;
24 import java.util.LinkedHashMap;
25 import java.util.LinkedHashSet;
26 import java.util.List;
28 import java.util.Map.Entry;
29 import java.util.NoSuchElementException;
31 import java.util.TreeMap;
33 import org.antlr.v4.runtime.ANTLRInputStream;
34 import org.antlr.v4.runtime.CommonTokenStream;
35 import org.antlr.v4.runtime.tree.ParseTree;
36 import org.antlr.v4.runtime.tree.ParseTreeWalker;
37 import org.opendaylight.controller.antlrv4.code.gen.YangLexer;
38 import org.opendaylight.controller.antlrv4.code.gen.YangParser;
39 import org.opendaylight.controller.yang.common.QName;
40 import org.opendaylight.controller.yang.model.api.AnyXmlSchemaNode;
41 import org.opendaylight.controller.yang.model.api.ChoiceNode;
42 import org.opendaylight.controller.yang.model.api.ContainerSchemaNode;
43 import org.opendaylight.controller.yang.model.api.DataNodeContainer;
44 import org.opendaylight.controller.yang.model.api.DataSchemaNode;
45 import org.opendaylight.controller.yang.model.api.GroupingDefinition;
46 import org.opendaylight.controller.yang.model.api.IdentitySchemaNode;
47 import org.opendaylight.controller.yang.model.api.LeafListSchemaNode;
48 import org.opendaylight.controller.yang.model.api.LeafSchemaNode;
49 import org.opendaylight.controller.yang.model.api.ListSchemaNode;
50 import org.opendaylight.controller.yang.model.api.Module;
51 import org.opendaylight.controller.yang.model.api.SchemaContext;
52 import org.opendaylight.controller.yang.model.api.SchemaNode;
53 import org.opendaylight.controller.yang.model.api.SchemaPath;
54 import org.opendaylight.controller.yang.model.api.TypeDefinition;
55 import org.opendaylight.controller.yang.model.api.UnknownSchemaNode;
56 import org.opendaylight.controller.yang.model.api.UsesNode;
57 import org.opendaylight.controller.yang.model.parser.api.YangModelParser;
58 import org.opendaylight.controller.yang.model.util.ExtendedType;
59 import org.opendaylight.controller.yang.model.util.IdentityrefType;
60 import org.opendaylight.controller.yang.model.util.UnknownType;
61 import org.opendaylight.controller.yang.parser.builder.api.AugmentationSchemaBuilder;
62 import org.opendaylight.controller.yang.parser.builder.api.Builder;
63 import org.opendaylight.controller.yang.parser.builder.api.DataNodeContainerBuilder;
64 import org.opendaylight.controller.yang.parser.builder.api.DataSchemaNodeBuilder;
65 import org.opendaylight.controller.yang.parser.builder.api.GroupingBuilder;
66 import org.opendaylight.controller.yang.parser.builder.api.GroupingMember;
67 import org.opendaylight.controller.yang.parser.builder.api.SchemaNodeBuilder;
68 import org.opendaylight.controller.yang.parser.builder.api.TypeAwareBuilder;
69 import org.opendaylight.controller.yang.parser.builder.api.TypeDefinitionBuilder;
70 import org.opendaylight.controller.yang.parser.builder.api.UsesNodeBuilder;
71 import org.opendaylight.controller.yang.parser.builder.impl.AnyXmlBuilder;
72 import org.opendaylight.controller.yang.parser.builder.impl.ChoiceBuilder;
73 import org.opendaylight.controller.yang.parser.builder.impl.ContainerSchemaNodeBuilder;
74 import org.opendaylight.controller.yang.parser.builder.impl.DeviationBuilder;
75 import org.opendaylight.controller.yang.parser.builder.impl.GroupingBuilderImpl;
76 import org.opendaylight.controller.yang.parser.builder.impl.IdentitySchemaNodeBuilder;
77 import org.opendaylight.controller.yang.parser.builder.impl.IdentityrefTypeBuilder;
78 import org.opendaylight.controller.yang.parser.builder.impl.LeafListSchemaNodeBuilder;
79 import org.opendaylight.controller.yang.parser.builder.impl.LeafSchemaNodeBuilder;
80 import org.opendaylight.controller.yang.parser.builder.impl.ListSchemaNodeBuilder;
81 import org.opendaylight.controller.yang.parser.builder.impl.ModuleBuilder;
82 import org.opendaylight.controller.yang.parser.builder.impl.RpcDefinitionBuilder;
83 import org.opendaylight.controller.yang.parser.builder.impl.TypeDefinitionBuilderImpl;
84 import org.opendaylight.controller.yang.parser.builder.impl.UnionTypeBuilder;
85 import org.opendaylight.controller.yang.parser.builder.impl.UnknownSchemaNodeBuilder;
86 import org.opendaylight.controller.yang.parser.builder.impl.UsesNodeBuilderImpl;
87 import org.opendaylight.controller.yang.parser.builder.impl.UsesNodeBuilderImpl.UsesNodeImpl;
88 import org.opendaylight.controller.yang.parser.util.ModuleDependencySort;
89 import org.opendaylight.controller.yang.parser.util.RefineHolder;
90 import org.opendaylight.controller.yang.parser.util.RefineUtils;
91 import org.opendaylight.controller.yang.parser.util.TypeConstraints;
92 import org.opendaylight.controller.yang.parser.util.YangParseException;
93 import org.opendaylight.controller.yang.validator.YangModelBasicValidator;
94 import org.slf4j.Logger;
95 import org.slf4j.LoggerFactory;
97 import com.google.common.collect.Lists;
98 import com.google.common.collect.Maps;
99 import com.google.common.collect.Sets;
101 public final class YangParserImpl implements YangModelParser {
102 private static final Logger LOG = LoggerFactory.getLogger(YangParserImpl.class);
105 public Set<Module> parseYangModels(final List<File> yangFiles) {
106 return Sets.newLinkedHashSet(parseYangModelsMapped(yangFiles).values());
110 public Set<Module> parseYangModels(final List<File> yangFiles, final SchemaContext context) {
111 if (yangFiles != null) {
112 final Map<InputStream, File> inputStreams = Maps.newHashMap();
114 for (final File yangFile : yangFiles) {
116 inputStreams.put(new FileInputStream(yangFile), yangFile);
117 } catch (FileNotFoundException e) {
118 LOG.warn("Exception while reading yang file: " + yangFile.getName(), e);
122 Map<ModuleBuilder, InputStream> builderToStreamMap = Maps.newHashMap();
124 final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuilders(
125 Lists.newArrayList(inputStreams.keySet()), builderToStreamMap);
127 for (InputStream is : inputStreams.keySet()) {
130 } catch (IOException e) {
131 LOG.debug("Failed to close stream.");
135 return new LinkedHashSet<Module>(buildWithContext(modules, context).values());
137 return Collections.emptySet();
141 public Set<Module> parseYangModelsFromStreams(final List<InputStream> yangModelStreams) {
142 return Sets.newHashSet(parseYangModelsFromStreamsMapped(yangModelStreams).values());
146 public Set<Module> parseYangModelsFromStreams(final List<InputStream> yangModelStreams, SchemaContext context) {
147 if (yangModelStreams != null) {
148 Map<ModuleBuilder, InputStream> builderToStreamMap = Maps.newHashMap();
149 final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuildersWithContext(
150 yangModelStreams, builderToStreamMap, context);
151 return new LinkedHashSet<Module>(buildWithContext(modules, context).values());
153 return Collections.emptySet();
157 public Map<File, Module> parseYangModelsMapped(List<File> yangFiles) {
158 if (yangFiles != null) {
159 final Map<InputStream, File> inputStreams = Maps.newHashMap();
161 for (final File yangFile : yangFiles) {
163 inputStreams.put(new FileInputStream(yangFile), yangFile);
164 } catch (FileNotFoundException e) {
165 LOG.warn("Exception while reading yang file: " + yangFile.getName(), e);
169 Map<ModuleBuilder, InputStream> builderToStreamMap = Maps.newHashMap();
170 final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuilders(
171 Lists.newArrayList(inputStreams.keySet()), builderToStreamMap);
173 for (InputStream is : inputStreams.keySet()) {
176 } catch (IOException e) {
177 LOG.debug("Failed to close stream.");
181 Map<File, Module> retVal = Maps.newLinkedHashMap();
182 Map<ModuleBuilder, Module> builderToModuleMap = build(modules);
184 for (Entry<ModuleBuilder, Module> builderToModule : builderToModuleMap.entrySet()) {
185 retVal.put(inputStreams.get(builderToStreamMap.get(builderToModule.getKey())),
186 builderToModule.getValue());
191 return Collections.emptyMap();
195 public Map<InputStream, Module> parseYangModelsFromStreamsMapped(final List<InputStream> yangModelStreams) {
196 Map<ModuleBuilder, InputStream> builderToStreamMap = Maps.newHashMap();
198 final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuilders(yangModelStreams,
200 Map<InputStream, Module> retVal = Maps.newLinkedHashMap();
201 Map<ModuleBuilder, Module> builderToModuleMap = build(modules);
203 for (Entry<ModuleBuilder, Module> builderToModule : builderToModuleMap.entrySet()) {
204 retVal.put(builderToStreamMap.get(builderToModule.getKey()), builderToModule.getValue());
210 public SchemaContext resolveSchemaContext(final Set<Module> modules) {
211 return new SchemaContextImpl(modules);
214 private ModuleBuilder[] parseModuleBuilders(List<InputStream> inputStreams,
215 Map<ModuleBuilder, InputStream> streamToBuilderMap) {
217 final ParseTreeWalker walker = new ParseTreeWalker();
218 final List<ParseTree> trees = parseStreams(inputStreams);
219 final ModuleBuilder[] builders = new ModuleBuilder[trees.size()];
222 new YangModelBasicValidator(walker).validate(trees);
224 YangParserListenerImpl yangModelParser = null;
225 for (int i = 0; i < trees.size(); i++) {
226 yangModelParser = new YangParserListenerImpl();
227 walker.walk(yangModelParser, trees.get(i));
228 ModuleBuilder moduleBuilder = yangModelParser.getModuleBuilder();
230 // We expect the order of trees and streams has to be the same
231 streamToBuilderMap.put(moduleBuilder, inputStreams.get(i));
232 builders[i] = moduleBuilder;
237 private Map<String, TreeMap<Date, ModuleBuilder>> resolveModuleBuilders(final List<InputStream> yangFileStreams,
238 Map<ModuleBuilder, InputStream> streamToBuilderMap) {
239 return resolveModuleBuildersWithContext(yangFileStreams, streamToBuilderMap, null);
242 private Map<String, TreeMap<Date, ModuleBuilder>> resolveModuleBuildersWithContext(
243 final List<InputStream> yangFileStreams, final Map<ModuleBuilder, InputStream> streamToBuilderMap,
244 final SchemaContext context) {
245 final ModuleBuilder[] builders = parseModuleBuilders(yangFileStreams, streamToBuilderMap);
247 // Linked Hash Map MUST be used because Linked Hash Map preserves ORDER
248 // of items stored in map.
249 final LinkedHashMap<String, TreeMap<Date, ModuleBuilder>> modules = new LinkedHashMap<String, TreeMap<Date, ModuleBuilder>>();
251 // module dependency graph sorted
252 List<ModuleBuilder> sorted = null;
253 if (context == null) {
254 sorted = ModuleDependencySort.sort(builders);
256 sorted = ModuleDependencySort.sortWithContext(context, builders);
259 for (final ModuleBuilder builder : sorted) {
260 if (builder == null) {
263 final String builderName = builder.getName();
264 Date builderRevision = builder.getRevision();
265 if (builderRevision == null) {
266 builderRevision = new Date(0L);
268 TreeMap<Date, ModuleBuilder> builderByRevision = modules.get(builderName);
269 if (builderByRevision == null) {
270 builderByRevision = new TreeMap<Date, ModuleBuilder>();
272 builderByRevision.put(builderRevision, builder);
273 modules.put(builderName, builderByRevision);
278 private List<ParseTree> parseStreams(final List<InputStream> yangStreams) {
279 final List<ParseTree> trees = new ArrayList<ParseTree>();
280 for (InputStream yangStream : yangStreams) {
281 trees.add(parseStream(yangStream));
286 private ParseTree parseStream(final InputStream yangStream) {
287 ParseTree result = null;
289 final ANTLRInputStream input = new ANTLRInputStream(yangStream);
290 final YangLexer lexer = new YangLexer(input);
291 final CommonTokenStream tokens = new CommonTokenStream(lexer);
292 final YangParser parser = new YangParser(tokens);
293 parser.removeErrorListeners();
294 parser.addErrorListener(new YangErrorListener());
296 result = parser.yang();
297 } catch (IOException e) {
298 LOG.warn("Exception while reading yang file: " + yangStream, e);
303 private Map<ModuleBuilder, Module> build(final Map<String, TreeMap<Date, ModuleBuilder>> modules) {
304 // fix unresolved nodes
305 for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
306 for (Map.Entry<Date, ModuleBuilder> childEntry : entry.getValue().entrySet()) {
307 final ModuleBuilder moduleBuilder = childEntry.getValue();
308 fixUnresolvedNodes(modules, moduleBuilder);
311 resolveAugments(modules);
312 resolveDeviations(modules);
315 // LinkedHashMap MUST be used otherwise the values will not maintain
317 // http://docs.oracle.com/javase/6/docs/api/java/util/LinkedHashMap.html
318 final Map<ModuleBuilder, Module> result = new LinkedHashMap<ModuleBuilder, Module>();
319 for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
320 final Map<Date, Module> modulesByRevision = new HashMap<Date, Module>();
321 for (Map.Entry<Date, ModuleBuilder> childEntry : entry.getValue().entrySet()) {
322 final ModuleBuilder moduleBuilder = childEntry.getValue();
323 final Module module = moduleBuilder.build();
324 modulesByRevision.put(childEntry.getKey(), module);
325 result.put(moduleBuilder, module);
331 private Map<ModuleBuilder, Module> buildWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
332 SchemaContext context) {
333 // fix unresolved nodes
334 for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
335 for (Map.Entry<Date, ModuleBuilder> childEntry : entry.getValue().entrySet()) {
336 final ModuleBuilder moduleBuilder = childEntry.getValue();
337 fixUnresolvedNodesWithContext(modules, moduleBuilder, context);
340 resolveAugmentsWithContext(modules, context);
341 resolveDeviationsWithContext(modules, context);
344 // LinkedHashMap MUST be used otherwise the values will not maintain
346 // http://docs.oracle.com/javase/6/docs/api/java/util/LinkedHashMap.html
347 final Map<ModuleBuilder, Module> result = new LinkedHashMap<ModuleBuilder, Module>();
348 for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
349 final Map<Date, Module> modulesByRevision = new HashMap<Date, Module>();
350 for (Map.Entry<Date, ModuleBuilder> childEntry : entry.getValue().entrySet()) {
351 final ModuleBuilder moduleBuilder = childEntry.getValue();
352 final Module module = moduleBuilder.build();
353 modulesByRevision.put(childEntry.getKey(), module);
354 result.put(moduleBuilder, module);
360 private void fixUnresolvedNodes(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder builder) {
361 resolveDirtyNodes(modules, builder);
362 resolveIdentities(modules, builder);
363 resolveUsesRefine(modules, builder);
364 resolveUnknownNodes(modules, builder);
367 private void fixUnresolvedNodesWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
368 final ModuleBuilder builder, final SchemaContext context) {
369 resolveDirtyNodesWithContext(modules, builder, context);
370 resolveIdentitiesWithContext(modules, builder, context);
371 resolveUsesRefineWithContext(modules, builder, context);
372 resolveUnknownNodesWithContext(modules, builder, context);
376 * Search for dirty nodes (node which contains UnknownType) and resolve
380 * all available modules
384 private void resolveDirtyNodes(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
385 final Set<TypeAwareBuilder> dirtyNodes = module.getDirtyNodes();
386 if (!dirtyNodes.isEmpty()) {
387 for (TypeAwareBuilder nodeToResolve : dirtyNodes) {
388 if (nodeToResolve instanceof UnionTypeBuilder) {
389 // special handling for union types
390 resolveTypeUnion((UnionTypeBuilder) nodeToResolve, modules, module);
391 } else if (nodeToResolve.getTypedef() instanceof IdentityrefTypeBuilder) {
392 // special handling for identityref types
393 IdentityrefTypeBuilder idref = (IdentityrefTypeBuilder) nodeToResolve.getTypedef();
394 nodeToResolve.setType(new IdentityrefType(findFullQName(modules, module, idref), idref.getPath()));
396 resolveType(nodeToResolve, modules, module);
402 private void resolveDirtyNodesWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
403 final ModuleBuilder module, SchemaContext context) {
404 final Set<TypeAwareBuilder> dirtyNodes = module.getDirtyNodes();
405 if (!dirtyNodes.isEmpty()) {
406 for (TypeAwareBuilder nodeToResolve : dirtyNodes) {
407 if (nodeToResolve instanceof UnionTypeBuilder) {
408 // special handling for union types
409 resolveTypeUnionWithContext((UnionTypeBuilder) nodeToResolve, modules, module, context);
410 } else if (nodeToResolve.getTypedef() instanceof IdentityrefTypeBuilder) {
411 // special handling for identityref types
412 IdentityrefTypeBuilder idref = (IdentityrefTypeBuilder) nodeToResolve.getTypedef();
413 nodeToResolve.setType(new IdentityrefType(findFullQName(modules, module, idref), idref.getPath()));
415 resolveTypeWithContext(nodeToResolve, modules, module, context);
422 * Resolve unknown type of node. It is assumed that type of node is either
423 * UnknownType or ExtendedType with UnknownType as base type.
425 * @param nodeToResolve
426 * node with type to resolve
432 private void resolveType(final TypeAwareBuilder nodeToResolve,
433 final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
434 TypeDefinitionBuilder resolvedType = null;
435 final int line = nodeToResolve.getLine();
436 final TypeDefinition<?> nodeToResolveType = nodeToResolve.getType();
437 final QName unknownTypeQName = nodeToResolveType.getBaseType().getQName();
438 final ModuleBuilder dependentModule = findDependentModuleBuilder(modules, module, unknownTypeQName.getPrefix(),
441 final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(nodeToResolve, dependentModule,
442 unknownTypeQName.getLocalName(), module.getName(), line);
444 if (nodeToResolveType instanceof ExtendedType) {
445 final ExtendedType extType = (ExtendedType) nodeToResolveType;
446 final TypeDefinitionBuilder newType = extendedTypeWithNewBaseTypeBuilder(targetTypeBuilder, extType,
447 modules, module, nodeToResolve.getLine());
448 resolvedType = newType;
450 resolvedType = targetTypeBuilder;
453 // validate constraints
454 final TypeConstraints constraints = findConstraintsFromTypeBuilder(nodeToResolve,
455 new TypeConstraints(module.getName(), nodeToResolve.getLine()), modules, module, null);
456 constraints.validateConstraints();
458 nodeToResolve.setTypedef(resolvedType);
462 * Resolve unknown type of node. It is assumed that type of node is either
463 * UnknownType or ExtendedType with UnknownType as base type.
465 * @param nodeToResolve
466 * node with type to resolve
472 * SchemaContext containing already resolved modules
474 private void resolveTypeWithContext(final TypeAwareBuilder nodeToResolve,
475 final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module,
476 final SchemaContext context) {
477 TypeDefinitionBuilder resolvedType = null;
478 final int line = nodeToResolve.getLine();
479 final TypeDefinition<?> nodeToResolveType = nodeToResolve.getType();
480 final QName unknownTypeQName = nodeToResolveType.getBaseType().getQName();
481 final ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module,
482 unknownTypeQName.getPrefix(), line);
484 if (dependentModuleBuilder == null) {
485 final Module dependentModule = findModuleFromContext(context, module, unknownTypeQName.getPrefix(), line);
486 final Set<TypeDefinition<?>> types = dependentModule.getTypeDefinitions();
487 final TypeDefinition<?> type = findTypeByName(types, unknownTypeQName.getLocalName());
489 if (nodeToResolveType instanceof ExtendedType) {
490 final ExtendedType extType = (ExtendedType) nodeToResolveType;
491 final TypeDefinitionBuilder newType = extendedTypeWithNewBaseType(type, extType, module,
492 nodeToResolve.getLine());
494 nodeToResolve.setTypedef(newType);
496 if (nodeToResolve instanceof TypeDefinitionBuilder) {
497 TypeDefinitionBuilder tdb = (TypeDefinitionBuilder) nodeToResolve;
498 TypeConstraints tc = findConstraintsFromTypeBuilder(nodeToResolve,
499 new TypeConstraints(module.getName(), nodeToResolve.getLine()), modules, module, context);
500 tdb.setLengths(tc.getLength());
501 tdb.setPatterns(tc.getPatterns());
502 tdb.setRanges(tc.getRange());
503 tdb.setFractionDigits(tc.getFractionDigits());
505 nodeToResolve.setType(type);
509 final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(nodeToResolve,
510 dependentModuleBuilder, unknownTypeQName.getLocalName(), module.getName(), line);
512 if (nodeToResolveType instanceof ExtendedType) {
513 final ExtendedType extType = (ExtendedType) nodeToResolveType;
514 final TypeDefinitionBuilder newType = extendedTypeWithNewBaseTypeBuilder(targetTypeBuilder, extType,
515 modules, module, nodeToResolve.getLine());
516 resolvedType = newType;
518 resolvedType = targetTypeBuilder;
521 // validate constraints
522 final TypeConstraints constraints = findConstraintsFromTypeBuilder(nodeToResolve, new TypeConstraints(
523 module.getName(), nodeToResolve.getLine()), modules, module, context);
524 constraints.validateConstraints();
526 nodeToResolve.setTypedef(resolvedType);
530 private void resolveTypeUnion(final UnionTypeBuilder union,
531 final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder builder) {
533 final List<TypeDefinition<?>> unionTypes = union.getTypes();
534 final List<TypeDefinition<?>> toRemove = new ArrayList<TypeDefinition<?>>();
535 for (TypeDefinition<?> unionType : unionTypes) {
536 if (unionType instanceof UnknownType) {
537 final UnknownType ut = (UnknownType) unionType;
538 final ModuleBuilder dependentModule = findDependentModuleBuilder(modules, builder, ut.getQName()
539 .getPrefix(), union.getLine());
540 final TypeDefinitionBuilder resolvedType = findTypeDefinitionBuilder(union, dependentModule, ut
541 .getQName().getLocalName(), builder.getName(), union.getLine());
542 union.setTypedef(resolvedType);
544 } else if (unionType instanceof ExtendedType) {
545 final ExtendedType extType = (ExtendedType) unionType;
546 final TypeDefinition<?> extTypeBase = extType.getBaseType();
547 if (extTypeBase instanceof UnknownType) {
548 final UnknownType ut = (UnknownType) extTypeBase;
549 final ModuleBuilder dependentModule = findDependentModuleBuilder(modules, builder, ut.getQName()
550 .getPrefix(), union.getLine());
551 final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(union, dependentModule,
552 ut.getQName().getLocalName(), builder.getName(), union.getLine());
554 final TypeDefinitionBuilder newType = extendedTypeWithNewBaseTypeBuilder(targetTypeBuilder,
555 extType, modules, builder, union.getLine());
557 union.setTypedef(newType);
558 toRemove.add(extType);
562 unionTypes.removeAll(toRemove);
565 private void resolveTypeUnionWithContext(final UnionTypeBuilder union,
566 final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder builder,
567 final SchemaContext context) {
569 final List<TypeDefinition<?>> unionTypes = union.getTypes();
570 final List<TypeDefinition<?>> toRemove = new ArrayList<TypeDefinition<?>>();
571 for (TypeDefinition<?> unionType : unionTypes) {
572 if (unionType instanceof UnknownType) {
573 final UnknownType ut = (UnknownType) unionType;
574 final QName utQName = ut.getQName();
575 final ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, builder,
576 utQName.getPrefix(), union.getLine());
578 if (dependentModuleBuilder == null) {
579 Module dependentModule = findModuleFromContext(context, builder, utQName.getPrefix(),
581 Set<TypeDefinition<?>> types = dependentModule.getTypeDefinitions();
582 TypeDefinition<?> type = findTypeByName(types, utQName.getLocalName());
586 final TypeDefinitionBuilder resolvedType = findTypeDefinitionBuilder(union, dependentModuleBuilder,
587 utQName.getLocalName(), builder.getName(), union.getLine());
588 union.setTypedef(resolvedType);
592 } else if (unionType instanceof ExtendedType) {
593 final ExtendedType extType = (ExtendedType) unionType;
594 TypeDefinition<?> extTypeBase = extType.getBaseType();
595 if (extTypeBase instanceof UnknownType) {
596 final UnknownType ut = (UnknownType) extTypeBase;
597 final QName utQName = ut.getQName();
598 final ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, builder,
599 utQName.getPrefix(), union.getLine());
601 if (dependentModuleBuilder == null) {
602 final Module dependentModule = findModuleFromContext(context, builder, utQName.getPrefix(),
604 Set<TypeDefinition<?>> types = dependentModule.getTypeDefinitions();
605 TypeDefinition<?> type = findTypeByName(types, utQName.getLocalName());
606 final TypeDefinitionBuilder newType = extendedTypeWithNewBaseType(type, extType, builder, 0);
608 union.setTypedef(newType);
609 toRemove.add(extType);
611 final TypeDefinitionBuilder targetTypeBuilder = findTypeDefinitionBuilder(union,
612 dependentModuleBuilder, utQName.getLocalName(), builder.getName(), union.getLine());
614 final TypeDefinitionBuilder newType = extendedTypeWithNewBaseTypeBuilder(targetTypeBuilder,
615 extType, modules, builder, union.getLine());
617 union.setTypedef(newType);
618 toRemove.add(extType);
623 unionTypes.removeAll(toRemove);
627 * Go through all augment definitions and resolve them. It is expected that
628 * modules are already sorted by their dependencies. This method also finds
629 * augment target node and add child nodes to it.
632 * all available modules
634 private void resolveAugments(final Map<String, TreeMap<Date, ModuleBuilder>> modules) {
635 final List<ModuleBuilder> allModulesList = new ArrayList<ModuleBuilder>();
636 final Set<ModuleBuilder> allModulesSet = new HashSet<ModuleBuilder>();
637 for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
638 for (Map.Entry<Date, ModuleBuilder> inner : entry.getValue().entrySet()) {
639 allModulesList.add(inner.getValue());
640 allModulesSet.add(inner.getValue());
644 for (int i = 0; i < allModulesList.size(); i++) {
645 final ModuleBuilder module = allModulesList.get(i);
646 // try to resolve augments in module
647 resolveAugment(modules, module);
648 // while all augments are not resolved
649 final Iterator<ModuleBuilder> allModulesIterator = allModulesSet.iterator();
650 while (!(module.getAugmentsResolved() == module.getAllAugments().size())) {
651 ModuleBuilder nextModule = null;
652 // try resolve other module augments
654 nextModule = allModulesIterator.next();
655 resolveAugment(modules, nextModule);
656 } catch (NoSuchElementException e) {
657 throw new YangParseException("Failed to resolve augments in module '" + module.getName() + "'.", e);
659 // then try to resolve first module again
660 resolveAugment(modules, module);
666 * Tries to resolve augments in given module. If augment target node is not
670 * all available modules
674 private void resolveAugment(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
675 if (module.getAugmentsResolved() < module.getAllAugments().size()) {
676 for (AugmentationSchemaBuilder augmentBuilder : module.getAllAugments()) {
678 if (!augmentBuilder.isResolved()) {
679 final SchemaPath augmentTargetSchemaPath = augmentBuilder.getTargetPath();
680 final List<QName> path = augmentTargetSchemaPath.getPath();
682 final QName qname = path.get(0);
683 String prefix = qname.getPrefix();
684 if (prefix == null) {
685 prefix = module.getPrefix();
688 final ModuleBuilder dependentModule = findDependentModuleBuilder(modules, module, prefix,
689 augmentBuilder.getLine());
690 processAugmentation(augmentBuilder, path, module, dependentModule);
698 * Go through all augment definitions and resolve them. This method works in
699 * same way as {@link #resolveAugments(Map)} except that if target node is
700 * not found in loaded modules, it search for target node in given context.
705 * SchemaContext containing already resolved modules
707 private void resolveAugmentsWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
708 final SchemaContext context) {
709 final List<ModuleBuilder> allModulesList = new ArrayList<ModuleBuilder>();
710 final Set<ModuleBuilder> allModulesSet = new HashSet<ModuleBuilder>();
711 for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
712 for (Map.Entry<Date, ModuleBuilder> inner : entry.getValue().entrySet()) {
713 allModulesList.add(inner.getValue());
714 allModulesSet.add(inner.getValue());
718 for (int i = 0; i < allModulesList.size(); i++) {
719 final ModuleBuilder module = allModulesList.get(i);
720 // try to resolve augments in module
721 resolveAugmentWithContext(modules, module, context);
722 // while all augments are not resolved
723 final Iterator<ModuleBuilder> allModulesIterator = allModulesSet.iterator();
724 while (!(module.getAugmentsResolved() == module.getAllAugments().size())) {
725 ModuleBuilder nextModule = null;
726 // try resolve other module augments
728 nextModule = allModulesIterator.next();
729 resolveAugmentWithContext(modules, nextModule, context);
730 } catch (NoSuchElementException e) {
731 throw new YangParseException("Failed to resolve augments in module '" + module.getName() + "'.", e);
733 // then try to resolve first module again
734 resolveAugmentWithContext(modules, module, context);
740 * Tries to resolve augments in given module. If augment target node is not
744 * all available modules
748 private void resolveAugmentWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
749 final ModuleBuilder module, final SchemaContext context) {
750 if (module.getAugmentsResolved() < module.getAllAugments().size()) {
752 for (AugmentationSchemaBuilder augmentBuilder : module.getAllAugments()) {
753 final int line = augmentBuilder.getLine();
755 if (!augmentBuilder.isResolved()) {
756 final List<QName> path = augmentBuilder.getTargetPath().getPath();
757 final QName qname = path.get(0);
758 String prefix = qname.getPrefix();
759 if (prefix == null) {
760 prefix = module.getPrefix();
763 // try to find augment target module in loaded modules...
764 final ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module, prefix,
766 if (dependentModuleBuilder == null) {
767 // perform augmentation on module from context and
768 // continue to next augment
769 processAugmentationOnContext(augmentBuilder, path, module, prefix, line, context);
772 processAugmentation(augmentBuilder, path, module, dependentModuleBuilder);
781 * Go through identity statements defined in current module and resolve
782 * their 'base' statement if present.
787 * module being resolved
789 private void resolveIdentities(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
790 final Set<IdentitySchemaNodeBuilder> identities = module.getIdentities();
791 for (IdentitySchemaNodeBuilder identity : identities) {
792 final String baseIdentityName = identity.getBaseIdentityName();
793 if (baseIdentityName != null) {
794 String baseIdentityPrefix = null;
795 String baseIdentityLocalName = null;
796 if (baseIdentityName.contains(":")) {
797 final String[] splitted = baseIdentityName.split(":");
798 baseIdentityPrefix = splitted[0];
799 baseIdentityLocalName = splitted[1];
801 baseIdentityPrefix = module.getPrefix();
802 baseIdentityLocalName = baseIdentityName;
804 final ModuleBuilder dependentModule = findDependentModuleBuilder(modules, module, baseIdentityPrefix,
807 final Set<IdentitySchemaNodeBuilder> dependentModuleIdentities = dependentModule.getIdentities();
808 for (IdentitySchemaNodeBuilder idBuilder : dependentModuleIdentities) {
809 if (idBuilder.getQName().getLocalName().equals(baseIdentityLocalName)) {
810 identity.setBaseIdentity(idBuilder);
818 * Go through identity statements defined in current module and resolve
819 * their 'base' statement. Method tries to find base identity in given
820 * modules. If base identity is not found, method will search it in context.
827 * SchemaContext containing already resolved modules
829 private void resolveIdentitiesWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
830 final ModuleBuilder module, final SchemaContext context) {
831 final Set<IdentitySchemaNodeBuilder> identities = module.getIdentities();
832 for (IdentitySchemaNodeBuilder identity : identities) {
833 final String baseIdentityName = identity.getBaseIdentityName();
834 if (baseIdentityName != null) {
835 String baseIdentityPrefix = null;
836 String baseIdentityLocalName = null;
837 if (baseIdentityName.contains(":")) {
838 final String[] splitted = baseIdentityName.split(":");
839 baseIdentityPrefix = splitted[0];
840 baseIdentityLocalName = splitted[1];
842 baseIdentityPrefix = module.getPrefix();
843 baseIdentityLocalName = baseIdentityName;
845 final ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module,
846 baseIdentityPrefix, identity.getLine());
848 if (dependentModuleBuilder == null) {
849 final Module dependentModule = findModuleFromContext(context, module, baseIdentityPrefix,
851 final Set<IdentitySchemaNode> dependentModuleIdentities = dependentModule.getIdentities();
852 for (IdentitySchemaNode idNode : dependentModuleIdentities) {
853 if (idNode.getQName().getLocalName().equals(baseIdentityLocalName)) {
854 identity.setBaseIdentity(idNode);
858 final Set<IdentitySchemaNodeBuilder> dependentModuleIdentities = dependentModuleBuilder
860 for (IdentitySchemaNodeBuilder idBuilder : dependentModuleIdentities) {
861 if (idBuilder.getQName().getLocalName().equals(baseIdentityLocalName)) {
862 identity.setBaseIdentity(idBuilder);
871 * Go through uses statements defined in current module and resolve their
877 * module being resolved
879 private void resolveUsesRefine(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
880 final List<UsesNodeBuilder> allModuleUses = module.getAllUsesNodes();
881 for (UsesNodeBuilder usesNode : allModuleUses) {
883 final int line = usesNode.getLine();
884 final GroupingBuilder targetGrouping = getTargetGroupingFromModules(usesNode, modules, module);
885 usesNode.setGroupingPath(targetGrouping.getPath());
886 for (RefineHolder refine : usesNode.getRefines()) {
887 final SchemaNodeBuilder nodeToRefine = RefineUtils.getRefineNodeFromGroupingBuilder(targetGrouping,
888 refine, module.getName());
889 if (nodeToRefine instanceof GroupingMember) {
890 ((GroupingMember) nodeToRefine).setAddedByUses(true);
892 RefineUtils.performRefine(nodeToRefine, refine, line);
893 usesNode.addRefineNode(nodeToRefine);
897 processUsesNode(module, usesNode, targetGrouping);
902 * Tries to search target grouping in given modules and resolve refine
903 * nodes. If grouping is not found in modules, method tries to find it in
904 * modules from context.
911 * SchemaContext containing already resolved modules
913 private void resolveUsesRefineWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
914 final ModuleBuilder module, final SchemaContext context) {
915 final List<UsesNodeBuilder> moduleUses = module.getAllUsesNodes();
916 for (UsesNodeBuilder usesNode : moduleUses) {
917 final int line = usesNode.getLine();
919 final GroupingBuilder targetGroupingBuilder = getTargetGroupingFromModules(usesNode, modules, module);
920 if (targetGroupingBuilder == null) {
921 final GroupingDefinition targetGrouping = getTargetGroupingFromContext(usesNode, module, context);
922 usesNode.setGroupingPath(targetGrouping.getPath());
923 for (RefineHolder refine : usesNode.getRefines()) {
924 final SchemaNodeBuilder nodeToRefine = RefineUtils.getRefineNodeFromGroupingDefinition(
925 targetGrouping, refine);
926 if (nodeToRefine instanceof GroupingMember) {
927 ((GroupingMember) nodeToRefine).setAddedByUses(true);
929 RefineUtils.performRefine(nodeToRefine, refine, line);
930 usesNode.addRefineNode(nodeToRefine);
933 processUsesNode(usesNode, targetGrouping);
935 usesNode.setGroupingPath(targetGroupingBuilder.getPath());
936 for (RefineHolder refine : usesNode.getRefines()) {
937 final SchemaNodeBuilder nodeToRefine = RefineUtils.getRefineNodeFromGroupingBuilder(
938 targetGroupingBuilder, refine, module.getName());
939 if (nodeToRefine instanceof GroupingMember) {
940 ((GroupingMember) nodeToRefine).setAddedByUses(true);
942 RefineUtils.performRefine(nodeToRefine, refine, line);
943 usesNode.addRefineNode(nodeToRefine);
946 processUsesNode(module, usesNode, targetGroupingBuilder);
952 * Search given modules for grouping by name defined in uses node.
955 * builder of uses statement
960 * @return grouping with given name if found, null otherwise
962 private GroupingBuilder getTargetGroupingFromModules(final UsesNodeBuilder usesBuilder,
963 final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
964 final int line = usesBuilder.getLine();
965 final String groupingString = usesBuilder.getGroupingName();
966 String groupingPrefix;
969 if (groupingString.contains(":")) {
970 String[] splitted = groupingString.split(":");
971 if (splitted.length != 2 || groupingString.contains("/")) {
972 throw new YangParseException(module.getName(), line, "Invalid name of target grouping");
974 groupingPrefix = splitted[0];
975 groupingName = splitted[1];
977 groupingPrefix = module.getPrefix();
978 groupingName = groupingString;
981 ModuleBuilder dependentModule = null;
982 if (groupingPrefix.equals(module.getPrefix())) {
983 dependentModule = module;
985 dependentModule = findDependentModuleBuilder(modules, module, groupingPrefix, line);
988 if (dependentModule == null) {
992 GroupingBuilder result = null;
993 Set<GroupingBuilder> groupings = dependentModule.getGroupingBuilders();
994 result = findGroupingBuilder(groupings, groupingName);
995 if (result != null) {
999 Builder parent = usesBuilder.getParent();
1001 while (parent != null) {
1002 if (parent instanceof DataNodeContainerBuilder) {
1003 groupings = ((DataNodeContainerBuilder) parent).getGroupingBuilders();
1004 } else if (parent instanceof RpcDefinitionBuilder) {
1005 groupings = ((RpcDefinitionBuilder) parent).getGroupings();
1007 result = findGroupingBuilder(groupings, groupingName);
1008 if (result == null) {
1009 parent = parent.getParent();
1015 if (result == null) {
1016 throw new YangParseException(module.getName(), line, "Referenced grouping '" + groupingName
1023 * Search context for grouping by name defined in uses node.
1025 * @param usesBuilder
1026 * builder of uses statement
1030 * SchemaContext containing already resolved modules
1031 * @return grouping with given name if found, null otherwise
1033 private GroupingDefinition getTargetGroupingFromContext(final UsesNodeBuilder usesBuilder,
1034 final ModuleBuilder module, final SchemaContext context) {
1035 final int line = usesBuilder.getLine();
1036 String groupingString = usesBuilder.getGroupingName();
1037 String groupingPrefix;
1038 String groupingName;
1040 if (groupingString.contains(":")) {
1041 String[] splitted = groupingString.split(":");
1042 if (splitted.length != 2 || groupingString.contains("/")) {
1043 throw new YangParseException(module.getName(), line, "Invalid name of target grouping");
1045 groupingPrefix = splitted[0];
1046 groupingName = splitted[1];
1048 groupingPrefix = module.getPrefix();
1049 groupingName = groupingString;
1052 Module dependentModule = findModuleFromContext(context, module, groupingPrefix, line);
1053 return findGroupingDefinition(dependentModule.getGroupings(), groupingName);
1057 * Add nodes defined in target grouping to current context. Refinement has
1058 * to be already performed.
1060 * @param module current module
1062 * @param targetGrouping
1064 private void processUsesNode(final ModuleBuilder module, final UsesNodeBuilder usesNode, final GroupingBuilder targetGrouping) {
1065 List<SchemaNodeBuilder> refineNodes = usesNode.getRefineNodes();
1066 DataNodeContainerBuilder parent = usesNode.getParent();
1067 URI namespace = null;
1068 Date revision = null;
1069 String prefix = null;
1070 if (parent instanceof ModuleBuilder || parent instanceof AugmentationSchemaBuilder) {
1071 namespace = module.getNamespace();
1072 revision = module.getRevision();
1073 prefix = module.getPrefix();
1075 QName parentQName = parent.getQName();
1076 namespace = parentQName.getNamespace();
1077 revision = parentQName.getRevision();
1078 prefix = parentQName.getPrefix();
1080 SchemaPath parentPath = parent.getPath();
1081 for (DataSchemaNodeBuilder child : targetGrouping.getChildNodeBuilders()) {
1082 if (child != null) {
1083 // if node is refined, take it from refined nodes and continue
1084 SchemaNodeBuilder refined = getRefined(child.getQName(), refineNodes);
1085 if (refined != null) {
1086 refined.setPath(createSchemaPath(parentPath, refined.getQName().getLocalName(), namespace,
1088 parent.addChildNode((DataSchemaNodeBuilder) refined);
1092 DataSchemaNodeBuilder newChild = null;
1093 if (child instanceof AnyXmlBuilder) {
1094 newChild = new AnyXmlBuilder((AnyXmlBuilder) child);
1095 } else if (child instanceof ChoiceBuilder) {
1096 newChild = new ChoiceBuilder((ChoiceBuilder) child);
1097 } else if (child instanceof ContainerSchemaNodeBuilder) {
1098 newChild = new ContainerSchemaNodeBuilder((ContainerSchemaNodeBuilder) child);
1099 } else if (child instanceof LeafListSchemaNodeBuilder) {
1100 newChild = new LeafListSchemaNodeBuilder((LeafListSchemaNodeBuilder) child);
1101 } else if (child instanceof LeafSchemaNodeBuilder) {
1102 newChild = new LeafSchemaNodeBuilder((LeafSchemaNodeBuilder) child);
1103 } else if (child instanceof ListSchemaNodeBuilder) {
1104 newChild = new ListSchemaNodeBuilder((ListSchemaNodeBuilder) child);
1107 if (newChild == null) {
1108 throw new YangParseException(usesNode.getModuleName(), usesNode.getLine(),
1109 "Unknown member of target grouping while resolving uses node.");
1112 if (newChild instanceof GroupingMember) {
1113 ((GroupingMember) newChild).setAddedByUses(true);
1116 newChild.setPath(createSchemaPath(parentPath, newChild.getQName().getLocalName(), namespace, revision,
1118 parent.addChildNode(newChild);
1121 for (GroupingBuilder g : targetGrouping.getGroupingBuilders()) {
1122 GroupingBuilder newGrouping = new GroupingBuilderImpl(g);
1123 newGrouping.setAddedByUses(true);
1124 newGrouping.setPath(createSchemaPath(parentPath, newGrouping.getQName().getLocalName(), namespace,
1126 parent.addGrouping(newGrouping);
1128 for (TypeDefinitionBuilder td : targetGrouping.getTypeDefinitionBuilders()) {
1129 TypeDefinitionBuilder newType = new TypeDefinitionBuilderImpl(td);
1130 newType.setAddedByUses(true);
1131 newType.setPath(createSchemaPath(parentPath, newType.getQName().getLocalName(), namespace, revision, prefix));
1132 parent.addTypedef(newType);
1134 for (UsesNodeBuilder un : targetGrouping.getUses()) {
1135 UsesNodeBuilder newUses = new UsesNodeBuilderImpl(un);
1136 newUses.setAddedByUses(true);
1137 // uses has not path
1138 parent.addUsesNode(newUses);
1140 for (UnknownSchemaNodeBuilder un : targetGrouping.getUnknownNodeBuilders()) {
1141 UnknownSchemaNodeBuilder newUn = new UnknownSchemaNodeBuilder(un);
1142 newUn.setAddedByUses(true);
1143 newUn.setPath(createSchemaPath(parentPath, un.getQName().getLocalName(), namespace, revision, prefix));
1144 parent.addUnknownNodeBuilder(newUn);
1148 private void processUsesNode(final UsesNodeBuilder usesNode, final GroupingDefinition targetGrouping) {
1149 final String moduleName = usesNode.getModuleName();
1150 final int line = usesNode.getLine();
1151 List<SchemaNodeBuilder> refineNodes = usesNode.getRefineNodes();
1152 DataNodeContainerBuilder parent = usesNode.getParent();
1153 URI namespace = null;
1154 Date revision = null;
1155 String prefix = null;
1156 if (parent instanceof ModuleBuilder) {
1157 ModuleBuilder module = (ModuleBuilder) parent;
1158 namespace = module.getNamespace();
1159 revision = module.getRevision();
1160 prefix = module.getPrefix();
1162 QName parentQName = parent.getQName();
1163 namespace = parentQName.getNamespace();
1164 revision = parentQName.getRevision();
1165 prefix = parentQName.getPrefix();
1167 SchemaPath parentPath = parent.getPath();
1168 for (DataSchemaNode child : targetGrouping.getChildNodes()) {
1169 if (child != null) {
1170 // if node is refined, take it from refined nodes and continue
1171 SchemaNodeBuilder refined = getRefined(child.getQName(), refineNodes);
1172 if (refined != null) {
1173 refined.setPath(createSchemaPath(parentPath, refined.getQName().getLocalName(), namespace,
1175 parent.addChildNode((DataSchemaNodeBuilder) refined);
1179 DataSchemaNodeBuilder newChild = null;
1180 if (child instanceof AnyXmlSchemaNode) {
1181 newChild = createAnyXml((AnyXmlSchemaNode) child, moduleName, line);
1182 } else if (child instanceof ChoiceNode) {
1183 newChild = createChoice((ChoiceNode) child, moduleName, line);
1184 } else if (child instanceof ContainerSchemaNode) {
1185 newChild = createContainer((ContainerSchemaNode) child, moduleName, line);
1186 } else if (child instanceof LeafListSchemaNode) {
1187 newChild = createLeafList((LeafListSchemaNode) child, moduleName, line);
1188 } else if (child instanceof LeafSchemaNode) {
1189 newChild = createLeafBuilder((LeafSchemaNode) child, moduleName, line);
1190 } else if (child instanceof ListSchemaNode) {
1191 newChild = createList((ListSchemaNode) child, moduleName, line);
1194 if (newChild == null) {
1195 throw new YangParseException(moduleName, line,
1196 "Unknown member of target grouping while resolving uses node.");
1199 if (newChild instanceof GroupingMember) {
1200 ((GroupingMember) newChild).setAddedByUses(true);
1202 newChild.setPath(createSchemaPath(parentPath, newChild.getQName().getLocalName(), namespace, revision,
1204 parent.addChildNode(newChild);
1207 for (GroupingDefinition g : targetGrouping.getGroupings()) {
1208 GroupingBuilder newGrouping = createGrouping(g, moduleName, line);
1209 newGrouping.setAddedByUses(true);
1210 newGrouping.setPath(createSchemaPath(parentPath, newGrouping.getQName().getLocalName(), namespace,
1212 parent.addGrouping(newGrouping);
1214 for (TypeDefinition<?> td : targetGrouping.getTypeDefinitions()) {
1215 TypeDefinitionBuilder newType = createTypedef((ExtendedType) td, moduleName, line);
1216 newType.setAddedByUses(true);
1217 newType.setPath(createSchemaPath(parentPath, newType.getQName().getLocalName(), namespace, revision, prefix));
1218 parent.addTypedef(newType);
1220 for (UsesNode un : targetGrouping.getUses()) {
1221 if (un instanceof UsesNodeImpl) {
1222 UsesNodeBuilder newUses = new UsesNodeBuilderImpl(((UsesNodeImpl) un).toBuilder());
1223 newUses.setAddedByUses(true);
1224 // uses has not path
1225 parent.addUsesNode(newUses);
1228 for (UnknownSchemaNode un : targetGrouping.getUnknownSchemaNodes()) {
1229 UnknownSchemaNodeBuilder newNode = createUnknownSchemaNode(un, moduleName, line);
1230 newNode.setAddedByUses(true);
1231 newNode.setPath(createSchemaPath(parentPath, un.getQName().getLocalName(), namespace, revision, prefix));
1232 parent.addUnknownNodeBuilder(newNode);
1236 private QName findFullQName(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module,
1237 final IdentityrefTypeBuilder idref) {
1238 QName result = null;
1239 String baseString = idref.getBaseString();
1240 if (baseString.contains(":")) {
1241 String[] splittedBase = baseString.split(":");
1242 if (splittedBase.length > 2) {
1243 throw new YangParseException(module.getName(), idref.getLine(), "Failed to parse identityref base: "
1246 String prefix = splittedBase[0];
1247 String name = splittedBase[1];
1248 ModuleBuilder dependentModule = findDependentModuleBuilder(modules, module, prefix, idref.getLine());
1249 result = new QName(dependentModule.getNamespace(), dependentModule.getRevision(), prefix, name);
1251 result = new QName(module.getNamespace(), module.getRevision(), module.getPrefix(), baseString);
1256 private void resolveUnknownNodes(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
1257 for (UnknownSchemaNodeBuilder usnb : module.getAllUnknownNodes()) {
1258 QName nodeType = usnb.getNodeType();
1259 if (nodeType.getNamespace() == null || nodeType.getRevision() == null) {
1261 ModuleBuilder dependentModule = findDependentModuleBuilder(modules, module, nodeType.getPrefix(),
1263 QName newNodeType = new QName(dependentModule.getNamespace(), dependentModule.getRevision(),
1264 nodeType.getPrefix(), nodeType.getLocalName());
1265 usnb.setNodeType(newNodeType);
1266 } catch (YangParseException e) {
1267 LOG.debug(module.getName(), usnb.getLine(), "Failed to find unknown node type: " + nodeType);
1273 private void resolveUnknownNodesWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
1274 final ModuleBuilder module, final SchemaContext context) {
1275 for (UnknownSchemaNodeBuilder unknownNodeBuilder : module.getAllUnknownNodes()) {
1276 QName nodeType = unknownNodeBuilder.getNodeType();
1277 if (nodeType.getNamespace() == null || nodeType.getRevision() == null) {
1279 ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module,
1280 nodeType.getPrefix(), unknownNodeBuilder.getLine());
1282 QName newNodeType = null;
1283 if (dependentModuleBuilder == null) {
1284 Module dependentModule = findModuleFromContext(context, module, nodeType.getPrefix(),
1285 unknownNodeBuilder.getLine());
1286 newNodeType = new QName(dependentModule.getNamespace(), dependentModule.getRevision(),
1287 nodeType.getPrefix(), nodeType.getLocalName());
1289 newNodeType = new QName(dependentModuleBuilder.getNamespace(),
1290 dependentModuleBuilder.getRevision(), nodeType.getPrefix(), nodeType.getLocalName());
1293 unknownNodeBuilder.setNodeType(newNodeType);
1294 } catch (YangParseException e) {
1295 LOG.debug(module.getName(), unknownNodeBuilder.getLine(), "Failed to find unknown node type: "
1302 private void resolveDeviations(final Map<String, TreeMap<Date, ModuleBuilder>> modules) {
1303 for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
1304 for (Map.Entry<Date, ModuleBuilder> inner : entry.getValue().entrySet()) {
1305 ModuleBuilder b = inner.getValue();
1306 resolveDeviation(modules, b);
1311 private void resolveDeviation(final Map<String, TreeMap<Date, ModuleBuilder>> modules, final ModuleBuilder module) {
1312 for (DeviationBuilder dev : module.getDeviations()) {
1313 int line = dev.getLine();
1314 SchemaPath targetPath = dev.getTargetPath();
1315 List<QName> path = targetPath.getPath();
1316 QName q0 = path.get(0);
1317 String prefix = q0.getPrefix();
1318 if (prefix == null) {
1319 prefix = module.getPrefix();
1322 ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module, prefix, line);
1323 processDeviation(dev, dependentModuleBuilder, path, module);
1327 private void resolveDeviationsWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
1328 final SchemaContext context) {
1329 for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
1330 for (Map.Entry<Date, ModuleBuilder> inner : entry.getValue().entrySet()) {
1331 ModuleBuilder b = inner.getValue();
1332 resolveDeviationWithContext(modules, b, context);
1337 private void resolveDeviationWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
1338 final ModuleBuilder module, final SchemaContext context) {
1339 for (DeviationBuilder dev : module.getDeviations()) {
1340 int line = dev.getLine();
1341 SchemaPath targetPath = dev.getTargetPath();
1342 List<QName> path = targetPath.getPath();
1343 QName q0 = path.get(0);
1344 String prefix = q0.getPrefix();
1345 if (prefix == null) {
1346 prefix = module.getPrefix();
1350 ModuleBuilder dependentModuleBuilder = findDependentModuleBuilder(modules, module, prefix, line);
1351 if (dependentModuleBuilder == null) {
1352 Module dependentModule = findModuleFromContext(context, module, prefix, line);
1353 Object currentParent = dependentModule;
1355 for (int i = 0; i < path.size(); i++) {
1356 if (currentParent == null) {
1357 throw new YangParseException(module.getName(), line, "Failed to find deviation target.");
1359 QName q = path.get(i);
1360 name = q.getLocalName();
1361 if (currentParent instanceof DataNodeContainer) {
1362 currentParent = ((DataNodeContainer) currentParent).getDataChildByName(name);
1366 if (currentParent == null) {
1367 throw new YangParseException(module.getName(), line, "Failed to find deviation target.");
1369 if (currentParent instanceof SchemaNode) {
1370 dev.setTargetPath(((SchemaNode) currentParent).getPath());
1374 processDeviation(dev, dependentModuleBuilder, path, module);
1380 * Correct deviation target path in deviation builder.
1384 * @param dependentModuleBuilder
1385 * module containing deviation target
1387 * current deviation target path
1391 private void processDeviation(final DeviationBuilder dev, final ModuleBuilder dependentModuleBuilder,
1392 final List<QName> path, final ModuleBuilder module) {
1393 final int line = dev.getLine();
1394 Builder currentParent = dependentModuleBuilder;
1396 for (int i = 0; i < path.size(); i++) {
1397 if (currentParent == null) {
1398 throw new YangParseException(module.getName(), line, "Failed to find deviation target.");
1400 QName q = path.get(i);
1401 String name = q.getLocalName();
1402 if (currentParent instanceof DataNodeContainerBuilder) {
1403 currentParent = ((DataNodeContainerBuilder) currentParent).getDataChildByName(name);
1407 if (currentParent == null || !(currentParent instanceof SchemaNodeBuilder)) {
1408 throw new YangParseException(module.getName(), line, "Failed to find deviation target.");
1410 dev.setTargetPath(((SchemaNodeBuilder) currentParent).getPath());