X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=yang%2Fyang-parser-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fparser%2Fimpl%2FYangParserImpl.java;h=7948158f4dee6b277493d8d2451395d3ee6b3d19;hb=300aed51915840a41a1483980ff7d045bde905cb;hp=aefd0ba1b93525ec19b20d0da6918eeeda1ba2c0;hpb=90d0c4f928887171dd1598d844c7939a78beb708;p=yangtools.git diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YangParserImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YangParserImpl.java index aefd0ba1b9..7948158f4d 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YangParserImpl.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YangParserImpl.java @@ -9,30 +9,22 @@ package org.opendaylight.yangtools.yang.parser.impl; import static com.google.common.base.Preconditions.checkNotNull; import static org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils.fillAugmentTarget; import static org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils.findBaseIdentity; -import static org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils.findModuleFromBuilders; import static org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils.findModuleFromContext; import static org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils.findSchemaNode; import static org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils.findSchemaNodeInModule; import static org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils.processAugmentation; -import static org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils.setNodeAddedByUses; -import static org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils.wrapChildNode; -import static org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils.wrapChildNodes; -import static org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils.wrapGroupings; -import static org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils.wrapTypedefs; -import static org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils.wrapUnknownNodes; import static org.opendaylight.yangtools.yang.parser.builder.impl.TypeUtils.resolveType; import static org.opendaylight.yangtools.yang.parser.builder.impl.TypeUtils.resolveTypeUnion; -import static org.opendaylight.yangtools.yang.parser.builder.impl.TypeUtils.resolveTypeUnionWithContext; -import static org.opendaylight.yangtools.yang.parser.builder.impl.TypeUtils.resolveTypeWithContext; import com.google.common.base.Optional; import com.google.common.base.Preconditions; +import com.google.common.base.Splitter; import com.google.common.collect.HashBiMap; import com.google.common.io.ByteSource; - import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -45,9 +37,7 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; - import javax.annotation.concurrent.Immutable; - import org.antlr.v4.runtime.ANTLRInputStream; import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.tree.ParseTree; @@ -57,15 +47,11 @@ import org.opendaylight.yangtools.antlrv4.code.gen.YangParser; import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.YangContext; import org.opendaylight.yangtools.yang.common.QName; import org.opendaylight.yangtools.yang.common.QNameModule; -import org.opendaylight.yangtools.yang.model.api.DataNodeContainer; -import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition; -import org.opendaylight.yangtools.yang.model.api.GroupingDefinition; import org.opendaylight.yangtools.yang.model.api.Module; import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier; import org.opendaylight.yangtools.yang.model.api.ModuleImport; import org.opendaylight.yangtools.yang.model.api.SchemaContext; -import org.opendaylight.yangtools.yang.model.api.SchemaNode; import org.opendaylight.yangtools.yang.model.api.SchemaPath; import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser; import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException; @@ -78,20 +64,17 @@ import org.opendaylight.yangtools.yang.parser.builder.api.ExtensionBuilder; import org.opendaylight.yangtools.yang.parser.builder.api.GroupingBuilder; import org.opendaylight.yangtools.yang.parser.builder.api.SchemaNodeBuilder; import org.opendaylight.yangtools.yang.parser.builder.api.TypeAwareBuilder; -import org.opendaylight.yangtools.yang.parser.builder.api.TypeDefinitionBuilder; import org.opendaylight.yangtools.yang.parser.builder.api.UnknownSchemaNodeBuilder; import org.opendaylight.yangtools.yang.parser.builder.api.UsesNodeBuilder; import org.opendaylight.yangtools.yang.parser.builder.impl.BuilderUtils; import org.opendaylight.yangtools.yang.parser.builder.impl.ChoiceBuilder; import org.opendaylight.yangtools.yang.parser.builder.impl.ChoiceCaseBuilder; -import org.opendaylight.yangtools.yang.parser.builder.impl.DeviationBuilder; import org.opendaylight.yangtools.yang.parser.builder.impl.GroupingUtils; import org.opendaylight.yangtools.yang.parser.builder.impl.IdentitySchemaNodeBuilder; import org.opendaylight.yangtools.yang.parser.builder.impl.IdentityrefTypeBuilder; import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleBuilder; import org.opendaylight.yangtools.yang.parser.builder.impl.ModuleImpl; import org.opendaylight.yangtools.yang.parser.builder.impl.UnionTypeBuilder; -import org.opendaylight.yangtools.yang.parser.builder.impl.UnknownSchemaNodeBuilderImpl; import org.opendaylight.yangtools.yang.parser.builder.util.Comparators; import org.opendaylight.yangtools.yang.parser.util.ModuleDependencySort; import org.opendaylight.yangtools.yang.parser.util.NamedByteArrayInputStream; @@ -104,16 +87,13 @@ import org.slf4j.LoggerFactory; @Immutable public final class YangParserImpl implements YangContextParser { private static final Logger LOG = LoggerFactory.getLogger(YangParserImpl.class); - - private static final String FAIL_DEVIATION_TARGET = "Failed to find deviation target."; + private static final Splitter COLON_SPLITTER = Splitter.on(':'); private static final YangParserImpl INSTANCE = new YangParserImpl(); public static YangParserImpl getInstance() { return INSTANCE; } - - @Override @Deprecated public Set parseYangModels(final File yangFile, final File directory) { @@ -125,8 +105,7 @@ public final class YangParserImpl implements YangContextParser { } @Override - public SchemaContext parseFile(final File yangFile, final File directory) throws IOException, - YangSyntaxErrorException { + public SchemaContext parseFile(final File yangFile, final File directory) throws IOException, YangSyntaxErrorException { Preconditions.checkState(yangFile.exists(), yangFile + " does not exists"); Preconditions.checkState(directory.exists(), directory + " does not exists"); Preconditions.checkState(directory.isDirectory(), directory + " is not a directory"); @@ -148,7 +127,7 @@ public final class YangParserImpl implements YangContextParser { } } - Map sourceToBuilder = parseSourcesToBuilders(sourceToFile.keySet()); + Map sourceToBuilder = parseSourcesToBuilders(sourceToFile.keySet(), null); ModuleBuilder main = sourceToBuilder.get(mainFileSource); List moduleBuilders = new ArrayList<>(); @@ -158,7 +137,7 @@ public final class YangParserImpl implements YangContextParser { // module builders sorted by dependencies List sortedBuilders = ModuleDependencySort.sort(resolved); - LinkedHashMap> modules = orderModules(sortedBuilders); + LinkedHashMap> modules = resolveModulesWithImports(sortedBuilders, null); Collection unsorted = build(modules).values(); Set result = new LinkedHashSet<>( ModuleDependencySort.sort(unsorted.toArray(new Module[unsorted.size()]))); @@ -212,12 +191,8 @@ public final class YangParserImpl implements YangContextParser { } @Override - public SchemaContext parseSources(final Collection sources) throws IOException, - YangSyntaxErrorException { - Collection unsorted = parseYangModelSources(sources).values(); - Set sorted = new LinkedHashSet<>( - ModuleDependencySort.sort(unsorted.toArray(new Module[unsorted.size()]))); - return resolveSchemaContext(sorted); + public SchemaContext parseSources(final Collection sources) throws IOException,YangSyntaxErrorException { + return assembleContext(parseYangModelSources(sources, null).values()); } @Override @@ -238,8 +213,10 @@ public final class YangParserImpl implements YangContextParser { return resolveSchemaContext(Collections. emptySet()); } - final Map> modules = resolveModuleBuilders(sources, context); - final Set unsorted = new LinkedHashSet<>(buildWithContext(modules, context).values()); + final List sorted = resolveModuleBuilders(sources, context); + final Map> modules = resolveModulesWithImports(sorted, context); + + final Set unsorted = new LinkedHashSet<>(build(modules).values()); if (context != null) { for (Module m : context.getModules()) { if (!unsorted.contains(m)) { @@ -252,6 +229,33 @@ public final class YangParserImpl implements YangContextParser { return resolveSchemaContext(result); } + private static LinkedHashMap> resolveModulesWithImports(final List sorted, + final SchemaContext context) { + final LinkedHashMap> modules = orderModules(sorted); + for (ModuleBuilder module : sorted) { + if (module != null) { + for (ModuleImport imp : module.getImports().values()) { + String prefix = imp.getPrefix(); + ModuleBuilder targetModule = BuilderUtils.findModuleFromBuilders(imp, sorted); + if (targetModule == null) { + Module result = findModuleFromContext(context, module, prefix, 0); + targetModule = new ModuleBuilder(result); + TreeMap map = modules.get(targetModule.getNamespace()); + if (map == null) { + map = new TreeMap<>(); + map.put(targetModule.getRevision(), targetModule); + modules.put(targetModule.getNamespace(), map); + } else { + map.put(targetModule.getRevision(), targetModule); + } + } + module.addImportedModule(prefix, targetModule); + } + } + } + return modules; + } + @Override public Map parseYangModelsMapped(final Collection yangFiles) { if (yangFiles == null || yangFiles.isEmpty()) { @@ -271,7 +275,7 @@ public final class YangParserImpl implements YangContextParser { Map byteSourceToModule; try { - byteSourceToModule = parseYangModelSources(byteSourceToFile.keySet()); + byteSourceToModule = parseYangModelSources(byteSourceToFile.keySet(), null); } catch (IOException | YangSyntaxErrorException e) { throw new YangParseException("Failed to parse yang data", e); } @@ -301,7 +305,7 @@ public final class YangParserImpl implements YangContextParser { Map sourceToModule; try { - sourceToModule = parseYangModelSources(sourceToStream.keySet()); + sourceToModule = parseYangModelSources(sourceToStream.keySet(), null); } catch (IOException | YangSyntaxErrorException e) { throw new YangParseException("Failed to parse yang data", e); } @@ -324,16 +328,29 @@ public final class YangParserImpl implements YangContextParser { return new SchemaContextImpl(modules, identifiersToSources); } - private Map parseYangModelSources(final Collection sources) throws IOException, - YangSyntaxErrorException { + public Collection buildModules(final Collection builders) { + Collection unsorted = resolveSubmodules(builders); + List sorted = ModuleDependencySort.sort(unsorted); + Map> modules = resolveModulesWithImports(sorted, null); + Map builderToModule = build(modules); + return builderToModule.values(); + } + + public SchemaContext assembleContext(final Collection modules) { + final Set sorted = new LinkedHashSet<>( + ModuleDependencySort.sort(modules.toArray(new Module[modules.size()]))); + return resolveSchemaContext(sorted); + } + + private Map parseYangModelSources(final Collection sources, final SchemaContext context) throws IOException, YangSyntaxErrorException { if (sources == null || sources.isEmpty()) { return Collections.emptyMap(); } - Map sourceToBuilder = resolveSources(sources); + Map sourceToBuilder = resolveSources(sources, context); // sort and check for duplicates List sorted = ModuleDependencySort.sort(sourceToBuilder.values()); - Map> modules = orderModules(sorted); + Map> modules = resolveModulesWithImports(sorted, null); Map builderToModule = build(modules); Map builderToSource = HashBiMap.create(sourceToBuilder).inverse(); sorted = ModuleDependencySort.sort(builderToModule.keySet()); @@ -357,14 +374,13 @@ public final class YangParserImpl implements YangContextParser { * @throws YangSyntaxErrorException */ // TODO: remove ByteSource result after removing YangModelParser - private Map resolveSources(final Collection streams) - throws IOException, YangSyntaxErrorException { - Map builders = parseSourcesToBuilders(streams); + private Map resolveSources(final Collection streams, final SchemaContext context) throws IOException, YangSyntaxErrorException { + Map builders = parseSourcesToBuilders(streams, context); return resolveSubmodules(builders); } - private Map parseSourcesToBuilders(final Collection sources) - throws IOException, YangSyntaxErrorException { + private Map parseSourcesToBuilders(final Collection sources, + final SchemaContext context) throws IOException, YangSyntaxErrorException { final ParseTreeWalker walker = new ParseTreeWalker(); final Map sourceToTree = parseYangSources(sources); final Map sourceToBuilder = new LinkedHashMap<>(); @@ -372,17 +388,20 @@ public final class YangParserImpl implements YangContextParser { // validate yang new YangModelBasicValidator(walker).validate(sourceToTree.values()); + Map> namespaceContext = BuilderUtils.createYangNamespaceContext( + sourceToTree.values(), Optional.fromNullable(context)); YangParserListenerImpl yangModelParser; for (Map.Entry entry : sourceToTree.entrySet()) { ByteSource source = entry.getKey(); String path = null; // TODO refactor to Optional - //TODO refactor so that path can be retrieved without opening stream: NamedInputStream -> NamedByteSource ? - try(InputStream stream = source.openStream()) { + // TODO refactor so that path can be retrieved without opening + // stream: NamedInputStream -> NamedByteSource ? + try (InputStream stream = source.openStream()) { if (stream instanceof NamedInputStream) { path = stream.toString(); } } - yangModelParser = new YangParserListenerImpl(path); + yangModelParser = new YangParserListenerImpl(namespaceContext, path); walker.walk(yangModelParser, entry.getValue()); ModuleBuilder moduleBuilder = yangModelParser.getModuleBuilder(); moduleBuilder.setSource(source); @@ -393,24 +412,54 @@ public final class YangParserImpl implements YangContextParser { private Map resolveSubmodules(final Map builders) { Map modules = new HashMap<>(); - Set submodules = new HashSet<>(); + Map> submodules = new HashMap<>(); for (Map.Entry entry : builders.entrySet()) { - ModuleBuilder moduleBuilder = entry.getValue(); - if (moduleBuilder.isSubmodule()) { - submodules.add(moduleBuilder); + ModuleBuilder builder = entry.getValue(); + if (builder.isSubmodule()) { + String submoduleName = builder.getName(); + TreeMap map = submodules.get(submoduleName); + if (map == null) { + map = new TreeMap<>(); + map.put(builder.getRevision(), builder); + submodules.put(submoduleName, map); + } else { + map.put(builder.getRevision(), builder); + } } else { - modules.put(entry.getKey(), moduleBuilder); + modules.put(entry.getKey(), builder); } } - Collection values = modules.values(); - for (ModuleBuilder submodule : submodules) { - for (ModuleBuilder module : values) { - if (module.getName().equals(submodule.getBelongsTo())) { - addSubmoduleToModule(submodule, module); + for (ModuleBuilder module : modules.values()) { + resolveSubmodules(module, submodules); + } + + return modules; + } + + private Collection resolveSubmodules(final Collection builders) { + Collection modules = new HashSet<>(); + Map> submodules = new HashMap<>(); + for (ModuleBuilder builder : builders) { + if (builder.isSubmodule()) { + String submoduleName = builder.getName(); + TreeMap map = submodules.get(submoduleName); + if (map == null) { + map = new TreeMap<>(); + map.put(builder.getRevision(), builder); + submodules.put(submoduleName, map); + } else { + map.put(builder.getRevision(), builder); } + } else { + modules.add(builder); } } + + for (ModuleBuilder module : modules) { + resolveSubmodules(module, submodules); + } + return modules; } @@ -418,35 +467,46 @@ public final class YangParserImpl implements YangContextParser { * Traverse collection of builders, find builders representing submodule and * add this submodule to its parent module. * - * @param builders - * collection of builders containing modules and submodules - * @return collection of module builders + * @param module + * current module + * @param submodules + * collection all loaded submodules + * @return collection of module builders with resolved submodules */ - private Collection resolveSubmodules(final Collection builders) { - Collection modules = new HashSet<>(); - Set submodules = new HashSet<>(); - for (ModuleBuilder moduleBuilder : builders) { - if (moduleBuilder.isSubmodule()) { - submodules.add(moduleBuilder); + private void resolveSubmodules(final ModuleBuilder module, + final Map> submodules) { + Map includes = module.getIncludedModules(); + for (Map.Entry entry : includes.entrySet()) { + TreeMap subs = submodules.get(entry.getKey()); + if (subs == null) { + throw new YangParseException("Failed to find references submodule " + entry.getKey() + " in module " + + module.getName()); + } + Date rev = entry.getValue(); + ModuleBuilder submodule; + if (rev == null) { + submodule = subs.lastEntry().getValue(); } else { - modules.add(moduleBuilder); + submodule = subs.get(rev); + // FIXME an exception should be thrown after issue with + // submodule's revisions and namespaces will be resolved + if (submodule == null) { + submodule = subs.lastEntry().getValue(); + } } - } - for (ModuleBuilder submodule : submodules) { - for (ModuleBuilder module : modules) { - if (module.getName().equals(submodule.getBelongsTo())) { - addSubmoduleToModule(submodule, module); - } + if (submodule.getIncludedModules().size() > 0) { + resolveSubmodules(submodule, submodules); } + addSubmoduleToModule(submodule, module); } - return modules; } private void addSubmoduleToModule(final ModuleBuilder submodule, final ModuleBuilder module) { + module.addSubmodule(submodule); submodule.setParent(module); module.getDirtyNodes().addAll(submodule.getDirtyNodes()); - module.getModuleImports().addAll(submodule.getModuleImports()); + module.getImports().putAll(submodule.getImports()); module.getAugments().addAll(submodule.getAugments()); module.getAugmentBuilders().addAll(submodule.getAugmentBuilders()); module.getAllAugments().addAll(submodule.getAllAugments()); @@ -476,10 +536,9 @@ public final class YangParserImpl implements YangContextParser { module.getAllUnknownNodes().addAll(submodule.getAllUnknownNodes()); } - private Map> resolveModuleBuilders( - final Collection yangFileStreams, final SchemaContext context) throws IOException, - YangSyntaxErrorException { - Map parsedBuilders = resolveSources(yangFileStreams); + private List resolveModuleBuilders(final Collection yangFileStreams, + final SchemaContext context) throws IOException, YangSyntaxErrorException { + Map parsedBuilders = resolveSources(yangFileStreams, context); ModuleBuilder[] builders = new ModuleBuilder[parsedBuilders.size()]; parsedBuilders.values().toArray(builders); @@ -490,33 +549,38 @@ public final class YangParserImpl implements YangContextParser { } else { sorted = ModuleDependencySort.sortWithContext(context, builders); } - return orderModules(sorted); + return sorted; } /** - * Order modules by name and revision. + * Order modules by namespace and revision. * * @param modules - * modules to order - * @return modules ordered by name and revision + * topologically sorted modules + * @return modules ordered by namespace and revision */ - private LinkedHashMap> orderModules(final List modules) { - final LinkedHashMap> result = new LinkedHashMap<>(); + private static LinkedHashMap> orderModules(final List modules) { + final LinkedHashMap> result = new LinkedHashMap<>(); for (final ModuleBuilder builder : modules) { if (builder == null) { continue; } - final String builderName = builder.getName(); - Date builderRevision = builder.getRevision(); - if (builderRevision == null) { - builderRevision = new Date(0L); + + URI ns = builder.getNamespace(); + Date rev = builder.getRevision(); + if (rev == null) { + rev = new Date(0); } - TreeMap builderByRevision = result.get(builderName); + + TreeMap builderByRevision = result.get(ns); if (builderByRevision == null) { builderByRevision = new TreeMap<>(); + builderByRevision.put(rev, builder); + result.put(ns, builderByRevision); + } else { + builderByRevision.put(rev, builder); } - builderByRevision.put(builderRevision, builder); - result.put(builderName, builderByRevision); + } return result; } @@ -534,7 +598,7 @@ public final class YangParserImpl implements YangContextParser { */ private void filterImports(final ModuleBuilder main, final Collection other, final Collection filtered) { - Set imports = main.getModuleImports(); + Map imports = main.getImports(); // if this is submodule, add parent to filtered and pick its imports if (main.isSubmodule()) { @@ -546,10 +610,10 @@ public final class YangParserImpl implements YangContextParser { } ModuleBuilder parent = dependencies.get(dependencies.firstKey()); filtered.add(parent); - imports.addAll(parent.getModuleImports()); + imports.putAll(parent.getImports()); } - for (ModuleImport mi : imports) { + for (ModuleImport mi : imports.values()) { for (ModuleBuilder builder : other) { if (mi.getModuleName().equals(builder.getModuleName())) { if (mi.getRevision() == null) { @@ -570,36 +634,35 @@ public final class YangParserImpl implements YangContextParser { } } - private Map parseYangSources(final Collection sources) throws IOException, - YangSyntaxErrorException { + private Map parseYangSources(final Collection sources) throws IOException, YangSyntaxErrorException { final Map trees = new HashMap<>(); for (ByteSource source : sources) { - trees.put(source, parseYangSource(source)); + try (InputStream stream = source.openStream()) { + trees.put(source, parseYangSource(stream)); + } } return trees; } - private YangContext parseYangSource(final ByteSource source) throws IOException, YangSyntaxErrorException { - try (InputStream stream = source.openStream()) { - final ANTLRInputStream input = new ANTLRInputStream(stream); - final YangLexer lexer = new YangLexer(input); - final CommonTokenStream tokens = new CommonTokenStream(lexer); - final YangParser parser = new YangParser(tokens); - parser.removeErrorListeners(); + public static YangContext parseYangSource(final InputStream stream) throws IOException, YangSyntaxErrorException { + final YangLexer lexer = new YangLexer(new ANTLRInputStream(stream)); + final CommonTokenStream tokens = new CommonTokenStream(lexer); + final YangParser parser = new YangParser(tokens); + parser.removeErrorListeners(); - final YangErrorListener errorListener = new YangErrorListener(); - parser.addErrorListener(errorListener); + final YangErrorListener errorListener = new YangErrorListener(); + parser.addErrorListener(errorListener); - final YangContext result = parser.yang(); - errorListener.validate(); + final YangContext result = parser.yang(); + errorListener.validate(); - return result; - } + return result; } /** - * Mini parser: This parsing context does not validate full YANG module, only - * parses header up to the revisions and imports. + * Mini parser: This parsing context does not validate full YANG module, + * only parses header up to the revisions and imports. + * * @see org.opendaylight.yangtools.yang.parser.impl.util.YangModelDependencyInfo */ public static YangContext parseStreamWithoutErrorListeners(final InputStream yangStream) { @@ -638,65 +701,18 @@ public final class YangParserImpl implements YangContextParser { * all loaded modules * @return modules mapped on their builders */ - private Map build(final Map> modules) { + private Map build(final Map> modules) { resolveDirtyNodes(modules); - resolveAugmentsTargetPath(modules, null); - resolveUsesTargetGrouping(modules, null); - resolveUsesForGroupings(modules, null); - resolveUsesForNodes(modules, null); - resolveAugments(modules, null); + resolveAugmentsTargetPath(modules); + resolveUsesTargetGrouping(modules); + resolveUsesForGroupings(modules); + resolveUsesForNodes(modules); + resolveAugments(modules); resolveIdentities(modules); - resolveDeviations(modules); - - // build - final Map result = new LinkedHashMap<>(); - for (Map.Entry> entry : modules.entrySet()) { - for (Map.Entry childEntry : entry.getValue().entrySet()) { - final ModuleBuilder moduleBuilder = childEntry.getValue(); - final Module module = moduleBuilder.build(); - result.put(moduleBuilder, module); - } - } - return result; - } - - /** - * Creates builder-to-module map based on given modules. Method first - * resolve unresolved type references, instantiate groupings through uses - * statements and perform augmentation. - * - * Node resolving must be performed in following order: - *
    - *
  1. - * unresolved type references
  2. - *
  3. - * uses in groupings
  4. - *
  5. - * uses in other nodes
  6. - *
  7. - * augments
  8. - *
- * - * @param modules - * all loaded modules - * @param context - * SchemaContext containing already resolved modules - * @return modules mapped on their builders - */ - private Map buildWithContext(final Map> modules, - final SchemaContext context) { - resolvedDirtyNodesWithContext(modules, context); - resolveAugmentsTargetPath(modules, context); - resolveUsesTargetGrouping(modules, context); - resolveUsesForGroupings(modules, context); - resolveUsesForNodes(modules, context); - resolveAugments(modules, context); - resolveIdentitiesWithContext(modules, context); - resolveDeviationsWithContext(modules, context); // build final Map result = new LinkedHashMap<>(); - for (Map.Entry> entry : modules.entrySet()) { + for (Map.Entry> entry : modules.entrySet()) { for (Map.Entry childEntry : entry.getValue().entrySet()) { final ModuleBuilder moduleBuilder = childEntry.getValue(); final Module module = moduleBuilder.build(); @@ -712,8 +728,8 @@ public final class YangParserImpl implements YangContextParser { * @param modules * all loaded modules */ - private void resolveDirtyNodes(final Map> modules) { - for (Map.Entry> entry : modules.entrySet()) { + private void resolveDirtyNodes(final Map> modules) { + for (Map.Entry> entry : modules.entrySet()) { for (Map.Entry childEntry : entry.getValue().entrySet()) { final ModuleBuilder module = childEntry.getValue(); resolveUnknownNodes(modules, module); @@ -722,25 +738,6 @@ public final class YangParserImpl implements YangContextParser { } } - /** - * Resolve all unresolved type references. - * - * @param modules - * all loaded modules - * @param context - * SchemaContext containing already resolved modules - */ - private void resolvedDirtyNodesWithContext(final Map> modules, - final SchemaContext context) { - for (Map.Entry> entry : modules.entrySet()) { - for (Map.Entry childEntry : entry.getValue().entrySet()) { - final ModuleBuilder module = childEntry.getValue(); - resolveUnknownNodesWithContext(modules, module, context); - resolveDirtyNodesWithContext(modules, module, context); - } - } - } - /** * Search for dirty nodes (node which contains UnknownType) and resolve * unknown types. @@ -750,7 +747,7 @@ public final class YangParserImpl implements YangContextParser { * @param module * current module */ - private void resolveDirtyNodes(final Map> modules, final ModuleBuilder module) { + private void resolveDirtyNodes(final Map> modules, final ModuleBuilder module) { final Set dirtyNodes = module.getDirtyNodes(); if (!dirtyNodes.isEmpty()) { for (TypeAwareBuilder nodeToResolve : dirtyNodes) { @@ -760,7 +757,7 @@ public final class YangParserImpl implements YangContextParser { } else if (nodeToResolve.getTypedef() instanceof IdentityrefTypeBuilder) { // special handling for identityref types IdentityrefTypeBuilder idref = (IdentityrefTypeBuilder) nodeToResolve.getTypedef(); - IdentitySchemaNodeBuilder identity = findBaseIdentity(modules, module, idref.getBaseString(), + IdentitySchemaNodeBuilder identity = findBaseIdentity(module, idref.getBaseString(), idref.getLine()); if (identity == null) { throw new YangParseException(module.getName(), idref.getLine(), "Failed to find base identity"); @@ -774,115 +771,65 @@ public final class YangParserImpl implements YangContextParser { } } - private void resolveDirtyNodesWithContext(final Map> modules, - final ModuleBuilder module, final SchemaContext context) { - final Set dirtyNodes = module.getDirtyNodes(); - if (!dirtyNodes.isEmpty()) { - for (TypeAwareBuilder nodeToResolve : dirtyNodes) { - if (nodeToResolve instanceof UnionTypeBuilder) { - // special handling for union types - resolveTypeUnionWithContext((UnionTypeBuilder) nodeToResolve, modules, module, context); - } else if (nodeToResolve.getTypedef() instanceof IdentityrefTypeBuilder) { - // special handling for identityref types - IdentityrefTypeBuilder idref = (IdentityrefTypeBuilder) nodeToResolve.getTypedef(); - IdentitySchemaNodeBuilder identity = findBaseIdentity(modules, module, idref.getBaseString(), - idref.getLine()); - idref.setBaseIdentity(identity); - nodeToResolve.setType(idref.build()); - } else { - resolveTypeWithContext(nodeToResolve, modules, module, context); - } - } - } - } - /** * Traverse through augmentations of modules and fix their child nodes * schema path. * * @param modules * all loaded modules - * @param context - * SchemaContext containing already resolved modules */ - private void resolveAugmentsTargetPath(final Map> modules, - final SchemaContext context) { + private void resolveAugmentsTargetPath(final Map> modules) { // collect augments from all loaded modules final List allAugments = new ArrayList<>(); - for (Map.Entry> entry : modules.entrySet()) { + for (Map.Entry> entry : modules.entrySet()) { for (Map.Entry inner : entry.getValue().entrySet()) { allAugments.addAll(inner.getValue().getAllAugments()); } } for (AugmentationSchemaBuilder augment : allAugments) { - setCorrectAugmentTargetPath(modules, augment, context); + setCorrectAugmentTargetPath(augment); } } /** * Find augment target and set correct schema path for all its child nodes. * - * @param modules - * all loaded modules * @param augment * augment to resolve - * @param context - * SchemaContext containing already resolved modules */ - private void setCorrectAugmentTargetPath(final Map> modules, - final AugmentationSchemaBuilder augment, final SchemaContext context) { - ModuleBuilder module = BuilderUtils.getParentModule(augment); - SchemaPath oldSchemaPath = augment.getTargetPath(); - List newPath = new ArrayList<>(); - + private void setCorrectAugmentTargetPath(final AugmentationSchemaBuilder augment) { Builder parent = augment.getParent(); - if (parent instanceof UsesNodeBuilder) { - DataNodeContainerBuilder usesParent = ((UsesNodeBuilder) parent).getParent(); - newPath.addAll(usesParent.getPath().getPath()); - - final QName baseQName = usesParent.getQName(); - final QNameModule qnm; - final String prefix; - if (baseQName == null) { - ModuleBuilder m = BuilderUtils.getParentModule(usesParent); - qnm = m.getQNameModule(); - prefix = m.getPrefix(); - } else { - qnm = baseQName.getModule(); - prefix = baseQName.getPrefix(); - } + final SchemaPath targetNodeSchemaPath; - for (QName qn : oldSchemaPath.getPathFromRoot()) { - newPath.add(QName.create(qnm, prefix, qn.getLocalName())); - } + if (parent instanceof UsesNodeBuilder) { + targetNodeSchemaPath = findUsesAugmentTargetNodePath(((UsesNodeBuilder) parent).getParent(), augment); } else { - Iterable oldPath = oldSchemaPath.getPathFromRoot(); - for (QName qn : oldPath) { - QNameModule qnm = module.getQNameModule(); - String localPrefix = qn.getPrefix(); - if (localPrefix != null && !localPrefix.isEmpty()) { - ModuleBuilder currentModule = BuilderUtils.findModuleFromBuilders(modules, module, localPrefix, - augment.getLine()); - if (currentModule == null) { - Module m = BuilderUtils.findModuleFromContext(context, module, localPrefix, augment.getLine()); - if (m == null) { - throw new YangParseException(module.getName(), augment.getLine(), "Module with prefix " - + localPrefix + " not found."); - } - qnm = m.getQNameModule(); - } else { - qnm = currentModule.getQNameModule(); - } - } - newPath.add(new QName(qnm.getNamespace(), qnm.getRevision(), localPrefix, qn.getLocalName())); - } + targetNodeSchemaPath = augment.getTargetPath(); } - augment.setTargetNodeSchemaPath(SchemaPath.create(newPath, true)); for (DataSchemaNodeBuilder childNode : augment.getChildNodeBuilders()) { - correctPathForAugmentNodes(childNode, augment.getTargetNodeSchemaPath()); + correctPathForAugmentNodes(childNode, targetNodeSchemaPath); + } + } + + private SchemaPath findUsesAugmentTargetNodePath(DataNodeContainerBuilder usesParent, + AugmentationSchemaBuilder augment) { + QName parentQName = usesParent.getQName(); + final QNameModule qnm; + if (parentQName == null) { + ModuleBuilder m = BuilderUtils.getParentModule(usesParent); + qnm = m.getQNameModule(); + } else { + qnm = parentQName.getModule(); + } + + SchemaPath path = usesParent.getPath(); + for (QName qname : augment.getTargetPath().getPathFromRoot()) { + path = path.createChild(QName.create(qnm, qname.getLocalName())); } + + return path; } /** @@ -919,11 +866,11 @@ public final class YangParserImpl implements YangContextParser { */ private void checkAugmentMandatoryNodes(final Collection augments) { for (AugmentationSchemaBuilder augment : augments) { - String augmentPrefix = augment.getTargetPath().getPathFromRoot().iterator().next().getPrefix(); + URI augmentTargetNs = augment.getTargetPath().getPathFromRoot().iterator().next().getNamespace(); + Date augmentTargetRev = augment.getTargetPath().getPathFromRoot().iterator().next().getRevision(); ModuleBuilder module = BuilderUtils.getParentModule(augment); - String modulePrefix = module.getPrefix(); - if (augmentPrefix == null || augmentPrefix.isEmpty() || augmentPrefix.equals(modulePrefix)) { + if (augmentTargetNs.equals(module.getNamespace()) && augmentTargetRev.equals(module.getRevision())) { continue; } @@ -941,33 +888,25 @@ public final class YangParserImpl implements YangContextParser { * Go through all augment definitions and resolve them. * * @param modules - * all loaded modules - * @param context - * SchemaContext containing already resolved modules + * all loaded modules topologically sorted (based on dependencies + * between each other) */ - private void resolveAugments(final Map> modules, final SchemaContext context) { + private void resolveAugments(final Map> modules) { List all = new ArrayList<>(); - for (Map.Entry> entry : modules.entrySet()) { + for (Map.Entry> entry : modules.entrySet()) { for (Map.Entry inner : entry.getValue().entrySet()) { all.add(inner.getValue()); } } - List sorted; - if (context == null) { - sorted = ModuleDependencySort.sort(all.toArray(new ModuleBuilder[all.size()])); - } else { - sorted = ModuleDependencySort.sortWithContext(context, all.toArray(new ModuleBuilder[all.size()])); - } - - for (ModuleBuilder mb : sorted) { + for (ModuleBuilder mb : all) { if (mb != null) { List augments = mb.getAllAugments(); checkAugmentMandatoryNodes(augments); - Collections.sort(augments, Comparators.AUGMENT_COMP); + Collections.sort(augments, Comparators.AUGMENT_BUILDER_COMP); for (AugmentationSchemaBuilder augment : augments) { if (!(augment.isResolved())) { - boolean resolved = resolveAugment(augment, mb, modules, context); + boolean resolved = resolveAugment(augment, mb, modules); if (!resolved) { throw new YangParseException(augment.getModuleName(), augment.getLine(), "Error in augment parsing: failed to find augment target: " + augment); @@ -987,12 +926,10 @@ public final class YangParserImpl implements YangContextParser { * current module * @param modules * all loaded modules - * @param context - * SchemaContext containing already resolved modules * @return true if augment process succeed */ private boolean resolveUsesAugment(final AugmentationSchemaBuilder augment, final ModuleBuilder module, - final Map> modules, final SchemaContext context) { + final Map> modules) { if (augment.isResolved()) { return true; } @@ -1000,20 +937,22 @@ public final class YangParserImpl implements YangContextParser { UsesNodeBuilder usesNode = (UsesNodeBuilder) augment.getParent(); DataNodeContainerBuilder parentNode = usesNode.getParent(); Optional potentialTargetNode; - SchemaPath resolvedTargetPath = augment.getTargetNodeSchemaPath(); + SchemaPath resolvedTargetPath = findUsesAugmentTargetNodePath(parentNode, augment); if (parentNode instanceof ModuleBuilder && resolvedTargetPath.isAbsolute()) { // Uses is directly used in module body, we lookup // We lookup in data namespace to find correct augmentation target potentialTargetNode = findSchemaNodeInModule(resolvedTargetPath, (ModuleBuilder) parentNode); } else { - // Uses is used in local context (be it data namespace or grouping namespace, + // Uses is used in local context (be it data namespace or grouping + // namespace, // since all nodes via uses are imported to localName, it is safe to // to proceed only with local names. // // Conflicting elements in other namespaces are still not present - // since resolveUsesAugment occurs before augmenting from external modules. + // since resolveUsesAugment occurs before augmenting from external + // modules. potentialTargetNode = Optional. fromNullable(findSchemaNode(augment.getTargetPath() - .getPath(), (SchemaNodeBuilder) parentNode)); + .getPathFromRoot(), (SchemaNodeBuilder) parentNode)); } if (potentialTargetNode.isPresent()) { @@ -1024,8 +963,11 @@ public final class YangParserImpl implements YangContextParser { augment.setResolved(true); return true; } else { - throw new YangParseException(module.getName(), augment.getLine(), String.format( - "Failed to resolve augment in uses. Invalid augment target: %s", potentialTargetNode)); + LOG.warn( + "Error in module {} at line {}: Unsupported augment target: {}. Augmentation process skipped.", + module.getName(), augment.getLine(), potentialTargetNode); + augment.setResolved(true); + return true; } } else { throw new YangParseException(module.getName(), augment.getLine(), String.format( @@ -1043,18 +985,16 @@ public final class YangParserImpl implements YangContextParser { * current module * @param modules * all loaded modules - * @param context - * SchemaContext containing already resolved modules * @return true if augment process succeed */ private boolean resolveAugment(final AugmentationSchemaBuilder augment, final ModuleBuilder module, - final Map> modules, final SchemaContext context) { + final Map> modules) { if (augment.isResolved()) { return true; } - QName targetPath = augment.getTargetPath().getPathFromRoot().iterator().next(); - ModuleBuilder targetModule = findTargetModule(targetPath, module, modules, context, augment.getLine()); + QName targetModuleName = augment.getTargetPath().getPathFromRoot().iterator().next(); + ModuleBuilder targetModule = BuilderUtils.findModule(targetModuleName, modules); if (targetModule == null) { throw new YangParseException(module.getModuleName(), augment.getLine(), "Failed to resolve augment " + augment); @@ -1063,148 +1003,44 @@ public final class YangParserImpl implements YangContextParser { return processAugmentation(augment, targetModule); } - /** - * Find module from loaded modules or from context based on given qname. If - * module is found in context, create wrapper over this module and add it to - * collection of loaded modules. - * - * @param qname - * @param module - * current module - * @param modules - * all loaded modules - * @param context - * schema context - * @param line - * current line - * @return - */ - private ModuleBuilder findTargetModule(final QName qname, final ModuleBuilder module, - final Map> modules, final SchemaContext context, final int line) { - ModuleBuilder targetModule; - - String prefix = qname.getPrefix(); - if (prefix == null || prefix.equals("")) { - targetModule = module; - } else { - targetModule = findModuleFromBuilders(modules, module, qname.getPrefix(), line); - } - - if (targetModule == null && context != null) { - Module m = findModuleFromContext(context, module, prefix, line); - targetModule = new ModuleBuilder(m); - DataSchemaNode firstNode = m.getDataChildByName(qname.getLocalName()); - DataSchemaNodeBuilder firstNodeWrapped = wrapChildNode(targetModule.getModuleName(), line, firstNode, - targetModule.getPath(), firstNode.getQName()); - targetModule.addChildNode(firstNodeWrapped); - - TreeMap map = new TreeMap<>(); - map.put(targetModule.getRevision(), targetModule); - modules.put(targetModule.getModuleName(), map); - } - - return targetModule; - } - - private ModuleBuilder findTargetModule(final String prefix, final ModuleBuilder module, - final Map> modules, final SchemaContext context, final int line) { - ModuleBuilder targetModule; - - if (prefix == null || prefix.equals("")) { - targetModule = module; - } else { - targetModule = findModuleFromBuilders(modules, module, prefix, line); - } - - if (targetModule == null && context != null) { - Module m = findModuleFromContext(context, module, prefix, line); - if (m != null) { - targetModule = new ModuleBuilder(m); - TreeMap map = new TreeMap<>(); - map.put(targetModule.getRevision(), targetModule); - modules.put(targetModule.getModuleName(), map); - } - } - - return targetModule; - } - /** * Go through identity statements defined in current module and resolve - * their 'base' statement if present. + * their 'base' statement. * * @param modules - * all modules - * @param module - * module being resolved + * all loaded modules */ - private void resolveIdentities(final Map> modules) { - for (Map.Entry> entry : modules.entrySet()) { + private void resolveIdentities(final Map> modules) { + for (Map.Entry> entry : modules.entrySet()) { for (Map.Entry inner : entry.getValue().entrySet()) { ModuleBuilder module = inner.getValue(); final Set identities = module.getAddedIdentities(); for (IdentitySchemaNodeBuilder identity : identities) { - final String baseIdentityName = identity.getBaseIdentityName(); - final int line = identity.getLine(); - if (baseIdentityName != null) { - IdentitySchemaNodeBuilder baseIdentity = findBaseIdentity(modules, module, baseIdentityName, - line); - if (baseIdentity == null) { - throw new YangParseException(module.getName(), identity.getLine(), - "Failed to find base identity"); - } else { - identity.setBaseIdentity(baseIdentity); - } - } + resolveIdentity(module, identity); } - } } } - /** - * Go through identity statements defined in current module and resolve - * their 'base' statement. Method tries to find base identity in given - * modules. If base identity is not found, method will search it in context. - * - * @param modules - * all loaded modules - * @param module - * current module - * @param context - * SchemaContext containing already resolved modules - */ - private void resolveIdentitiesWithContext(final Map> modules, - final SchemaContext context) { - for (Map.Entry> entry : modules.entrySet()) { - for (Map.Entry inner : entry.getValue().entrySet()) { - ModuleBuilder module = inner.getValue(); - final Set identities = module.getAddedIdentities(); - for (IdentitySchemaNodeBuilder identity : identities) { - final String baseIdentityName = identity.getBaseIdentityName(); - final int line = identity.getLine(); - if (baseIdentityName != null) { - - IdentitySchemaNodeBuilder result = null; - if (baseIdentityName.contains(":")) { - String[] splittedBase = baseIdentityName.split(":"); - if (splittedBase.length > 2) { - throw new YangParseException(module.getName(), line, - "Failed to parse identityref base: " + baseIdentityName); - } - String prefix = splittedBase[0]; - String name = splittedBase[1]; - ModuleBuilder dependentModule = findTargetModule(prefix, module, modules, context, line); - if (dependentModule != null) { - result = BuilderUtils.findIdentity(dependentModule.getAddedIdentities(), name); - } - } else { - result = BuilderUtils.findIdentity(module.getAddedIdentities(), baseIdentityName); - } - identity.setBaseIdentity(result); - } + private void resolveIdentity(final ModuleBuilder module, final IdentitySchemaNodeBuilder identity) { + final String baseIdentityName = identity.getBaseIdentityName(); + if (baseIdentityName != null) { + IdentitySchemaNodeBuilder result = null; + if (baseIdentityName.contains(":")) { + final int line = identity.getLine(); + String[] splittedBase = baseIdentityName.split(":"); + if (splittedBase.length > 2) { + throw new YangParseException(module.getName(), line, "Failed to parse identityref base: " + + baseIdentityName); } + String prefix = splittedBase[0]; + String name = splittedBase[1]; + ModuleBuilder dependentModule = BuilderUtils.getModuleByPrefix(module, prefix); + result = BuilderUtils.findIdentity(dependentModule.getAddedIdentities(), name); + } else { + result = BuilderUtils.findIdentity(module.getAddedIdentities(), baseIdentityName); } + identity.setBaseIdentity(result); } } @@ -1213,14 +1049,10 @@ public final class YangParserImpl implements YangContextParser { * * @param modules * all loaded modules - * @param context - * SchemaContext containing already resolved modules or null if - * context is not available */ - private void resolveUsesTargetGrouping(final Map> modules, - final SchemaContext context) { + private void resolveUsesTargetGrouping(final Map> modules) { final List allUses = new ArrayList<>(); - for (Map.Entry> entry : modules.entrySet()) { + for (Map.Entry> entry : modules.entrySet()) { for (Map.Entry inner : entry.getValue().entrySet()) { allUses.addAll(inner.getValue().getAllUsesNodes()); } @@ -1229,18 +1061,7 @@ public final class YangParserImpl implements YangContextParser { ModuleBuilder module = BuilderUtils.getParentModule(usesNode); final GroupingBuilder targetGroupingBuilder = GroupingUtils.getTargetGroupingFromModules(usesNode, modules, module); - if (targetGroupingBuilder == null) { - if (context == null) { - throw new YangParseException(module.getName(), usesNode.getLine(), "Referenced grouping '" - + usesNode.getGroupingPathAsString() + "' not found."); - } else { - GroupingDefinition targetGroupingDefinition = GroupingUtils.getTargetGroupingFromContext(usesNode, - module, context); - usesNode.setGroupingDefinition(targetGroupingDefinition); - } - } else { - usesNode.setGrouping(targetGroupingBuilder); - } + usesNode.setGrouping(targetGroupingBuilder); } } @@ -1249,13 +1070,10 @@ public final class YangParserImpl implements YangContextParser { * * @param modules * all loaded modules - * @param context - * SchemaContext containing already resolved modules */ - private void resolveUsesForGroupings(final Map> modules, - final SchemaContext context) { + private void resolveUsesForGroupings(final Map> modules) { final Set allGroupings = new HashSet<>(); - for (Map.Entry> entry : modules.entrySet()) { + for (Map.Entry> entry : modules.entrySet()) { for (Map.Entry inner : entry.getValue().entrySet()) { ModuleBuilder module = inner.getValue(); allGroupings.addAll(module.getAllGroupings()); @@ -1266,7 +1084,7 @@ public final class YangParserImpl implements YangContextParser { List usesNodes = new ArrayList<>(GroupingSort.getAllUsesNodes(gb)); Collections.sort(usesNodes, new GroupingUtils.UsesComparator()); for (UsesNodeBuilder usesNode : usesNodes) { - resolveUses(usesNode, modules, context); + resolveUses(usesNode, modules); } } } @@ -1276,18 +1094,15 @@ public final class YangParserImpl implements YangContextParser { * * @param modules * all loaded modules - * @param context - * SchemaContext containing already resolved modules */ - private void resolveUsesForNodes(final Map> modules, - final SchemaContext context) { - for (Map.Entry> entry : modules.entrySet()) { + private void resolveUsesForNodes(final Map> modules) { + for (Map.Entry> entry : modules.entrySet()) { for (Map.Entry inner : entry.getValue().entrySet()) { ModuleBuilder module = inner.getValue(); List usesNodes = module.getAllUsesNodes(); Collections.sort(usesNodes, new GroupingUtils.UsesComparator()); for (UsesNodeBuilder usesNode : usesNodes) { - resolveUses(usesNode, modules, context); + resolveUses(usesNode, modules); } } } @@ -1301,310 +1116,111 @@ public final class YangParserImpl implements YangContextParser { * uses node to resolve * @param modules * all loaded modules - * @param context - * SchemaContext containing already resolved modules */ - private void resolveUses(final UsesNodeBuilder usesNode, final Map> modules, - final SchemaContext context) { + private void resolveUses(final UsesNodeBuilder usesNode, final Map> modules) { if (!usesNode.isResolved()) { DataNodeContainerBuilder parent = usesNode.getParent(); ModuleBuilder module = BuilderUtils.getParentModule(parent); GroupingBuilder target = GroupingUtils.getTargetGroupingFromModules(usesNode, modules, module); - if (target == null) { - resolveUsesWithContext(usesNode); - usesNode.setResolved(true); - for (AugmentationSchemaBuilder augment : usesNode.getAugmentations()) { - resolveUsesAugment(augment, module, modules, context); - } - } else { - parent.getChildNodeBuilders().addAll(target.instantiateChildNodes(parent)); - parent.getTypeDefinitionBuilders().addAll(target.instantiateTypedefs(parent)); - parent.getGroupingBuilders().addAll(target.instantiateGroupings(parent)); - parent.getUnknownNodes().addAll(target.instantiateUnknownNodes(parent)); - usesNode.setResolved(true); - for (AugmentationSchemaBuilder augment : usesNode.getAugmentations()) { - resolveUsesAugment(augment, module, modules, context); - } + + int index = nodeAfterUsesIndex(usesNode); + List targetNodes = target.instantiateChildNodes(parent); + for (DataSchemaNodeBuilder targetNode : targetNodes) { + parent.addChildNode(index++, targetNode); + } + parent.getTypeDefinitionBuilders().addAll(target.instantiateTypedefs(parent)); + parent.getGroupingBuilders().addAll(target.instantiateGroupings(parent)); + parent.getUnknownNodes().addAll(target.instantiateUnknownNodes(parent)); + usesNode.setResolved(true); + for (AugmentationSchemaBuilder augment : usesNode.getAugmentations()) { + resolveUsesAugment(augment, module, modules); } + GroupingUtils.performRefine(usesNode); } } - /** - * Copy target grouping child nodes to current location with new namespace. - * - * @param usesNode - * uses node to resolve - * @param modules - * all loaded modules - * @param context - * SchemaContext containing already resolved modules - */ - private void resolveUsesWithContext(final UsesNodeBuilder usesNode) { - final int line = usesNode.getLine(); + private int nodeAfterUsesIndex(final UsesNodeBuilder usesNode) { DataNodeContainerBuilder parent = usesNode.getParent(); - ModuleBuilder module = BuilderUtils.getParentModule(parent); - SchemaPath parentPath; - - final QName parentQName; - if (parent instanceof AugmentationSchemaBuilder || parent instanceof ModuleBuilder) { - parentQName = QName.create(module.getQNameModule(), module.getPrefix(), "dummy"); - if (parent instanceof AugmentationSchemaBuilder) { - parentPath = ((AugmentationSchemaBuilder) parent).getTargetNodeSchemaPath(); - } else { - parentPath = parent.getPath(); - } - } else { - parentQName = parent.getQName(); - parentPath = parent.getPath(); - } + int usesLine = usesNode.getLine(); - GroupingDefinition gd = usesNode.getGroupingDefinition(); - - Set childNodes = wrapChildNodes(module.getModuleName(), line, gd.getChildNodes(), - parentPath, parentQName); - parent.getChildNodeBuilders().addAll(childNodes); - for (DataSchemaNodeBuilder childNode : childNodes) { - setNodeAddedByUses(childNode); + List childNodes = parent.getChildNodeBuilders(); + if (childNodes.isEmpty()) { + return 0; } - Set typedefs = wrapTypedefs(module.getModuleName(), line, gd, parentPath, parentQName); - parent.getTypeDefinitionBuilders().addAll(typedefs); - for (TypeDefinitionBuilder typedef : typedefs) { - setNodeAddedByUses(typedef); + DataSchemaNodeBuilder nextNodeAfterUses = null; + for (DataSchemaNodeBuilder childNode : childNodes) { + if (!(childNode.isAddedByUses()) && !(childNode.isAugmenting())) { + if (childNode.getLine() > usesLine) { + nextNodeAfterUses = childNode; + break; + } + } } - Set groupings = wrapGroupings(module.getModuleName(), line, usesNode.getGroupingDefinition() - .getGroupings(), parentPath, parentQName); - parent.getGroupingBuilders().addAll(groupings); - for (GroupingBuilder gb : groupings) { - setNodeAddedByUses(gb); + // uses is declared after child nodes + if (nextNodeAfterUses == null) { + return childNodes.size(); } - List unknownNodes = wrapUnknownNodes(module.getModuleName(), line, - gd.getUnknownSchemaNodes(), parentPath, parentQName); - parent.getUnknownNodes().addAll(unknownNodes); - for (UnknownSchemaNodeBuilder un : unknownNodes) { - un.setAddedByUses(true); - } + return parent.getChildNodeBuilders().indexOf(nextNodeAfterUses); } /** - * Try to find extension builder describing this unknown node and assign it - * to unknown node builder. + * Try to find extension describing this unknown node and assign it to + * unknown node builder. * * @param modules * all loaded modules * @param module * current module */ - private void resolveUnknownNodes(final Map> modules, final ModuleBuilder module) { + private void resolveUnknownNodes(final Map> modules, final ModuleBuilder module) { for (UnknownSchemaNodeBuilder usnb : module.getAllUnknownNodes()) { QName nodeType = usnb.getNodeType(); - try { - ModuleBuilder dependentModule = findModuleFromBuilders(modules, module, nodeType.getPrefix(), - usnb.getLine()); - for (ExtensionBuilder extension : dependentModule.getAddedExtensions()) { - if (extension.getQName().getLocalName().equals(nodeType.getLocalName())) { - usnb.setNodeType(extension.getQName()); - usnb.setExtensionBuilder(extension); - break; - } - } - } catch (YangParseException e) { - throw new YangParseException(module.getName(), usnb.getLine(), "Failed to resolve node " + usnb - + ": no such extension definition found.", e); + String localName = usnb.getNodeType().getLocalName(); + ModuleBuilder dependentModule = BuilderUtils.findModule(nodeType, modules); + + if (dependentModule == null) { + LOG.warn( + "Error in module {} at line {}: Failed to resolve node {}: no such extension definition found.", + module.getName(), usnb.getLine(), usnb); + continue; } - } - } - /** - * Try to find extension builder describing this unknown node and assign it - * to unknown node builder. If extension is not found in loaded modules, try - * to find it in context. - * - * @param modules - * all loaded modules - * @param module - * current module - * @param context - * SchemaContext containing already resolved modules - */ - private void resolveUnknownNodesWithContext(final Map> modules, - final ModuleBuilder module, final SchemaContext context) { - for (UnknownSchemaNodeBuilder usnb : module.getAllUnknownNodes()) { - QName nodeType = usnb.getNodeType(); - try { - ModuleBuilder dependentModuleBuilder = findModuleFromBuilders(modules, module, nodeType.getPrefix(), - usnb.getLine()); - - if (dependentModuleBuilder == null) { - Module dependentModule = findModuleFromContext(context, module, nodeType.getPrefix(), - usnb.getLine()); - for (ExtensionDefinition e : dependentModule.getExtensionSchemaNodes()) { - if (e.getQName().getLocalName().equals(nodeType.getLocalName())) { - usnb.setNodeType(new QName(e.getQName().getNamespace(), e.getQName().getRevision(), - nodeType.getPrefix(), e.getQName().getLocalName())); - usnb.setExtensionDefinition(e); - break; - } - } + ExtensionBuilder extBuilder = findExtBuilder(localName, dependentModule.getAddedExtensions()); + if (extBuilder == null) { + ExtensionDefinition extDef = findExtDef(localName, dependentModule.getExtensions()); + if (extDef == null) { + LOG.warn( + "Error in module {} at line {}: Failed to resolve node {}: no such extension definition found.", + module.getName(), usnb.getLine(), usnb); } else { - for (ExtensionBuilder extension : dependentModuleBuilder.getAddedExtensions()) { - if (extension.getQName().getLocalName().equals(nodeType.getLocalName())) { - usnb.setExtensionBuilder(extension); - break; - } - } + usnb.setExtensionDefinition(extDef); } - - } catch (YangParseException e) { - throw new YangParseException(module.getName(), usnb.getLine(), "Failed to resolve node " + usnb - + ": no such extension definition found.", e); - } - - } - } - - /** - * Traverse through modules and resolve their deviation statements. - * - * @param modules - * all loaded modules - */ - private void resolveDeviations(final Map> modules) { - for (Map.Entry> entry : modules.entrySet()) { - for (Map.Entry inner : entry.getValue().entrySet()) { - ModuleBuilder b = inner.getValue(); - resolveDeviation(modules, b); - } - } - } - - /** - * Traverse through module and resolve its deviation statements. - * - * @param modules - * all loaded modules - * @param module - * module in which resolve deviations - */ - private void resolveDeviation(final Map> modules, final ModuleBuilder module) { - for (DeviationBuilder dev : module.getDeviationBuilders()) { - int line = dev.getLine(); - SchemaPath targetPath = dev.getTargetPath(); - Iterable path = targetPath.getPathFromRoot(); - QName q0 = path.iterator().next(); - String prefix = q0.getPrefix(); - if (prefix == null) { - prefix = module.getPrefix(); - } - - ModuleBuilder dependentModuleBuilder = findModuleFromBuilders(modules, module, prefix, line); - processDeviation(dev, dependentModuleBuilder, path, module); - } - } - - /** - * Traverse through modules and resolve their deviation statements with - * given context. - * - * @param modules - * all loaded modules - * @param context - * already resolved context - */ - private void resolveDeviationsWithContext(final Map> modules, - final SchemaContext context) { - for (Map.Entry> entry : modules.entrySet()) { - for (Map.Entry inner : entry.getValue().entrySet()) { - ModuleBuilder b = inner.getValue(); - resolveDeviationWithContext(modules, b, context); + } else { + usnb.setExtensionBuilder(extBuilder); } } } - /** - * Traverse through module and resolve its deviation statements with given - * context. - * - * @param modules - * all loaded modules - * @param module - * module in which resolve deviations - * @param context - * already resolved context - */ - private void resolveDeviationWithContext(final Map> modules, - final ModuleBuilder module, final SchemaContext context) { - for (DeviationBuilder dev : module.getDeviationBuilders()) { - int line = dev.getLine(); - SchemaPath targetPath = dev.getTargetPath(); - Iterable path = targetPath.getPathFromRoot(); - QName q0 = path.iterator().next(); - String prefix = q0.getPrefix(); - if (prefix == null) { - prefix = module.getPrefix(); - } - - ModuleBuilder dependentModuleBuilder = findModuleFromBuilders(modules, module, prefix, line); - if (dependentModuleBuilder == null) { - Object currentParent = findModuleFromContext(context, module, prefix, line); - - for (QName q : path) { - if (currentParent == null) { - throw new YangParseException(module.getName(), line, FAIL_DEVIATION_TARGET); - } - String name = q.getLocalName(); - if (currentParent instanceof DataNodeContainer) { - currentParent = ((DataNodeContainer) currentParent).getDataChildByName(name); - } - } - - if (currentParent == null) { - throw new YangParseException(module.getName(), line, FAIL_DEVIATION_TARGET); - } - if (currentParent instanceof SchemaNode) { - dev.setTargetPath(((SchemaNode) currentParent).getPath()); - } - - } else { - processDeviation(dev, dependentModuleBuilder, path, module); + private ExtensionBuilder findExtBuilder(final String name, final Collection extensions) { + for (ExtensionBuilder extension : extensions) { + if (extension.getQName().getLocalName().equals(name)) { + return extension; } } + return null; } - /** - * Correct deviation target path in deviation builder. - * - * @param dev - * deviation - * @param dependentModuleBuilder - * module containing deviation target - * @param path - * current deviation target path - * @param module - * current module - */ - private void processDeviation(final DeviationBuilder dev, final ModuleBuilder dependentModuleBuilder, - final Iterable path, final ModuleBuilder module) { - final int line = dev.getLine(); - Builder currentParent = dependentModuleBuilder; - - for (QName q : path) { - if (currentParent == null) { - throw new YangParseException(module.getName(), line, FAIL_DEVIATION_TARGET); - } - String name = q.getLocalName(); - if (currentParent instanceof DataNodeContainerBuilder) { - currentParent = ((DataNodeContainerBuilder) currentParent).getDataChildByName(name); + private ExtensionDefinition findExtDef(final String name, final Collection extensions) { + for (ExtensionDefinition extension : extensions) { + if (extension.getQName().getLocalName().equals(name)) { + return extension; } } - - if (!(currentParent instanceof SchemaNodeBuilder)) { - throw new YangParseException(module.getName(), line, FAIL_DEVIATION_TARGET); - } - dev.setTargetPath(((SchemaNodeBuilder) currentParent).getPath()); + return null; } }