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=7948158f4dee6b277493d8d2451395d3ee6b3d19;hpb=24b697d9f464bf5557796c2a7a6bfc5c14f50796;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 7948158f4d..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 @@ -10,15 +11,13 @@ 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.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.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; @@ -35,6 +34,7 @@ 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; @@ -47,11 +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.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; @@ -84,10 +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 Splitter COLON_SPLITTER = Splitter.on(':'); private static final YangParserImpl INSTANCE = new YangParserImpl(); public static YangParserImpl getInstance() { @@ -137,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()]))); @@ -214,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) { @@ -229,9 +238,9 @@ public final class YangParserImpl implements YangContextParser { return resolveSchemaContext(result); } - private static 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()) { @@ -240,7 +249,7 @@ public final class YangParserImpl implements YangContextParser { if (targetModule == null) { Module result = findModuleFromContext(context, module, prefix, 0); targetModule = new ModuleBuilder(result); - TreeMap map = modules.get(targetModule.getNamespace()); + NavigableMap map = modules.get(targetModule.getNamespace()); if (map == null) { map = new TreeMap<>(); map.put(targetModule.getRevision(), targetModule); @@ -331,7 +340,7 @@ public final class YangParserImpl implements YangContextParser { public Collection buildModules(final Collection builders) { Collection unsorted = resolveSubmodules(builders); List sorted = ModuleDependencySort.sort(unsorted); - Map> modules = resolveModulesWithImports(sorted, null); + Map> modules = resolveModulesWithImports(sorted, null); Map builderToModule = build(modules); return builderToModule.values(); } @@ -350,7 +359,7 @@ public final class YangParserImpl implements YangContextParser { 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,7 +388,7 @@ public final class YangParserImpl implements YangContextParser { return resolveSubmodules(builders); } - private Map parseSourcesToBuilders(final Collection sources, + private static Map parseSourcesToBuilders(final Collection sources, final SchemaContext context) throws IOException, YangSyntaxErrorException { final ParseTreeWalker walker = new ParseTreeWalker(); final Map sourceToTree = parseYangSources(sources); @@ -388,7 +397,7 @@ public final class YangParserImpl implements YangContextParser { // validate yang new YangModelBasicValidator(walker).validate(sourceToTree.values()); - Map> namespaceContext = BuilderUtils.createYangNamespaceContext( + Map> namespaceContext = BuilderUtils.createYangNamespaceContext( sourceToTree.values(), Optional.fromNullable(context)); YangParserListenerImpl yangModelParser; for (Map.Entry entry : sourceToTree.entrySet()) { @@ -412,12 +421,12 @@ public final class YangParserImpl implements YangContextParser { private Map resolveSubmodules(final Map builders) { Map modules = new HashMap<>(); - Map> submodules = new HashMap<>(); + Map> submodules = new HashMap<>(); for (Map.Entry entry : builders.entrySet()) { ModuleBuilder builder = entry.getValue(); if (builder.isSubmodule()) { String submoduleName = builder.getName(); - TreeMap map = submodules.get(submoduleName); + NavigableMap map = submodules.get(submoduleName); if (map == null) { map = new TreeMap<>(); map.put(builder.getRevision(), builder); @@ -439,11 +448,11 @@ public final class YangParserImpl implements YangContextParser { private Collection resolveSubmodules(final Collection builders) { Collection modules = new HashSet<>(); - Map> submodules = new HashMap<>(); + Map> submodules = new HashMap<>(); for (ModuleBuilder builder : builders) { if (builder.isSubmodule()) { String submoduleName = builder.getName(); - TreeMap map = submodules.get(submoduleName); + NavigableMap map = submodules.get(submoduleName); if (map == null) { map = new TreeMap<>(); map.put(builder.getRevision(), builder); @@ -474,10 +483,10 @@ public final class YangParserImpl implements YangContextParser { * @return collection of module builders with resolved submodules */ private void resolveSubmodules(final ModuleBuilder module, - final Map> submodules) { + final Map> submodules) { Map includes = module.getIncludedModules(); for (Map.Entry entry : includes.entrySet()) { - TreeMap subs = submodules.get(entry.getKey()); + NavigableMap subs = submodules.get(entry.getKey()); if (subs == null) { throw new YangParseException("Failed to find references submodule " + entry.getKey() + " in module " + module.getName()); @@ -495,14 +504,14 @@ public final class YangParserImpl implements YangContextParser { } } - if (submodule.getIncludedModules().size() > 0) { + if (!submodule.getIncludedModules().isEmpty()) { resolveSubmodules(submodule, submodules); } addSubmoduleToModule(submodule, module); } } - 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()); @@ -559,8 +568,8 @@ public final class YangParserImpl implements YangContextParser { * topologically sorted modules * @return modules ordered by namespace and revision */ - private static 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; @@ -572,7 +581,7 @@ public final class YangParserImpl implements YangContextParser { rev = new Date(0); } - TreeMap builderByRevision = result.get(ns); + NavigableMap builderByRevision = result.get(ns); if (builderByRevision == null) { builderByRevision = new TreeMap<>(); builderByRevision.put(rev, builder); @@ -602,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); @@ -622,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); } } } @@ -634,7 +641,7 @@ 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) { try (InputStream stream = source.openStream()) { @@ -663,6 +670,8 @@ public final class YangParserImpl implements YangContextParser { * 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) { @@ -701,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); @@ -709,10 +718,11 @@ public final class YangParserImpl implements YangContextParser { resolveUsesForNodes(modules); resolveAugments(modules); resolveIdentities(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(); @@ -728,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); @@ -747,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) { @@ -778,10 +788,10 @@ 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()); } @@ -813,8 +823,8 @@ public final class YangParserImpl implements YangContextParser { } } - private SchemaPath findUsesAugmentTargetNodePath(DataNodeContainerBuilder usesParent, - AugmentationSchemaBuilder augment) { + private static SchemaPath findUsesAugmentTargetNodePath(final DataNodeContainerBuilder usesParent, + final AugmentationSchemaBuilder augment) { QName parentQName = usesParent.getQName(); final QNameModule qnm; if (parentQName == null) { @@ -864,7 +874,7 @@ 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) { URI augmentTargetNs = augment.getTargetPath().getPathFromRoot().iterator().next().getNamespace(); Date augmentTargetRev = augment.getTargetPath().getPathFromRoot().iterator().next().getRevision(); @@ -891,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()); } @@ -928,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; } @@ -951,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() - .getPathFromRoot(), (SchemaNodeBuilder) parentNode)); + potentialTargetNode = Optional. fromNullable(findTargetNode(augment.getTargetPath() + .getPathFromRoot(), parentNode)); } if (potentialTargetNode.isPresent()) { @@ -967,6 +977,7 @@ public final class YangParserImpl implements YangContextParser { "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 { @@ -987,8 +998,8 @@ 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; } @@ -1010,8 +1021,8 @@ 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(); @@ -1022,7 +1033,8 @@ public final class YangParserImpl implements YangContextParser { } } - private void resolveIdentity(final ModuleBuilder module, final IdentitySchemaNodeBuilder identity) { + private static void resolveIdentity(final ModuleBuilder module, + final IdentitySchemaNodeBuilder identity) { final String baseIdentityName = identity.getBaseIdentityName(); if (baseIdentityName != null) { IdentitySchemaNodeBuilder result = null; @@ -1030,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); } @@ -1050,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()); } @@ -1071,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()); @@ -1095,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(); @@ -1117,7 +1148,7 @@ 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); @@ -1140,7 +1171,7 @@ public final class YangParserImpl implements YangContextParser { } } - private int nodeAfterUsesIndex(final UsesNodeBuilder usesNode) { + private static int nodeAfterUsesIndex(final UsesNodeBuilder usesNode) { DataNodeContainerBuilder parent = usesNode.getParent(); int usesLine = usesNode.getLine(); @@ -1151,11 +1182,9 @@ public final class YangParserImpl implements YangContextParser { DataSchemaNodeBuilder nextNodeAfterUses = null; for (DataSchemaNodeBuilder childNode : childNodes) { - if (!(childNode.isAddedByUses()) && !(childNode.isAugmenting())) { - if (childNode.getLine() > usesLine) { - nextNodeAfterUses = childNode; - break; - } + if (!childNode.isAddedByUses() && !childNode.isAugmenting() && childNode.getLine() > usesLine) { + nextNodeAfterUses = childNode; + break; } } @@ -1176,7 +1205,7 @@ 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(); String localName = usnb.getNodeType().getLocalName(); @@ -1205,7 +1234,7 @@ public final class YangParserImpl implements YangContextParser { } } - 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; @@ -1214,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; @@ -1223,4 +1252,73 @@ public final class YangParserImpl implements YangContextParser { return null; } + + /** + * Traverse through modules and check if choice has choice cases with the + * same qname. + * + * @param modules + * all loaded modules + */ + 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); + } + } + } + } + + 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)); + } + } + } + } + + private List getChoicesFrom(final Module module) { + final List allChoices = new ArrayList<>(); + + for (DataSchemaNode dataSchemaNode : module.getChildNodes()) { + findChoicesIn(dataSchemaNode, allChoices); + } + return allChoices; + } + + 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); + } + } 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); + } + } + }