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%2Fbuilder%2Fimpl%2FModuleBuilder.java;h=13372b1c38d8452173fd4ad893e38aef307effee;hb=36368e8e6f9a791c355a7e61010a04e6a4f347d4;hp=67471068db920398c87a3358b10eaa1820998588;hpb=df1236c753c1e917b587686efb9251f83e49cfb2;p=yangtools.git diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/builder/impl/ModuleBuilder.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/builder/impl/ModuleBuilder.java index 67471068db..13372b1c38 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/builder/impl/ModuleBuilder.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/builder/impl/ModuleBuilder.java @@ -8,45 +8,13 @@ package org.opendaylight.yangtools.yang.parser.builder.impl; import java.net.URI; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeMap; -import java.util.TreeSet; +import java.util.*; import org.opendaylight.yangtools.yang.common.QName; -import org.opendaylight.yangtools.yang.model.api.AugmentationSchema; -import org.opendaylight.yangtools.yang.model.api.DataSchemaNode; -import org.opendaylight.yangtools.yang.model.api.Deviation; -import org.opendaylight.yangtools.yang.model.api.ExtensionDefinition; -import org.opendaylight.yangtools.yang.model.api.FeatureDefinition; -import org.opendaylight.yangtools.yang.model.api.GroupingDefinition; -import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode; -import org.opendaylight.yangtools.yang.model.api.Module; -import org.opendaylight.yangtools.yang.model.api.ModuleImport; -import org.opendaylight.yangtools.yang.model.api.NotificationDefinition; -import org.opendaylight.yangtools.yang.model.api.RpcDefinition; -import org.opendaylight.yangtools.yang.model.api.SchemaPath; -import org.opendaylight.yangtools.yang.model.api.TypeDefinition; -import org.opendaylight.yangtools.yang.model.api.UnknownSchemaNode; -import org.opendaylight.yangtools.yang.model.api.UsesNode; -import org.opendaylight.yangtools.yang.parser.builder.api.AbstractDataNodeContainerBuilder; -import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationSchemaBuilder; -import org.opendaylight.yangtools.yang.parser.builder.api.Builder; -import org.opendaylight.yangtools.yang.parser.builder.api.DataNodeContainerBuilder; -import org.opendaylight.yangtools.yang.parser.builder.api.DataSchemaNodeBuilder; -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.UsesNodeBuilder; +import org.opendaylight.yangtools.yang.model.api.*; +import org.opendaylight.yangtools.yang.parser.builder.api.*; import org.opendaylight.yangtools.yang.parser.util.Comparators; +import org.opendaylight.yangtools.yang.parser.util.ModuleImportImpl; import org.opendaylight.yangtools.yang.parser.util.RefineHolder; import org.opendaylight.yangtools.yang.parser.util.YangParseException; @@ -56,6 +24,7 @@ import org.opendaylight.yangtools.yang.parser.util.YangParseException; * otherwise result may not be valid. */ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { + private final ModuleImpl instance; private final String name; private final SchemaPath schemaPath; @@ -63,31 +32,75 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { private String prefix; private Date revision; - private final LinkedList actualPath = new LinkedList(); - private final Set dirtyNodes = new HashSet(); + private final Deque actualPath = new LinkedList<>(); + private final Set dirtyNodes = new HashSet<>(); private final Set imports = new HashSet(); - private final List addedAugments = new ArrayList(); - private final List allAugments = new ArrayList(); - private final Set addedUsesNodes = new HashSet(); - private final List allUsesNodes = new ArrayList(); - private final Set addedRpcs = new HashSet(); - private final Set addedNotifications = new HashSet(); - private final Set addedIdentities = new HashSet(); - private final Set addedFeatures = new HashSet(); - private final Set addedDeviations = new HashSet(); - private final Set addedTypedefs = new HashSet(); - private final List addedExtensions = new ArrayList(); + + private final Set augments = new HashSet<>(); + private final List augmentBuilders = new ArrayList<>(); + private final List allAugments = new ArrayList<>(); + + private final List allGroupings = new ArrayList<>(); + + private final List allUsesNodes = new ArrayList<>(); + + private final Set rpcs = new TreeSet<>(Comparators.SCHEMA_NODE_COMP); + private final Set addedRpcs = new HashSet<>(); + + private final Set notifications = new TreeSet<>(Comparators.SCHEMA_NODE_COMP); + private final Set addedNotifications = new HashSet<>(); + + private final Set identities = new TreeSet<>(Comparators.SCHEMA_NODE_COMP); + private final Set addedIdentities = new HashSet<>(); + + private final Set features = new TreeSet<>(Comparators.SCHEMA_NODE_COMP); + private final Set addedFeatures = new HashSet<>(); + + private final Set deviations = new HashSet<>(); + private final Set deviationBuilders = new HashSet<>(); + + private final List extensions = new ArrayList<>(); + private final List addedExtensions = new ArrayList<>(); + private final List allUnknownNodes = new ArrayList(); public ModuleBuilder(final String name) { super(name, 0, null); this.name = name; - schemaPath = new SchemaPath(Collections.emptyList(), true); + schemaPath = new SchemaPath(Collections. emptyList(), true); instance = new ModuleImpl(name); actualPath.push(this); } + public ModuleBuilder(Module base) { + super(base.getName(), 0, null); + this.name = base.getName(); + schemaPath = new SchemaPath(Collections. emptyList(), true); + instance = new ModuleImpl(base.getName()); + actualPath.push(this); + + namespace = base.getNamespace(); + prefix = base.getPrefix(); + revision = base.getRevision(); + + for (DataSchemaNode childNode : base.getChildNodes()) { + childNodes.put(childNode.getQName(), childNode); + } + + typedefs.addAll(base.getTypeDefinitions()); + groupings.addAll(base.getGroupings()); + usesNodes.addAll(base.getUses()); + augments.addAll(base.getAugmentations()); + rpcs.addAll(base.getRpcs()); + notifications.addAll(base.getNotifications()); + identities.addAll(base.getIdentities()); + features.addAll(base.getFeatures()); + deviations.addAll(base.getDeviations()); + extensions.addAll(base.getExtensionSchemaNodes()); + unknownNodes.addAll(base.getUnknownSchemaNodes()); + } + /** * Build new Module object based on this builder. */ @@ -99,71 +112,61 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { instance.setNamespace(namespace); // TYPEDEFS - final Set> typedefs = new TreeSet>(Comparators.SCHEMA_NODE_COMP); for (TypeDefinitionBuilder tdb : addedTypedefs) { typedefs.add(tdb.build()); } instance.setTypeDefinitions(typedefs); // CHILD NODES - final Map children = new TreeMap(Comparators.QNAME_COMP); for (DataSchemaNodeBuilder child : addedChildNodes) { - children.put(child.getQName(), child.build()); + DataSchemaNode childNode = child.build(); + childNodes.put(childNode.getQName(), childNode); } - instance.setChildNodes(children); + instance.addChildNodes(childNodes); // GROUPINGS - final Set groupings = new TreeSet(Comparators.SCHEMA_NODE_COMP); for (GroupingBuilder gb : addedGroupings) { groupings.add(gb.build()); } instance.setGroupings(groupings); // USES - final Set usesDefinitions = new HashSet(); for (UsesNodeBuilder unb : addedUsesNodes) { - usesDefinitions.add(unb.build()); + usesNodes.add(unb.build()); } - instance.setUses(usesDefinitions); + instance.setUses(usesNodes); // FEATURES - final Set features = new TreeSet(Comparators.SCHEMA_NODE_COMP); for (FeatureBuilder fb : addedFeatures) { features.add(fb.build()); } instance.setFeatures(features); // NOTIFICATIONS - final Set notifications = new TreeSet( - Comparators.SCHEMA_NODE_COMP); for (NotificationBuilder entry : addedNotifications) { notifications.add(entry.build()); } instance.setNotifications(notifications); // AUGMENTATIONS - final Set augmentations = new HashSet(); - for (AugmentationSchemaBuilder builder : addedAugments) { - augmentations.add(builder.build()); + for (AugmentationSchemaBuilder builder : augmentBuilders) { + augments.add(builder.build()); } - instance.setAugmentations(augmentations); + instance.setAugmentations(augments); // RPCs - final Set rpcs = new TreeSet(Comparators.SCHEMA_NODE_COMP); for (RpcDefinitionBuilder rpc : addedRpcs) { rpcs.add(rpc.build()); } instance.setRpcs(rpcs); // DEVIATIONS - final Set deviations = new HashSet(); - for (DeviationBuilder entry : addedDeviations) { + for (DeviationBuilder entry : deviationBuilders) { deviations.add(entry.build()); } instance.setDeviations(deviations); // EXTENSIONS - final List extensions = new ArrayList(); for (ExtensionBuilder eb : addedExtensions) { extensions.add(eb.build()); } @@ -171,31 +174,21 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { instance.setExtensionSchemaNodes(extensions); // IDENTITIES - final Set identities = new TreeSet(Comparators.SCHEMA_NODE_COMP); for (IdentitySchemaNodeBuilder id : addedIdentities) { identities.add(id.build()); } instance.setIdentities(identities); // UNKNOWN NODES - final List unknownNodes = new ArrayList(); for (UnknownSchemaNodeBuilder unb : addedUnknownNodes) { unknownNodes.add(unb.build()); } + Collections.sort(unknownNodes, Comparators.SCHEMA_NODE_COMP); instance.setUnknownSchemaNodes(unknownNodes); return instance; } - public boolean isAllUsesDataCollected() { - for(UsesNodeBuilder usesNode : allUsesNodes) { - if(!usesNode.isDataCollected()) { - return false; - } - } - return true; - } - @Override public void setParent(Builder parent) { throw new YangParseException(name, 0, "Can not set parent to module"); @@ -223,7 +216,7 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { if (actualPath.isEmpty()) { return null; } else { - return actualPath.get(0); + return actualPath.peekFirst(); } } @@ -231,7 +224,10 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { if (actualPath.size() < 2) { return null; } else { - return actualPath.get(1); + Builder builderChild = actualPath.removeFirst(); + Builder builderParent = actualPath.peekFirst(); + actualPath.addFirst(builderChild); + return builderParent; } } @@ -247,12 +243,20 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { return addedIdentities; } + public List getAllGroupings() { + return allGroupings; + } + public List getAllUsesNodes() { return allUsesNodes; } public Set getDeviations() { - return addedDeviations; + return deviationBuilders; + } + + public List getExtensions() { + return addedExtensions; } public List getAllUnknownNodes() { @@ -321,15 +325,20 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { return imports; } - public ExtensionBuilder addExtension(final QName qname, final int line) { + public ExtensionBuilder addExtension(final QName qname, final int line, final SchemaPath path) { + Builder parent = getActualNode(); + if (!(parent.equals(this))) { + throw new YangParseException(name, line, "extension can be defined only in module or submodule"); + } + final String extName = qname.getLocalName(); for (ExtensionBuilder addedExtension : addedExtensions) { if (addedExtension.getQName().getLocalName().equals(extName)) { - throw new YangParseException(moduleName, line, "Can not add extension '" + extName - + "': extension with same name already declared at line " + addedExtension.getLine()); + raiseYangParserException("extension", "node", extName, line, addedExtension.getLine()); } } - final ExtensionBuilder builder = new ExtensionBuilder(name, line, qname); + final ExtensionBuilder builder = new ExtensionBuilder(name, line, qname, path); + builder.setParent(parent); addedExtensions.add(builder); return builder; } @@ -374,8 +383,8 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { return builder; } - public GroupingBuilder addGrouping(final int line, final QName qname) { - final GroupingBuilder builder = new GroupingBuilderImpl(name, line, qname); + public GroupingBuilder addGrouping(final int line, final QName qname, final SchemaPath path) { + final GroupingBuilder builder = new GroupingBuilderImpl(name, line, qname, path); Builder parent = getActualNode(); builder.setParent(parent); @@ -384,8 +393,7 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { if (parent.equals(this)) { for (GroupingBuilder addedGrouping : addedGroupings) { if (addedGrouping.getQName().getLocalName().equals(groupingName)) { - throw new YangParseException(name, line, "grouping with same name '" + groupingName - + "' already declared at line " + addedGrouping.getLine()); + raiseYangParserException("", "Grouping", groupingName, line, addedGrouping.getLine()); } } addedGroupings.add(builder); @@ -394,8 +402,7 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parent; for (GroupingBuilder addedGrouping : parentNode.getGroupingBuilders()) { if (addedGrouping.getQName().getLocalName().equals(groupingName)) { - throw new YangParseException(name, line, "grouping with same name '" + groupingName - + "' already declared at line " + addedGrouping.getLine()); + raiseYangParserException("", "Grouping", groupingName, line, addedGrouping.getLine()); } } parentNode.addGrouping(builder); @@ -403,8 +410,7 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { RpcDefinitionBuilder parentNode = (RpcDefinitionBuilder) parent; for (GroupingBuilder child : parentNode.getGroupings()) { if (child.getQName().getLocalName().equals(groupingName)) { - throw new YangParseException(name, line, "grouping with same name '" + groupingName - + "' already declared at line " + child.getLine()); + raiseYangParserException("", "Grouping", groupingName, line, child.getLine()); } } parentNode.addGrouping(builder); @@ -413,6 +419,7 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { } } + allGroupings.add(builder); return builder; } @@ -424,10 +431,21 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { if (parent.equals(this)) { // augment can be declared only under 'module' ... - addedAugments.add(builder); + if (!(augmentTargetStr.startsWith("/"))) { + throw new YangParseException( + name, + line, + "If the 'augment' statement is on the top level in a module, the absolute form of a schema node identifier MUST be used."); + } + augmentBuilders.add(builder); } else { // ... or 'uses' statement if (parent instanceof UsesNodeBuilder) { + if (augmentTargetStr.startsWith("/")) { + throw new YangParseException(name, line, + "If 'augment' statement is a substatement to the 'uses' statement, it cannot contain absolute path (" + + augmentTargetStr + ")"); + } ((UsesNodeBuilder) parent).addAugment(builder); } else { throw new YangParseException(name, line, "Augment can be declared only under module or uses statement."); @@ -438,11 +456,6 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { return builder; } - @Override - public Set getUsesNodes() { - return addedUsesNodes; - } - @Override public void addUsesNode(UsesNodeBuilder usesBuilder) { addedUsesNodes.add(usesBuilder); @@ -461,11 +474,12 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { if (!(parent instanceof DataNodeContainerBuilder)) { throw new YangParseException(name, line, "Unresolved parent of uses '" + groupingPathStr + "'."); } - if (parent instanceof AugmentationSchemaBuilder) { - usesBuilder.setAugmenting(true); - } ((DataNodeContainerBuilder) parent).addUsesNode(usesBuilder); } + if (parent instanceof AugmentationSchemaBuilder) { + usesBuilder.setAugmenting(true); + } + allUsesNodes.add(usesBuilder); return usesBuilder; } @@ -479,32 +493,29 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { refine.setParent(parent); } - public RpcDefinitionBuilder addRpc(final int line, final QName qname) { + public RpcDefinitionBuilder addRpc(final int line, final QName qname, final SchemaPath path) { Builder parent = getActualNode(); if (!(parent.equals(this))) { throw new YangParseException(name, line, "rpc can be defined only in module or submodule"); } - final RpcDefinitionBuilder rpcBuilder = new RpcDefinitionBuilder(name, line, qname); + final RpcDefinitionBuilder rpcBuilder = new RpcDefinitionBuilder(name, line, qname, path); rpcBuilder.setParent(parent); String rpcName = qname.getLocalName(); for (RpcDefinitionBuilder rpc : addedRpcs) { if (rpc.getQName().getLocalName().equals(rpcName)) { - throw new YangParseException(name, line, "rpc with same name '" + rpcName - + "' already declared at line " + rpc.getLine()); + raiseYangParserException("", "rpc", rpcName, line, rpc.getLine()); } } for (DataSchemaNodeBuilder addedChild : addedChildNodes) { if (addedChild.getQName().getLocalName().equals(rpcName)) { - throw new YangParseException(name, line, "Can not add rpc: node with same name '" + rpcName - + "' already declared at line " + addedChild.getLine()); + raiseYangParserException("rpc", "node", rpcName, line, addedChild.getLine()); } } for (NotificationBuilder addedNotification : addedNotifications) { if (addedNotification.getQName().getLocalName().equals(rpcName)) { - throw new YangParseException(name, line, "Can not add rpc: notification with same name '" + rpcName - + "' already declared at line " + addedNotification.getLine()); + raiseYangParserException("rpc", "notification", rpcName, line, addedNotification.getLine()); } } addedRpcs.add(rpcBuilder); @@ -539,7 +550,11 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { return outputBuilder; } - public NotificationBuilder addNotification(final int line, final QName qname) { + public void addNotification(NotificationDefinition notification) { + notifications.add(notification); + } + + public NotificationBuilder addNotification(final int line, final QName qname, final SchemaPath path) { final Builder parent = getActualNode(); if (!(parent.equals(this))) { throw new YangParseException(name, line, "notification can be defined only in module or submodule"); @@ -548,52 +563,48 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { String notificationName = qname.getLocalName(); for (NotificationBuilder nb : addedNotifications) { if (nb.getQName().equals(qname)) { - throw new YangParseException(name, line, "notification with same name '" + notificationName - + "' already declared at line " + nb.getLine()); + raiseYangParserException("", "notification", notificationName, line, nb.getLine()); } } for (RpcDefinitionBuilder rpc : addedRpcs) { if (rpc.getQName().getLocalName().equals(notificationName)) { - throw new YangParseException(name, line, "Can not add notification: rpc with same name '" - + notificationName + "' already declared at line " + rpc.getLine()); + raiseYangParserException("notification", "rpc", notificationName, line, rpc.getLine()); } } for (DataSchemaNodeBuilder addedChild : addedChildNodes) { if (addedChild.getQName().getLocalName().equals(notificationName)) { - throw new YangParseException(name, line, "Can not add notification: node with same name '" - + notificationName + "' already declared at line " + addedChild.getLine()); + raiseYangParserException("notification", "node", notificationName, line, addedChild.getLine()); } } - final NotificationBuilder builder = new NotificationBuilder(name, line, qname); + final NotificationBuilder builder = new NotificationBuilder(name, line, qname, path); builder.setParent(parent); addedNotifications.add(builder); return builder; } - public FeatureBuilder addFeature(final int line, final QName qname) { + public FeatureBuilder addFeature(final int line, final QName qname, final SchemaPath path) { Builder parent = getActualNode(); if (!(parent.equals(this))) { throw new YangParseException(name, line, "feature can be defined only in module or submodule"); } - final FeatureBuilder builder = new FeatureBuilder(name, line, qname); + final FeatureBuilder builder = new FeatureBuilder(name, line, qname, path); builder.setParent(parent); String featureName = qname.getLocalName(); for (FeatureBuilder addedFeature : addedFeatures) { if (addedFeature.getQName().getLocalName().equals(featureName)) { - throw new YangParseException(name, line, "feature with same name '" + featureName - + "' already declared at line " + addedFeature.getLine()); + raiseYangParserException("", "feature", featureName, line, addedFeature.getLine()); } } addedFeatures.add(builder); return builder; } - public ChoiceBuilder addChoice(final int line, final QName qname) { - final ChoiceBuilder builder = new ChoiceBuilder(name, line, qname); + public ChoiceBuilder addChoice(final int line, final QName qname, final SchemaPath path) { + final ChoiceBuilder builder = new ChoiceBuilder(name, line, qname, path); Builder parent = getActualNode(); builder.setParent(parent); @@ -602,13 +613,13 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { return builder; } - public ChoiceCaseBuilder addCase(final int line, final QName qname) { + public ChoiceCaseBuilder addCase(final int line, final QName qname, final SchemaPath path) { Builder parent = getActualNode(); if (parent == null || parent.equals(this)) { throw new YangParseException(name, line, "'case' parent not found"); } - final ChoiceCaseBuilder builder = new ChoiceCaseBuilder(name, line, qname); + final ChoiceCaseBuilder builder = new ChoiceCaseBuilder(name, line, qname, path); builder.setParent(parent); if (parent instanceof ChoiceBuilder) { @@ -637,15 +648,14 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { String nodeName = typedefBuilder.getQName().getLocalName(); for (TypeDefinitionBuilder tdb : addedTypedefs) { if (tdb.getQName().getLocalName().equals(nodeName)) { - throw new YangParseException(name, typedefBuilder.getLine(), "typedef with same name '" + nodeName - + "' already declared at line " + tdb.getLine()); + raiseYangParserException("", "typedef", nodeName, typedefBuilder.getLine(), tdb.getLine()); } } addedTypedefs.add(typedefBuilder); } - public TypeDefinitionBuilderImpl addTypedef(final int line, final QName qname) { - final TypeDefinitionBuilderImpl builder = new TypeDefinitionBuilderImpl(name, line, qname); + public TypeDefinitionBuilderImpl addTypedef(final int line, final QName qname, final SchemaPath path) { + final TypeDefinitionBuilderImpl builder = new TypeDefinitionBuilderImpl(name, line, qname, path); Builder parent = getActualNode(); builder.setParent(parent); @@ -654,8 +664,7 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { if (parent.equals(this)) { for (TypeDefinitionBuilder tdb : addedTypedefs) { if (tdb.getQName().getLocalName().equals(typedefName)) { - throw new YangParseException(name, line, "typedef with same name '" + typedefName - + "' already declared at line " + tdb.getLine()); + raiseYangParserException("", "typedef", typedefName, line, tdb.getLine()); } } addedTypedefs.add(builder); @@ -664,8 +673,7 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parent; for (TypeDefinitionBuilder child : parentNode.getTypeDefinitionBuilders()) { if (child.getQName().getLocalName().equals(typedefName)) { - throw new YangParseException(name, line, "typedef with same name '" + typedefName - + "' already declared at line " + child.getLine()); + raiseYangParserException("", "typedef", typedefName, line, child.getLine()); } } parentNode.addTypedef(builder); @@ -673,8 +681,7 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { RpcDefinitionBuilder rpcParent = (RpcDefinitionBuilder) parent; for (TypeDefinitionBuilder tdb : rpcParent.getTypeDefinitions()) { if (tdb.getQName().getLocalName().equals(builder.getQName().getLocalName())) { - throw new YangParseException(name, line, "typedef with same name '" + typedefName - + "' already declared at line " + tdb.getLine()); + raiseYangParserException("", "typedef", typedefName, line, tdb.getLine()); } } rpcParent.addTypedef(builder); @@ -688,7 +695,7 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { public void setType(final TypeDefinition type) { Builder parent = getActualNode(); - if (parent == null || !(parent instanceof TypeAwareBuilder)) { + if (!(parent instanceof TypeAwareBuilder)) { throw new YangParseException("Failed to set type '" + type.getQName().getLocalName() + "'. Invalid parent node: " + parent); } @@ -735,11 +742,11 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { final DeviationBuilder builder = new DeviationBuilder(name, line, targetPath); builder.setParent(parent); - addedDeviations.add(builder); + deviationBuilders.add(builder); return builder; } - public IdentitySchemaNodeBuilder addIdentity(final QName qname, final int line) { + public IdentitySchemaNodeBuilder addIdentity(final QName qname, final int line, final SchemaPath path) { Builder parent = getActualNode(); if (!(parent.equals(this))) { throw new YangParseException(name, line, "identity can be defined only in module or submodule"); @@ -747,12 +754,11 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { String identityName = qname.getLocalName(); for (IdentitySchemaNodeBuilder idBuilder : addedIdentities) { if (idBuilder.getQName().equals(qname)) { - throw new YangParseException(name, line, "identity with same name '" + identityName - + "' already declared at line " + idBuilder.getLine()); + raiseYangParserException("", "identity", identityName, line, idBuilder.getLine()); } } - final IdentitySchemaNodeBuilder builder = new IdentitySchemaNodeBuilder(name, line, qname); + final IdentitySchemaNodeBuilder builder = new IdentitySchemaNodeBuilder(name, line, qname, path); builder.setParent(parent); addedIdentities.add(builder); return builder; @@ -764,9 +770,9 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { allUnknownNodes.add(builder); } - public UnknownSchemaNodeBuilder addUnknownSchemaNode(final int line, final QName qname) { + public UnknownSchemaNodeBuilder addUnknownSchemaNode(final int line, final QName qname, final SchemaPath path) { final Builder parent = getActualNode(); - final UnknownSchemaNodeBuilder builder = new UnknownSchemaNodeBuilder(name, line, qname); + final UnknownSchemaNodeBuilder builder = new UnknownSchemaNodeBuilder(name, line, qname, path); builder.setParent(parent); allUnknownNodes.add(builder); @@ -788,6 +794,14 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { return builder; } + public Set getRpcs() { + return addedRpcs; + } + + public Set getNotifications() { + return addedNotifications; + } + @Override public String toString() { return "module " + name; @@ -803,19 +817,19 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { private String reference; private String organization; private String contact; - private Set imports = Collections.emptySet(); - private Set features = Collections.emptySet(); - private Set> typeDefinitions = Collections.emptySet(); - private Set notifications = Collections.emptySet(); - private Set augmentations = Collections.emptySet(); - private Set rpcs = Collections.emptySet(); - private Set deviations = Collections.emptySet(); - private Map childNodes = Collections.emptyMap(); - private Set groupings = Collections.emptySet(); - private Set uses = Collections.emptySet(); - private List extensionNodes = Collections.emptyList(); - private Set identities = Collections.emptySet(); - private List unknownNodes = Collections.emptyList(); + private final Set imports = new HashSet<>(); + private final Set features = new TreeSet<>(Comparators.SCHEMA_NODE_COMP); + private final Set> typeDefinitions = new TreeSet<>(Comparators.SCHEMA_NODE_COMP); + private final Set notifications = new TreeSet<>(Comparators.SCHEMA_NODE_COMP); + private final Set augmentations = new HashSet<>(); + private final Set rpcs = new TreeSet<>(Comparators.SCHEMA_NODE_COMP); + private final Set deviations = new HashSet<>(); + private final Map childNodes = new TreeMap<>(Comparators.QNAME_COMP); + private final Set groupings = new TreeSet<>(Comparators.SCHEMA_NODE_COMP); + private final Set uses = new HashSet<>(); + private final List extensionNodes = new ArrayList<>(); + private final Set identities = new TreeSet<>(Comparators.SCHEMA_NODE_COMP); + private final List unknownNodes = new ArrayList<>(); private ModuleImpl(String name) { this.name = name; @@ -905,7 +919,7 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { private void setImports(Set imports) { if (imports != null) { - this.imports = imports; + this.imports.addAll(imports); } } @@ -916,7 +930,7 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { private void setFeatures(Set features) { if (features != null) { - this.features = features; + this.features.addAll(features); } } @@ -927,7 +941,7 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { private void setTypeDefinitions(Set> typeDefinitions) { if (typeDefinitions != null) { - this.typeDefinitions = typeDefinitions; + this.typeDefinitions.addAll(typeDefinitions); } } @@ -938,7 +952,7 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { private void setNotifications(Set notifications) { if (notifications != null) { - this.notifications = notifications; + this.notifications.addAll(notifications); } } @@ -949,7 +963,7 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { private void setAugmentations(Set augmentations) { if (augmentations != null) { - this.augmentations = augmentations; + this.augmentations.addAll(augmentations); } } @@ -960,7 +974,7 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { private void setRpcs(Set rpcs) { if (rpcs != null) { - this.rpcs = rpcs; + this.rpcs.addAll(rpcs); } } @@ -971,18 +985,20 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { private void setDeviations(Set deviations) { if (deviations != null) { - this.deviations = deviations; + this.deviations.addAll(deviations); } } @Override public Set getChildNodes() { - return new LinkedHashSet(childNodes.values()); + final Set result = new TreeSet<>(Comparators.SCHEMA_NODE_COMP); + result.addAll(childNodes.values()); + return Collections.unmodifiableSet(result); } - private void setChildNodes(Map childNodes) { + private void addChildNodes(Map childNodes) { if (childNodes != null) { - this.childNodes = childNodes; + this.childNodes.putAll(childNodes); } } @@ -993,7 +1009,7 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { private void setGroupings(Set groupings) { if (groupings != null) { - this.groupings = groupings; + this.groupings.addAll(groupings); } } @@ -1004,18 +1020,19 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { private void setUses(Set uses) { if (uses != null) { - this.uses = uses; + this.uses.addAll(uses); } } @Override public List getExtensionSchemaNodes() { + Collections.sort(extensionNodes, Comparators.SCHEMA_NODE_COMP); return extensionNodes; } private void setExtensionSchemaNodes(final List extensionNodes) { if (extensionNodes != null) { - this.extensionNodes = extensionNodes; + this.extensionNodes.addAll(extensionNodes); } } @@ -1026,7 +1043,7 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { private void setIdentities(final Set identities) { if (identities != null) { - this.identities = identities; + this.identities.addAll(identities); } } @@ -1037,7 +1054,7 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { private void setUnknownSchemaNodes(final List unknownNodes) { if (unknownNodes != null) { - this.unknownNodes = unknownNodes; + this.unknownNodes.addAll(unknownNodes); } } @@ -1144,131 +1161,169 @@ public class ModuleBuilder extends AbstractDataNodeContainerBuilder { * @param childName */ private void addChildToParent(final Builder parent, final DataSchemaNodeBuilder child, final String childName) { - final int line = child.getLine(); + final int lineNum = child.getLine(); if (parent.equals(this)) { - // if parent == null => node is defined under module - // All leafs, leaf-lists, lists, containers, choices, rpcs, - // notifications, and anyxmls defined within a parent node or at the - // top level of the module or its submodules share the same - // identifier namespace. - for (DataSchemaNodeBuilder childNode : addedChildNodes) { - if (childNode.getQName().getLocalName().equals(childName)) { - throw new YangParseException(name, line, "Can not add '" + child - + "': node with same name already declared at line " + childNode.getLine()); - } - } - for (RpcDefinitionBuilder rpc : addedRpcs) { - if (rpc.getQName().getLocalName().equals(childName)) { - throw new YangParseException(name, line, "Can not add '" + child - + "': rpc with same name already declared at line " + rpc.getLine()); - } + addChildToModule(child, childName, lineNum); + } else { + addChildToSubnodeOfModule(parent, child, childName, lineNum); + } + } + + /** + * Adds child node child to the set of nodes child nodes. + * + * The method reduces the complexity of the method + * {@link #addChildToParent(Builder, DataSchemaNodeBuilder, String) + * addChildToParent}. + * + * @param child + * data schema node builder for child node + * @param childName + * string with name of child node + * @param lineNum + * line number in YANG file where is the node with the name equal + * to childName is defined + */ + private void addChildToModule(final DataSchemaNodeBuilder child, final String childName, final int lineNum) { + // if parent == null => node is defined under module + // All leafs, leaf-lists, lists, containers, choices, rpcs, + // notifications, and anyxmls defined within a parent node or at the + // top level of the module or its submodules share the same + // identifier namespace. + for (DataSchemaNodeBuilder childNode : addedChildNodes) { + if (childNode.getQName().getLocalName().equals(childName)) { + raiseYangParserException("'" + child + "'", "node", childName, lineNum, childNode.getLine()); } - for (NotificationBuilder notification : addedNotifications) { - if (notification.getQName().getLocalName().equals(childName)) { - throw new YangParseException(name, line, "Can not add '" + child - + "': notification with same name already declared at line " + notification.getLine()); - } + } + for (RpcDefinitionBuilder rpc : addedRpcs) { + if (rpc.getQName().getLocalName().equals(childName)) { + raiseYangParserException("'" + child + "'", "rpc", childName, lineNum, rpc.getLine()); } - addedChildNodes.add(child); - } else { - if(parent instanceof AugmentationSchemaBuilder) { - child.setAugmenting(true); + } + for (NotificationBuilder notification : addedNotifications) { + if (notification.getQName().getLocalName().equals(childName)) { + raiseYangParserException("'" + child + "'", "notification", childName, lineNum, notification.getLine()); } - // no need for checking rpc and notification because they can be - // defined only under module or submodule - if (parent instanceof DataNodeContainerBuilder) { - DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parent; - for (DataSchemaNodeBuilder childNode : parentNode.getChildNodeBuilders()) { - if (childNode.getQName().getLocalName().equals(childName)) { - throw new YangParseException(name, line, "Can not add '" + child + "': node with same name '" - + childName + "' already declared at line " + childNode.getLine()); - } + } + addedChildNodes.add(child); + } + + /** + * Adds child node child to the group of child nodes of the + * parent + * + * The method reduces the complexity of the method + * {@link #addChildToParent(Builder, DataSchemaNodeBuilder, String) + * addChildToParent}. * + * + * @param parent + * builder of node which is parent for child + * @param child + * data schema node builder for child node + * @param childName + * string with name of child node + * @param lineNum + * line number in YANG file where is the node with the name equal + * to childName is defined + */ + private void addChildToSubnodeOfModule(final Builder parent, final DataSchemaNodeBuilder child, + final String childName, final int lineNum) { + // no need for checking rpc and notification because they can be + // defined only under module or submodule + if (parent instanceof DataNodeContainerBuilder) { + DataNodeContainerBuilder parentNode = (DataNodeContainerBuilder) parent; + for (DataSchemaNodeBuilder childNode : parentNode.getChildNodes()) { + if (childNode.getQName().getLocalName().equals(childName)) { + raiseYangParserException("'" + child + "'", "node", childName, lineNum, childNode.getLine()); } - parentNode.addChildNode(child); - } else if (parent instanceof ChoiceBuilder) { - ChoiceBuilder parentNode = (ChoiceBuilder) parent; - for (ChoiceCaseBuilder caseBuilder : parentNode.getCases()) { - if (caseBuilder.getQName().getLocalName().equals(childName)) { - throw new YangParseException(name, line, "Can not add '" + child + "': case with same name '" - + childName + "' already declared at line " + caseBuilder.getLine()); - } + } + parentNode.addChildNode(child); + } else if (parent instanceof ChoiceBuilder) { + ChoiceBuilder parentNode = (ChoiceBuilder) parent; + for (ChoiceCaseBuilder caseBuilder : parentNode.getCases()) { + if (caseBuilder.getQName().getLocalName().equals(childName)) { + raiseYangParserException("'" + child + "'", "node", childName, lineNum, caseBuilder.getLine()); } - parentNode.addCase(child); - } else { - throw new YangParseException(name, line, "Unresolved parent of node '" + childName + "'."); } + parentNode.addCase(child); + } else { + throw new YangParseException(name, lineNum, "Unresolved parent of node '" + childName + "'."); } } private ModuleImport createModuleImport(final String moduleName, final Date revision, final String prefix) { - final ModuleImport moduleImport = new ModuleImport() { - @Override - public String getModuleName() { - return moduleName; - } + final ModuleImport moduleImport = new ModuleImportImpl(moduleName, revision, prefix); + return moduleImport; + } - @Override - public Date getRevision() { - return revision; - } + private void raiseYangParserException(final String cantAddType, final String type, final String name, + final int currentLine, final int duplicateLine) { - @Override - public String getPrefix() { - return prefix; - } + StringBuilder msgPrefix = new StringBuilder(""); + if (cantAddType != null && !cantAddType.isEmpty()) { + msgPrefix.append("Can not add "); + msgPrefix.append(cantAddType); + msgPrefix.append(": "); + } - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((moduleName == null) ? 0 : moduleName.hashCode()); - result = prime * result + ((revision == null) ? 0 : revision.hashCode()); - result = prime * result + ((prefix == null) ? 0 : prefix.hashCode()); - return result; - } + String msg = String.format("%s%s with same name '%s' already declared at line %d.", msgPrefix, type, name, + duplicateLine); + throw new YangParseException(moduleName, currentLine, msg); + } - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - ModuleImport other = (ModuleImport) obj; - if (getModuleName() == null) { - if (other.getModuleName() != null) { - return false; - } - } else if (!getModuleName().equals(other.getModuleName())) { - return false; - } - if (getRevision() == null) { - if (other.getRevision() != null) { - return false; - } - } else if (!getRevision().equals(other.getRevision())) { - return false; - } - if (getPrefix() == null) { - if (other.getPrefix() != null) { - return false; - } - } else if (!getPrefix().equals(other.getPrefix())) { - return false; - } - return true; - } + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + result = prime * result + ((namespace == null) ? 0 : namespace.hashCode()); + result = prime * result + ((revision == null) ? 0 : revision.hashCode()); + result = prime * result + ((prefix == null) ? 0 : prefix.hashCode()); + + return result; + } - @Override - public String toString() { - return "ModuleImport[moduleName=" + moduleName + ", revision=" + revision + ", prefix=" + prefix + "]"; + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + ModuleBuilder other = (ModuleBuilder) obj; + if (name == null) { + if (other.name != null) { + return false; } - }; - return moduleImport; + } else if (!name.equals(other.name)) { + return false; + } + if (namespace == null) { + if (other.namespace != null) { + return false; + } + } else if (!namespace.equals(other.namespace)) { + return false; + } + if (prefix == null) { + if (other.prefix != null) { + return false; + } + } else if (!prefix.equals(other.prefix)) { + return false; + } + if (revision == null) { + if (other.revision != null) { + return false; + } + } else if (!revision.equals(other.revision)) { + return false; + } + return true; } }