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=b25986d34db17c3b1fb089c331f525b9df9bc54c;hb=42abb28b99a02f9580f4676ce5c315628e5bcd24;hp=25ace683009ac9f49d72e74458b353f1679450f9;hpb=8b2d88f91744ed2ec60b1d800d3c7b89de18310b;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 25ace68300..b25986d34d 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 @@ -1,5 +1,6 @@ /* - * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. + * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html @@ -9,28 +10,20 @@ 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.findTargetNode; 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.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 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; @@ -41,11 +34,10 @@ import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.NavigableMap; 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; @@ -55,12 +47,17 @@ 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.ChoiceCaseNode; +import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode; +import org.opendaylight.yangtools.yang.model.api.ContainerSchemaNode; +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.ListSchemaNode; 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; @@ -73,20 +70,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; @@ -96,11 +90,13 @@ import org.opendaylight.yangtools.yang.parser.util.YangParseException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +/** + * @deprecated Pre-Beryllium implementation, scheduled for removal. + */ +@Deprecated @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() { @@ -118,8 +114,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"); @@ -141,7 +136,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<>(); @@ -151,7 +146,7 @@ public final class YangParserImpl implements YangContextParser { // module builders sorted by dependencies List sortedBuilders = ModuleDependencySort.sort(resolved); - LinkedHashMap> modules = resolveModulesWithImports(sortedBuilders, null); + Map> modules = resolveModulesWithImports(sortedBuilders, null); Collection unsorted = build(modules).values(); Set result = new LinkedHashSet<>( ModuleDependencySort.sort(unsorted.toArray(new Module[unsorted.size()]))); @@ -205,12 +200,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 @@ -232,7 +223,7 @@ public final class YangParserImpl implements YangContextParser { } final List sorted = resolveModuleBuilders(sources, context); - final Map> modules = resolveModulesWithImports(sorted, context); + final Map> modules = resolveModulesWithImports(sorted, context); final Set unsorted = new LinkedHashSet<>(build(modules).values()); if (context != null) { @@ -247,22 +238,22 @@ public final class YangParserImpl implements YangContextParser { return resolveSchemaContext(result); } - private LinkedHashMap> resolveModulesWithImports(final List sorted, + private static Map> resolveModulesWithImports(final List sorted, final SchemaContext context) { - final LinkedHashMap> modules = orderModules(sorted); + final Map> modules = orderModules(sorted); for (ModuleBuilder module : sorted) { if (module != null) { for (ModuleImport imp : module.getImports().values()) { String prefix = imp.getPrefix(); - ModuleBuilder targetModule = findModuleFromBuilders(modules, module, prefix, 0); + ModuleBuilder targetModule = BuilderUtils.findModuleFromBuilders(imp, sorted); if (targetModule == null) { Module result = findModuleFromContext(context, module, prefix, 0); targetModule = new ModuleBuilder(result); - TreeMap map = modules.get(prefix); + NavigableMap map = modules.get(targetModule.getNamespace()); if (map == null) { map = new TreeMap<>(); map.put(targetModule.getRevision(), targetModule); - modules.put(targetModule.getName(), map); + modules.put(targetModule.getNamespace(), map); } else { map.put(targetModule.getRevision(), targetModule); } @@ -293,7 +284,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); } @@ -323,7 +314,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); } @@ -346,16 +337,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 = resolveModulesWithImports(sorted, null); + Map> modules = resolveModulesWithImports(sorted, null); Map builderToModule = build(modules); Map builderToSource = HashBiMap.create(sourceToBuilder).inverse(); sorted = ModuleDependencySort.sort(builderToModule.keySet()); @@ -379,14 +383,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 static 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<>(); @@ -394,6 +397,8 @@ 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(); @@ -405,7 +410,7 @@ public final class YangParserImpl implements YangContextParser { path = stream.toString(); } } - yangModelParser = new YangParserListenerImpl(path); + yangModelParser = new YangParserListenerImpl(namespaceContext, path); walker.walk(yangModelParser, entry.getValue()); ModuleBuilder moduleBuilder = yangModelParser.getModuleBuilder(); moduleBuilder.setSource(source); @@ -416,24 +421,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(); + NavigableMap 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(); + NavigableMap 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; } @@ -441,32 +476,43 @@ 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()) { + NavigableMap 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().isEmpty()) { + resolveSubmodules(submodule, submodules); } + addSubmoduleToModule(submodule, module); } - return modules; } - private void addSubmoduleToModule(final ModuleBuilder submodule, final ModuleBuilder module) { + private static void addSubmoduleToModule(final ModuleBuilder submodule, final ModuleBuilder module) { + module.addSubmodule(submodule); submodule.setParent(module); module.getDirtyNodes().addAll(submodule.getDirtyNodes()); module.getImports().putAll(submodule.getImports()); @@ -501,7 +547,7 @@ public final class YangParserImpl implements YangContextParser { private List resolveModuleBuilders(final Collection yangFileStreams, final SchemaContext context) throws IOException, YangSyntaxErrorException { - Map parsedBuilders = resolveSources(yangFileStreams); + Map parsedBuilders = resolveSources(yangFileStreams, context); ModuleBuilder[] builders = new ModuleBuilder[parsedBuilders.size()]; parsedBuilders.values().toArray(builders); @@ -516,31 +562,34 @@ public final class YangParserImpl implements YangContextParser { } /** - * Order modules by name and revision. + * Order modules by namespace and revision. * * @param modules * topologically sorted modules - * @return modules ordered by name and revision + * @return modules ordered by namespace and revision */ - private LinkedHashMap> orderModules(final List modules) { - final LinkedHashMap> result = new LinkedHashMap<>(); + private static Map> orderModules(final List modules) { + final Map> 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); + + NavigableMap builderByRevision = result.get(ns); if (builderByRevision == null) { builderByRevision = new TreeMap<>(); - builderByRevision.put(builderRevision, builder); - result.put(builderName, builderByRevision); + builderByRevision.put(rev, builder); + result.put(ns, builderByRevision); } else { - builderByRevision.put(builderRevision, builder); + builderByRevision.put(rev, builder); } + } return result; } @@ -562,7 +611,7 @@ public final class YangParserImpl implements YangContextParser { // if this is submodule, add parent to filtered and pick its imports if (main.isSubmodule()) { - TreeMap dependencies = new TreeMap<>(); + NavigableMap dependencies = new TreeMap<>(); for (ModuleBuilder mb : other) { if (mb.getName().equals(main.getBelongsTo())) { dependencies.put(mb.getRevision(), mb); @@ -582,11 +631,9 @@ public final class YangParserImpl implements YangContextParser { filterImports(builder, other, filtered); } } else { - if (mi.getRevision().equals(builder.getRevision())) { - if (!filtered.contains(builder)) { - filtered.add(builder); - filterImports(builder, other, filtered); - } + if (!filtered.contains(builder) && mi.getRevision().equals(builder.getRevision())) { + filtered.add(builder); + filterImports(builder, other, filtered); } } } @@ -594,37 +641,37 @@ public final class YangParserImpl implements YangContextParser { } } - private Map parseYangSources(final Collection sources) throws IOException, - YangSyntaxErrorException { + private static 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. * + * @param yangStream input stream containing a yang module + * @return new instance of YangContext * @see org.opendaylight.yangtools.yang.parser.impl.util.YangModelDependencyInfo */ public static YangContext parseStreamWithoutErrorListeners(final InputStream yangStream) { @@ -663,7 +710,7 @@ 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); resolveUsesTargetGrouping(modules); @@ -671,11 +718,11 @@ public final class YangParserImpl implements YangContextParser { resolveUsesForNodes(modules); resolveAugments(modules); resolveIdentities(modules); - resolveDeviations(modules); + checkChoiceCasesForDuplicityQNames(modules); // 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(); @@ -691,8 +738,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 static 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); @@ -710,7 +757,7 @@ public final class YangParserImpl implements YangContextParser { * @param module * current module */ - private void resolveDirtyNodes(final Map> modules, final ModuleBuilder module) { + private static void resolveDirtyNodes(final Map> modules, final ModuleBuilder module) { final Set dirtyNodes = module.getDirtyNodes(); if (!dirtyNodes.isEmpty()) { for (TypeAwareBuilder nodeToResolve : dirtyNodes) { @@ -720,7 +767,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"); @@ -741,85 +788,58 @@ public final class YangParserImpl implements YangContextParser { * @param modules * all loaded modules */ - private void resolveAugmentsTargetPath(final Map> modules) { + 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); + 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 */ - private void setCorrectAugmentTargetPath(final Map> modules, - final AugmentationSchemaBuilder augment) { - ModuleBuilder module = BuilderUtils.getParentModule(augment); - final SchemaPath newSchemaPath; - + private void setCorrectAugmentTargetPath(final AugmentationSchemaBuilder augment) { Builder parent = augment.getParent(); + final SchemaPath targetNodeSchemaPath; + if (parent instanceof UsesNodeBuilder) { - DataNodeContainerBuilder usesParent = ((UsesNodeBuilder) parent).getParent(); - - QName baseQName = usesParent.getQName(); - final QNameModule qnm; - String prefix; - if (baseQName == null) { - ModuleBuilder m = BuilderUtils.getParentModule(usesParent); - qnm = m.getQNameModule(); - prefix = m.getPrefix(); - } else { - qnm = baseQName.getModule(); - prefix = baseQName.getPrefix(); - } + targetNodeSchemaPath = findUsesAugmentTargetNodePath(((UsesNodeBuilder) parent).getParent(), augment); + } else { + targetNodeSchemaPath = augment.getTargetPath(); + } - SchemaPath s = usesParent.getPath(); - for (QName qn : augment.getTargetPath().getPathFromRoot()) { - s = s.createChild(QName.create(qnm, prefix, qn.getLocalName())); - } + for (DataSchemaNodeBuilder childNode : augment.getChildNodeBuilders()) { + correctPathForAugmentNodes(childNode, targetNodeSchemaPath); + } + } - newSchemaPath = s; + private static SchemaPath findUsesAugmentTargetNodePath(final DataNodeContainerBuilder usesParent, + final AugmentationSchemaBuilder augment) { + QName parentQName = usesParent.getQName(); + final QNameModule qnm; + if (parentQName == null) { + ModuleBuilder m = BuilderUtils.getParentModule(usesParent); + qnm = m.getQNameModule(); } else { - final List newPath = new ArrayList<>(); - - for (QName qn : augment.getTargetPath().getPathFromRoot()) { - QNameModule qnm = module.getQNameModule(); - String localPrefix = qn.getPrefix(); - if (localPrefix != null && !localPrefix.isEmpty()) { - ModuleBuilder currentModule = BuilderUtils.getModuleByPrefix(module, localPrefix); - if (currentModule == null) { - throw new YangParseException(module.getName(), augment.getLine(), "Module with prefix " - + localPrefix + " not found."); - } - qnm = currentModule.getQNameModule(); - } - newPath.add(QName.create(qnm, localPrefix, qn.getLocalName())); - } - - /* - * FIXME: this method of SchemaPath construction is highly ineffective. - * It would be great if we could actually dive into the context, - * find the actual target node and reuse its SchemaPath. Can we - * do that? - */ - newSchemaPath = SchemaPath.create(newPath, true); + qnm = parentQName.getModule(); } - augment.setTargetNodeSchemaPath(newSchemaPath); - for (DataSchemaNodeBuilder childNode : augment.getChildNodeBuilders()) { - correctPathForAugmentNodes(childNode, augment.getTargetNodeSchemaPath()); + SchemaPath path = usesParent.getPath(); + for (QName qname : augment.getTargetPath().getPathFromRoot()) { + path = path.createChild(QName.create(qnm, qname.getLocalName())); } + + return path; } /** @@ -854,13 +874,13 @@ public final class YangParserImpl implements YangContextParser { * @param augments * augments to check */ - private void checkAugmentMandatoryNodes(final Collection augments) { + private static 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; } @@ -881,9 +901,9 @@ public final class YangParserImpl implements YangContextParser { * all loaded modules topologically sorted (based on dependencies * between each other) */ - private void resolveAugments(final Map> modules) { + private static 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()); } @@ -918,8 +938,8 @@ public final class YangParserImpl implements YangContextParser { * all loaded modules * @return true if augment process succeed */ - private boolean resolveUsesAugment(final AugmentationSchemaBuilder augment, final ModuleBuilder module, - final Map> modules) { + private static boolean resolveUsesAugment(final AugmentationSchemaBuilder augment, final ModuleBuilder module, + final Map> modules) { if (augment.isResolved()) { return true; } @@ -927,7 +947,7 @@ 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 @@ -941,8 +961,8 @@ public final class YangParserImpl implements YangContextParser { // Conflicting elements in other namespaces are still not present // since resolveUsesAugment occurs before augmenting from external // modules. - potentialTargetNode = Optional. fromNullable(findSchemaNode(augment.getTargetPath() - .getPath(), (SchemaNodeBuilder) parentNode)); + potentialTargetNode = Optional. fromNullable(findTargetNode(augment.getTargetPath() + .getPathFromRoot(), parentNode)); } if (potentialTargetNode.isPresent()) { @@ -953,8 +973,12 @@ 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); + augment.setUnsupportedTarget(true); + return true; } } else { throw new YangParseException(module.getName(), augment.getLine(), String.format( @@ -974,14 +998,14 @@ public final class YangParserImpl implements YangContextParser { * all loaded modules * @return true if augment process succeed */ - private boolean resolveAugment(final AugmentationSchemaBuilder augment, final ModuleBuilder module, - final Map> modules) { + private static boolean resolveAugment(final AugmentationSchemaBuilder augment, final ModuleBuilder module, + final Map> modules) { if (augment.isResolved()) { return true; } QName targetModuleName = augment.getTargetPath().getPathFromRoot().iterator().next(); - ModuleBuilder targetModule = BuilderUtils.getModuleByPrefix(module, targetModuleName.getPrefix()); + ModuleBuilder targetModule = BuilderUtils.findModule(targetModuleName, modules); if (targetModule == null) { throw new YangParseException(module.getModuleName(), augment.getLine(), "Failed to resolve augment " + augment); @@ -997,19 +1021,19 @@ public final class YangParserImpl implements YangContextParser { * @param modules * all loaded modules */ - private void resolveIdentities(final Map> modules) { - for (Map.Entry> entry : modules.entrySet()) { + private static 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) { - resolveIdentity(modules, module, identity); + resolveIdentity(module, identity); } } } } - private void resolveIdentity(final Map> modules, final ModuleBuilder module, + private static void resolveIdentity(final ModuleBuilder module, final IdentitySchemaNodeBuilder identity) { final String baseIdentityName = identity.getBaseIdentityName(); if (baseIdentityName != null) { @@ -1018,15 +1042,34 @@ public final class YangParserImpl implements YangContextParser { 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); + 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); + + if (prefix.equals(module.getPrefix()) + && name.equals(identity.getQName().getLocalName())) { + throw new YangParseException(module.getName(), + identity.getLine(), + "Failed to parse base, identity name equals base identity name: " + + baseIdentityName); + } + + ModuleBuilder dependentModule = BuilderUtils.getModuleByPrefix( + module, prefix); + result = BuilderUtils.findIdentity( + dependentModule.getAddedIdentities(), name); } else { - result = BuilderUtils.findIdentity(module.getAddedIdentities(), baseIdentityName); + if (baseIdentityName.equals(identity.getQName().getLocalName())) { + throw new YangParseException(module.getName(), + identity.getLine(), + "Failed to parse base, identity name equals base identity name: " + + baseIdentityName); + } + result = BuilderUtils.findIdentity(module.getAddedIdentities(), + baseIdentityName); } identity.setBaseIdentity(result); } @@ -1038,9 +1081,9 @@ public final class YangParserImpl implements YangContextParser { * @param modules * all loaded modules */ - private void resolveUsesTargetGrouping(final Map> modules) { + private static 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()); } @@ -1049,10 +1092,6 @@ public final class YangParserImpl implements YangContextParser { ModuleBuilder module = BuilderUtils.getParentModule(usesNode); final GroupingBuilder targetGroupingBuilder = GroupingUtils.getTargetGroupingFromModules(usesNode, modules, module); - if (targetGroupingBuilder == null) { - throw new YangParseException(module.getName(), usesNode.getLine(), "Referenced grouping '" - + usesNode.getGroupingPathAsString() + "' not found."); - } usesNode.setGrouping(targetGroupingBuilder); } } @@ -1063,9 +1102,9 @@ public final class YangParserImpl implements YangContextParser { * @param modules * all loaded modules */ - private void resolveUsesForGroupings(final Map> modules) { + private static 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()); @@ -1087,8 +1126,8 @@ public final class YangParserImpl implements YangContextParser { * @param modules * all loaded modules */ - private void resolveUsesForNodes(final Map> modules) { - for (Map.Entry> entry : modules.entrySet()) { + private static 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(); @@ -1109,84 +1148,52 @@ public final class YangParserImpl implements YangContextParser { * @param modules * all loaded modules */ - private void resolveUses(final UsesNodeBuilder usesNode, final Map> modules) { + private static 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); - } - } 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); - } + + 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 - */ - private void resolveUsesWithContext(final UsesNodeBuilder usesNode) { - final int line = usesNode.getLine(); + private static 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(); - } - - GroupingDefinition gd = usesNode.getGroupingDefinition(); + int usesLine = usesNode.getLine(); - 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() && 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); } /** @@ -1198,32 +1205,36 @@ public final class YangParserImpl implements YangContextParser { * @param module * current module */ - private void resolveUnknownNodes(final Map> modules, final ModuleBuilder module) { + private static void resolveUnknownNodes(final Map> modules, final ModuleBuilder module) { for (UnknownSchemaNodeBuilder usnb : module.getAllUnknownNodes()) { QName nodeType = usnb.getNodeType(); - ModuleBuilder dependentModuleBuilder = BuilderUtils.getModuleByPrefix(module, nodeType.getPrefix()); - ExtensionBuilder extBuilder = findExtBuilder(nodeType.getLocalName(), - dependentModuleBuilder.getAddedExtensions()); + 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; + } + + ExtensionBuilder extBuilder = findExtBuilder(localName, dependentModule.getAddedExtensions()); if (extBuilder == null) { - ExtensionDefinition extDef = findExtDef(nodeType.getLocalName(), dependentModuleBuilder.getExtensions()); + 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 { - usnb.setNodeType(new QName(extDef.getQName().getNamespace(), extDef.getQName().getRevision(), - nodeType.getPrefix(), extDef.getQName().getLocalName())); usnb.setExtensionDefinition(extDef); } } else { - usnb.setNodeType(QName.create(extBuilder.getQName().getModule(), - nodeType.getPrefix(), extBuilder.getQName().getLocalName())); usnb.setExtensionBuilder(extBuilder); } } } - private ExtensionBuilder findExtBuilder(final String name, final Collection extensions) { + private static ExtensionBuilder findExtBuilder(final String name, final Collection extensions) { for (ExtensionBuilder extension : extensions) { if (extension.getQName().getLocalName().equals(name)) { return extension; @@ -1232,7 +1243,7 @@ public final class YangParserImpl implements YangContextParser { return null; } - private ExtensionDefinition findExtDef(final String name, final Collection extensions) { + private static ExtensionDefinition findExtDef(final String name, final Collection extensions) { for (ExtensionDefinition extension : extensions) { if (extension.getQName().getLocalName().equals(name)) { return extension; @@ -1241,75 +1252,73 @@ public final class YangParserImpl implements YangContextParser { return null; } + /** - * Traverse through modules and resolve their deviation statements. + * Traverse through modules and check if choice has choice cases with the + * same qname. * * @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); + private void checkChoiceCasesForDuplicityQNames(final Map> modules) { + for (Map.Entry> entry : modules.entrySet()) { + for (Map.Entry childEntry : entry.getValue().entrySet()) { + final ModuleBuilder moduleBuilder = childEntry.getValue(); + final Module module = moduleBuilder.build(); + final List allChoicesFromModule = getChoicesFrom(module); + + for (ChoiceSchemaNode choiceNode : allChoicesFromModule) { + findDuplicityNodesIn(choiceNode, module, moduleBuilder, modules); + } } } } - /** - * 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()) { - SchemaPath targetPath = dev.getTargetPath(); - Iterable path = targetPath.getPathFromRoot(); - QName q0 = path.iterator().next(); - String prefix = q0.getPrefix(); - if (prefix == null) { - prefix = module.getPrefix(); + private static void findDuplicityNodesIn(final ChoiceSchemaNode choiceNode, final Module module, final ModuleBuilder moduleBuilder, + final Map> modules) { + final Set duplicityTestSet = new HashSet<>(); + + for (ChoiceCaseNode choiceCaseNode : choiceNode.getCases()) { + + for (DataSchemaNode childSchemaNode : choiceCaseNode.getChildNodes()) { + if (!duplicityTestSet.add(childSchemaNode.getQName())) { + final Optional schemaNodeBuilder = BuilderUtils.findSchemaNodeInModule(childSchemaNode.getPath(), moduleBuilder); + final String nameOfSchemaNode = childSchemaNode.getQName().getLocalName(); + int lineOfSchemaNode = 0; + + if (schemaNodeBuilder.isPresent()) { + lineOfSchemaNode = schemaNodeBuilder.get().getLine(); + } + throw new YangParseException(module.getName(), lineOfSchemaNode, + String.format("Choice has two nodes case with same qnames - %s", nameOfSchemaNode)); + } } + } + } - ModuleBuilder dependentModuleBuilder = BuilderUtils.getModuleByPrefix(module, prefix); - processDeviation(dev, dependentModuleBuilder, path, module); + private List getChoicesFrom(final Module module) { + final List allChoices = new ArrayList<>(); + + for (DataSchemaNode dataSchemaNode : module.getChildNodes()) { + findChoicesIn(dataSchemaNode, allChoices); } + return allChoices; } - /** - * 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); + private void findChoicesIn(final SchemaNode schemaNode, final Collection choiceNodes) { + if (schemaNode instanceof ContainerSchemaNode) { + final ContainerSchemaNode contSchemaNode = (ContainerSchemaNode) schemaNode; + for (DataSchemaNode dataSchemaNode : contSchemaNode.getChildNodes()) { + findChoicesIn(dataSchemaNode, choiceNodes); } - String name = q.getLocalName(); - if (currentParent instanceof DataNodeContainerBuilder) { - currentParent = ((DataNodeContainerBuilder) currentParent).getDataChildByName(name); + } else if (schemaNode instanceof ListSchemaNode) { + final ListSchemaNode listSchemaNode = (ListSchemaNode) schemaNode; + for (DataSchemaNode dataSchemaNode : listSchemaNode.getChildNodes()) { + findChoicesIn(dataSchemaNode, choiceNodes); } + } else if (schemaNode instanceof ChoiceSchemaNode) { + choiceNodes.add((ChoiceSchemaNode) schemaNode); } - - if (!(currentParent instanceof SchemaNodeBuilder)) { - throw new YangParseException(module.getName(), line, FAIL_DEVIATION_TARGET); - } - dev.setTargetPath(((SchemaNodeBuilder) currentParent).getPath()); } }