X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?p=controller.git;a=blobdiff_plain;f=opendaylight%2Fsal%2Fyang-prototype%2Fcode-generator%2Fyang-model-parser-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fyang%2Fmodel%2Fparser%2Fimpl%2FYangModelParserImpl.java;h=35c04a8713bcae29908491b443b726a5a83aabe6;hp=27a65c1168f24fa822f1c13175d4c4a5a0cef0e2;hb=bb19f8f0c1d080a1232100b1a0e4ffa89f32a542;hpb=4a5b8b61c06c7091a7de5ed9df7456fa325dd909 diff --git a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserImpl.java b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserImpl.java index 27a65c1168..35c04a8713 100644 --- a/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserImpl.java +++ b/opendaylight/sal/yang-prototype/code-generator/yang-model-parser-impl/src/main/java/org/opendaylight/controller/yang/model/parser/impl/YangModelParserImpl.java @@ -12,13 +12,16 @@ import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; +import java.net.URI; import java.util.ArrayList; -import java.util.Calendar; +import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.util.Set; import java.util.TreeMap; @@ -29,11 +32,11 @@ import org.antlr.v4.runtime.tree.ParseTreeWalker; import org.opendaylight.controller.antlrv4.code.gen.YangLexer; import org.opendaylight.controller.antlrv4.code.gen.YangParser; import org.opendaylight.controller.yang.common.QName; -import org.opendaylight.controller.yang.model.api.AugmentationSchema; import org.opendaylight.controller.yang.model.api.DataSchemaNode; import org.opendaylight.controller.yang.model.api.ExtensionDefinition; import org.opendaylight.controller.yang.model.api.Module; import org.opendaylight.controller.yang.model.api.ModuleImport; +import org.opendaylight.controller.yang.model.api.MustDefinition; import org.opendaylight.controller.yang.model.api.NotificationDefinition; import org.opendaylight.controller.yang.model.api.RpcDefinition; import org.opendaylight.controller.yang.model.api.SchemaContext; @@ -49,18 +52,35 @@ import org.opendaylight.controller.yang.model.api.type.StringTypeDefinition; import org.opendaylight.controller.yang.model.parser.api.YangModelParser; import org.opendaylight.controller.yang.model.parser.builder.api.AugmentationSchemaBuilder; import org.opendaylight.controller.yang.model.parser.builder.api.AugmentationTargetBuilder; +import org.opendaylight.controller.yang.model.parser.builder.api.Builder; import org.opendaylight.controller.yang.model.parser.builder.api.ChildNodeBuilder; import org.opendaylight.controller.yang.model.parser.builder.api.DataSchemaNodeBuilder; +import org.opendaylight.controller.yang.model.parser.builder.api.GroupingBuilder; import org.opendaylight.controller.yang.model.parser.builder.api.TypeAwareBuilder; import org.opendaylight.controller.yang.model.parser.builder.api.TypeDefinitionBuilder; +import org.opendaylight.controller.yang.model.parser.builder.api.UsesNodeBuilder; +import org.opendaylight.controller.yang.model.parser.builder.impl.AnyXmlBuilder; +import org.opendaylight.controller.yang.model.parser.builder.impl.ChoiceBuilder; +import org.opendaylight.controller.yang.model.parser.builder.impl.ContainerSchemaNodeBuilder; import org.opendaylight.controller.yang.model.parser.builder.impl.IdentitySchemaNodeBuilder; +import org.opendaylight.controller.yang.model.parser.builder.impl.IdentityrefTypeBuilder; +import org.opendaylight.controller.yang.model.parser.builder.impl.LeafListSchemaNodeBuilder; +import org.opendaylight.controller.yang.model.parser.builder.impl.LeafSchemaNodeBuilder; +import org.opendaylight.controller.yang.model.parser.builder.impl.ListSchemaNodeBuilder; import org.opendaylight.controller.yang.model.parser.builder.impl.ModuleBuilder; import org.opendaylight.controller.yang.model.parser.builder.impl.TypedefBuilder; import org.opendaylight.controller.yang.model.parser.builder.impl.UnionTypeBuilder; +import org.opendaylight.controller.yang.model.parser.builder.impl.UnknownSchemaNodeBuilder; +import org.opendaylight.controller.yang.model.parser.util.ModuleDependencySort; +import org.opendaylight.controller.yang.model.parser.util.ModuleDependencySort.ModuleSimple; +import org.opendaylight.controller.yang.model.parser.util.ParserUtils; +import org.opendaylight.controller.yang.model.parser.util.RefineHolder; import org.opendaylight.controller.yang.model.parser.util.TypeConstraints; import org.opendaylight.controller.yang.model.parser.util.YangParseException; import org.opendaylight.controller.yang.model.util.ExtendedType; +import org.opendaylight.controller.yang.model.util.IdentityrefType; import org.opendaylight.controller.yang.model.util.UnknownType; +import org.opendaylight.controller.yang.model.validator.YangModelBasicValidator; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -70,22 +90,28 @@ public class YangModelParserImpl implements YangModelParser { .getLogger(YangModelParserImpl.class); @Override - public Module parseYangModel(final String yangFile) { - final Map> modules = resolveModuleBuildersFromStreams(yangFile); - final Set result = build(modules); - return result.iterator().next(); - } - - @Override - public Set parseYangModels(final String... yangFiles) { - final Map> modules = resolveModuleBuildersFromStreams(yangFiles); - return build(modules); + public Set parseYangModels(final List yangFiles) { + if (yangFiles != null) { + final List inputStreams = new ArrayList(); + + for (final File yangFile : yangFiles) { + try { + inputStreams.add(new FileInputStream(yangFile)); + } catch (FileNotFoundException e) { + logger.warn("Exception while reading yang file: " + + yangFile.getName(), e); + } + } + final Map> modules = resolveModuleBuilders(inputStreams); + return build(modules); + } + return Collections.emptySet(); } @Override public Set parseYangModelsFromStreams( - final InputStream... yangModelStreams) { - final Map> modules = resolveModuleBuildersFromStreams(yangModelStreams); + final List yangModelStreams) { + final Map> modules = resolveModuleBuilders(yangModelStreams); return build(modules); } @@ -94,31 +120,16 @@ public class YangModelParserImpl implements YangModelParser { return new SchemaContextImpl(modules); } - private Map> resolveModuleBuildersFromStreams( - String... yangFiles) { - InputStream[] streams = new InputStream[yangFiles.length]; - FileInputStream inStream = null; - for (int i = 0; i < yangFiles.length; i++) { - final String yangFileName = yangFiles[i]; - final File yangFile = new File(yangFileName); - try { - inStream = new FileInputStream(yangFile); - } catch (FileNotFoundException e) { - logger.warn("Exception while reading yang stream: " + inStream, - e); - } - streams[i] = inStream; - } - return resolveModuleBuildersFromStreams(streams); - } - - private Map> resolveModuleBuildersFromStreams( - InputStream... yangFiles) { + private Map> resolveModuleBuilders( + final List yangFileStreams) { final Map> modules = new HashMap>(); final ParseTreeWalker walker = new ParseTreeWalker(); - final List trees = parseStreams(yangFiles); + final List trees = parseStreams(yangFileStreams); final ModuleBuilder[] builders = new ModuleBuilder[trees.size()]; + // validate yang + new YangModelBasicValidator(walker).validate(trees); + YangModelParserListenerImpl yangModelParser = null; for (int i = 0; i < trees.size(); i++) { yangModelParser = new YangModelParserListenerImpl(); @@ -126,11 +137,14 @@ public class YangModelParserImpl implements YangModelParser { builders[i] = yangModelParser.getModuleBuilder(); } + // module dependency graph sorted + List sorted = new ModuleDependencySort(builders).sort(); + for (ModuleBuilder builder : builders) { final String builderName = builder.getName(); Date builderRevision = builder.getRevision(); if (builderRevision == null) { - builderRevision = createEpochTime(); + builderRevision = new Date(0L); } TreeMap builderByRevision = modules .get(builderName); @@ -143,7 +157,7 @@ public class YangModelParserImpl implements YangModelParser { return modules; } - private List parseStreams(InputStream... yangStreams) { + private List parseStreams(final List yangStreams) { final List trees = new ArrayList(); for (InputStream yangStream : yangStreams) { trees.add(parseStream(yangStream)); @@ -151,7 +165,7 @@ public class YangModelParserImpl implements YangModelParser { return trees; } - private ParseTree parseStream(InputStream yangStream) { + private ParseTree parseStream(final InputStream yangStream) { ParseTree result = null; try { final ANTLRInputStream input = new ANTLRInputStream(yangStream); @@ -165,16 +179,18 @@ public class YangModelParserImpl implements YangModelParser { return result; } - private Set build(Map> modules) { - // validate + private Set build( + final Map> modules) { + // fix unresolved nodes for (Map.Entry> entry : modules .entrySet()) { for (Map.Entry childEntry : entry.getValue() .entrySet()) { - ModuleBuilder moduleBuilder = childEntry.getValue(); - validateModule(modules, moduleBuilder); + final ModuleBuilder moduleBuilder = childEntry.getValue(); + fixUnresolvedNodes(modules, moduleBuilder); } } + resolveAugments(modules); // build final Set result = new HashSet(); @@ -183,8 +199,8 @@ public class YangModelParserImpl implements YangModelParser { final Map modulesByRevision = new HashMap(); for (Map.Entry childEntry : entry.getValue() .entrySet()) { - ModuleBuilder moduleBuilder = childEntry.getValue(); - Module module = moduleBuilder.build(); + final ModuleBuilder moduleBuilder = childEntry.getValue(); + final Module module = moduleBuilder.build(); modulesByRevision.put(childEntry.getKey(), module); result.add(module); } @@ -192,12 +208,13 @@ public class YangModelParserImpl implements YangModelParser { return result; } - private void validateModule( - Map> modules, - ModuleBuilder builder) { + private void fixUnresolvedNodes( + final Map> modules, + final ModuleBuilder builder) { resolveDirtyNodes(modules, builder); - resolveAugments(modules, builder); resolveIdentities(modules, builder); + resolveUses(modules, builder); + resolveUnknownNodes(modules, builder); } /** @@ -210,47 +227,53 @@ public class YangModelParserImpl implements YangModelParser { * current module */ private void resolveDirtyNodes( - Map> modules, - ModuleBuilder module) { + final Map> modules, + final ModuleBuilder module) { final Map, TypeAwareBuilder> dirtyNodes = module .getDirtyNodes(); if (!dirtyNodes.isEmpty()) { for (Map.Entry, TypeAwareBuilder> entry : dirtyNodes .entrySet()) { - TypeAwareBuilder typeToResolve = entry.getValue(); - if (typeToResolve instanceof UnionTypeBuilder) { - UnionTypeBuilder union = (UnionTypeBuilder) typeToResolve; - List> unionTypes = union.getTypes(); - List toRemove = new ArrayList(); + final TypeAwareBuilder nodeToResolve = entry.getValue(); + // different handling for union types + if (nodeToResolve instanceof UnionTypeBuilder) { + final UnionTypeBuilder union = (UnionTypeBuilder) nodeToResolve; + final List> unionTypes = union.getTypes(); + final List toRemove = new ArrayList(); for (TypeDefinition td : unionTypes) { if (td instanceof UnknownType) { - UnknownType unknownType = (UnknownType) td; - TypeDefinitionBuilder resolvedType = findTargetTypeUnion( - typeToResolve, unknownType, modules, module); + final UnknownType unknownType = (UnknownType) td; + final TypeDefinitionBuilder resolvedType = resolveTypeUnion( + nodeToResolve, unknownType, modules, module); union.setType(resolvedType); toRemove.add(unknownType); } } unionTypes.removeAll(toRemove); + } else if (nodeToResolve.getTypedef() instanceof IdentityrefTypeBuilder) { + IdentityrefTypeBuilder idref = (IdentityrefTypeBuilder) nodeToResolve + .getTypedef(); + nodeToResolve.setType(new IdentityrefType(findFullQName( + modules, module, idref), idref.getPath())); } else { - TypeDefinitionBuilder resolvedType = findTargetType( - typeToResolve, modules, module); - typeToResolve.setType(resolvedType); + final TypeDefinitionBuilder resolvedType = resolveType( + nodeToResolve, modules, module); + nodeToResolve.setType(resolvedType); } } } } - private TypeDefinitionBuilder findTargetType( - TypeAwareBuilder typeToResolve, - Map> modules, - ModuleBuilder builder) { - TypeConstraints constraints = new TypeConstraints(); + private TypeDefinitionBuilder resolveType( + final TypeAwareBuilder typeToResolve, + final Map> modules, + final ModuleBuilder builder) { + final TypeConstraints constraints = new TypeConstraints(); - TypeDefinitionBuilder targetType = findTypedef(typeToResolve, modules, - builder); - TypeConstraints tConstraints = findConstraints(typeToResolve, + final TypeDefinitionBuilder targetType = getTypedefBuilder( + typeToResolve, modules, builder); + final TypeConstraints tConstraints = findConstraints(typeToResolve, constraints, modules, builder); targetType.setRanges(tConstraints.getRange()); targetType.setLengths(tConstraints.getLength()); @@ -260,15 +283,16 @@ public class YangModelParserImpl implements YangModelParser { return targetType; } - private TypeDefinitionBuilder findTargetTypeUnion( - TypeAwareBuilder typeToResolve, UnknownType unknownType, - Map> modules, - ModuleBuilder builder) { - TypeConstraints constraints = new TypeConstraints(); + private TypeDefinitionBuilder resolveTypeUnion( + final TypeAwareBuilder typeToResolve, + final UnknownType unknownType, + final Map> modules, + final ModuleBuilder builder) { + final TypeConstraints constraints = new TypeConstraints(); - TypeDefinitionBuilder targetType = findTypedefUnion(typeToResolve, + final TypeDefinitionBuilder targetType = getUnionBuilder(typeToResolve, unknownType, modules, builder); - TypeConstraints tConstraints = findConstraints(typeToResolve, + final TypeConstraints tConstraints = findConstraints(typeToResolve, constraints, modules, builder); targetType.setRanges(tConstraints.getRange()); targetType.setLengths(tConstraints.getLength()); @@ -278,68 +302,66 @@ public class YangModelParserImpl implements YangModelParser { return targetType; } - private TypeDefinitionBuilder findTypedef(TypeAwareBuilder typeToResolve, - Map> modules, - ModuleBuilder builder) { + private TypeDefinitionBuilder getTypedefBuilder( + final TypeAwareBuilder nodeToResolve, + final Map> modules, + final ModuleBuilder builder) { - TypeDefinition baseTypeToResolve = typeToResolve.getType(); - if (baseTypeToResolve != null - && !(baseTypeToResolve instanceof UnknownType)) { - return (TypeDefinitionBuilder) typeToResolve; + final TypeDefinition nodeToResolveBase = nodeToResolve.getType(); + if (nodeToResolveBase != null + && !(nodeToResolveBase instanceof UnknownType)) { + return (TypeDefinitionBuilder) nodeToResolve; } - UnknownType unknownType = (UnknownType) typeToResolve.getType(); - - QName unknownTypeQName = unknownType.getQName(); - String unknownTypeName = unknownTypeQName.getLocalName(); - String unknownTypePrefix = unknownTypeQName.getPrefix(); + final UnknownType unknownType = (UnknownType) nodeToResolve.getType(); + final QName unknownTypeQName = unknownType.getQName(); // search for module which contains referenced typedef - ModuleBuilder dependentModule = findDependentModule(modules, builder, - unknownTypePrefix); - TypeDefinitionBuilder lookedUpBuilder = findTypedefBuilder( - dependentModule.getModuleTypedefs(), unknownTypeName); - - TypeDefinitionBuilder lookedUpBuilderCopy = copyTypedefBuilder( - lookedUpBuilder, typeToResolve instanceof TypeDefinitionBuilder); - TypeDefinitionBuilder resolvedCopy = resolveCopiedBuilder( + final ModuleBuilder dependentModule = findDependentModule(modules, + builder, unknownTypeQName.getPrefix()); + final TypeDefinitionBuilder lookedUpBuilder = findTypedefBuilderByName( + dependentModule, unknownTypeQName.getLocalName()); + + final TypeDefinitionBuilder lookedUpBuilderCopy = copyTypedefBuilder( + lookedUpBuilder, nodeToResolve instanceof TypeDefinitionBuilder); + final TypeDefinitionBuilder resolvedCopy = resolveCopiedBuilder( lookedUpBuilderCopy, modules, dependentModule); return resolvedCopy; } - private TypeDefinitionBuilder findTypedefUnion( - TypeAwareBuilder typeToResolve, UnknownType unknownType, - Map> modules, - ModuleBuilder builder) { + private TypeDefinitionBuilder getUnionBuilder( + final TypeAwareBuilder nodeToResolve, + final UnknownType unknownType, + final Map> modules, + final ModuleBuilder module) { - TypeDefinition baseTypeToResolve = typeToResolve.getType(); + final TypeDefinition baseTypeToResolve = nodeToResolve.getType(); if (baseTypeToResolve != null && !(baseTypeToResolve instanceof UnknownType)) { - return (TypeDefinitionBuilder) typeToResolve; + return (TypeDefinitionBuilder) nodeToResolve; } - QName unknownTypeQName = unknownType.getQName(); - String unknownTypeName = unknownTypeQName.getLocalName(); - String unknownTypePrefix = unknownTypeQName.getPrefix(); - + final QName unknownTypeQName = unknownType.getQName(); // search for module which contains referenced typedef - ModuleBuilder dependentModule = findDependentModule(modules, builder, - unknownTypePrefix); - TypeDefinitionBuilder lookedUpBuilder = findTypedefBuilder( - dependentModule.getModuleTypedefs(), unknownTypeName); - - TypeDefinitionBuilder lookedUpBuilderCopy = copyTypedefBuilder( - lookedUpBuilder, typeToResolve instanceof TypeDefinitionBuilder); - TypeDefinitionBuilder resolvedCopy = resolveCopiedBuilder( + final ModuleBuilder dependentModule = findDependentModule(modules, + module, unknownTypeQName.getPrefix()); + final TypeDefinitionBuilder lookedUpBuilder = findTypedefBuilderByName( + dependentModule, unknownTypeQName.getLocalName()); + + final TypeDefinitionBuilder lookedUpBuilderCopy = copyTypedefBuilder( + lookedUpBuilder, nodeToResolve instanceof TypeDefinitionBuilder); + final TypeDefinitionBuilder resolvedCopy = resolveCopiedBuilder( lookedUpBuilderCopy, modules, dependentModule); return resolvedCopy; } - private TypeDefinitionBuilder copyTypedefBuilder(TypeDefinitionBuilder old, - boolean seekByTypedefBuilder) { + private TypeDefinitionBuilder copyTypedefBuilder( + final TypeDefinitionBuilder old, final boolean seekByTypedefBuilder) { if (old instanceof UnionTypeBuilder) { - UnionTypeBuilder oldUnion = (UnionTypeBuilder) old; - UnionTypeBuilder newUnion = new UnionTypeBuilder(); + final UnionTypeBuilder oldUnion = (UnionTypeBuilder) old; + final UnionTypeBuilder newUnion = new UnionTypeBuilder( + oldUnion.getActualPath(), oldUnion.getNamespace(), + oldUnion.getRevision()); for (TypeDefinition td : oldUnion.getTypes()) { newUnion.setType(td); } @@ -349,17 +371,19 @@ public class YangModelParserImpl implements YangModelParser { return newUnion; } - QName oldQName = old.getQName(); - QName newQName = new QName(oldQName.getNamespace(), - oldQName.getRevision(), oldQName.getPrefix(), - oldQName.getLocalName()); - TypeDefinitionBuilder tdb = new TypedefBuilder(newQName); + final QName oldName = old.getQName(); + final QName newName = new QName(oldName.getNamespace(), + oldName.getRevision(), oldName.getPrefix(), + oldName.getLocalName()); + final TypeDefinitionBuilder tdb = new TypedefBuilder(newName); tdb.setRanges(old.getRanges()); tdb.setLengths(old.getLengths()); tdb.setPatterns(old.getPatterns()); + tdb.setFractionDigits(old.getFractionDigits()); + tdb.setPath(old.getPath()); - TypeDefinition oldType = old.getType(); + final TypeDefinition oldType = old.getType(); if (oldType == null) { tdb.setType(old.getTypedef()); } else { @@ -377,18 +401,18 @@ public class YangModelParserImpl implements YangModelParser { } private TypeDefinitionBuilder resolveCopiedBuilder( - TypeDefinitionBuilder copied, - Map> modules, - ModuleBuilder builder) { - - if (copied instanceof UnionTypeBuilder) { - UnionTypeBuilder union = (UnionTypeBuilder) copied; - List> unionTypes = union.getTypes(); - List toRemove = new ArrayList(); + final TypeDefinitionBuilder copy, + final Map> modules, + final ModuleBuilder builder) { + + if (copy instanceof UnionTypeBuilder) { + final UnionTypeBuilder union = (UnionTypeBuilder) copy; + final List> unionTypes = union.getTypes(); + final List toRemove = new ArrayList(); for (TypeDefinition td : unionTypes) { if (td instanceof UnknownType) { - UnknownType unknownType = (UnknownType) td; - TypeDefinitionBuilder resolvedType = findTargetTypeUnion( + final UnknownType unknownType = (UnknownType) td; + final TypeDefinitionBuilder resolvedType = resolveTypeUnion( union, unknownType, modules, builder); union.setType(resolvedType); toRemove.add(unknownType); @@ -399,118 +423,113 @@ public class YangModelParserImpl implements YangModelParser { return union; } - TypeDefinition base = copied.getType(); - TypeDefinitionBuilder baseTdb = copied.getTypedef(); + final TypeDefinition base = copy.getType(); + final TypeDefinitionBuilder baseTdb = copy.getTypedef(); if (base != null && !(base instanceof UnknownType)) { - return copied; + return copy; } else if (base instanceof UnknownType) { - UnknownType unknownType = (UnknownType) base; - QName unknownTypeQName = unknownType.getQName(); - String unknownTypePrefix = unknownTypeQName.getPrefix(); - ModuleBuilder dependentModule = findDependentModule(modules, + final UnknownType unknownType = (UnknownType) base; + final QName unknownTypeQName = unknownType.getQName(); + final String unknownTypePrefix = unknownTypeQName.getPrefix(); + final ModuleBuilder dependentModule = findDependentModule(modules, builder, unknownTypePrefix); - TypeDefinitionBuilder unknownTypeBuilder = findTypedef(copied, + final TypeDefinitionBuilder utBuilder = getTypedefBuilder(copy, modules, dependentModule); - copied.setType(unknownTypeBuilder); - return copied; + copy.setType(utBuilder); + return copy; } else if (base == null && baseTdb != null) { // make a copy of baseTypeDef and call again - TypeDefinitionBuilder baseTdbCopy = copyTypedefBuilder(baseTdb, - true); - TypeDefinitionBuilder baseTdbCopyResolved = resolveCopiedBuilder( + final TypeDefinitionBuilder baseTdbCopy = copyTypedefBuilder( + baseTdb, true); + final TypeDefinitionBuilder baseTdbCopyResolved = resolveCopiedBuilder( baseTdbCopy, modules, builder); - copied.setType(baseTdbCopyResolved); - return copied; + copy.setType(baseTdbCopyResolved); + return copy; } else { - throw new IllegalStateException( - "TypeDefinitionBuilder in unexpected state"); + throw new IllegalStateException("Failed to resolve type " + + copy.getQName().getLocalName()); } } - private TypeDefinitionBuilder findTypedef(QName unknownTypeQName, - Map> modules, - ModuleBuilder builder) { - - String unknownTypeName = unknownTypeQName.getLocalName(); - String unknownTypePrefix = unknownTypeQName.getPrefix(); - + private TypeDefinitionBuilder findTypedefBuilder( + final QName unknownTypeQName, + final Map> modules, + final ModuleBuilder builder) { // search for module which contains referenced typedef - ModuleBuilder dependentModule = findDependentModule(modules, builder, - unknownTypePrefix); - - TypeDefinitionBuilder lookedUpBuilder = findTypedefBuilder( - dependentModule.getModuleTypedefs(), unknownTypeName); - - TypeDefinitionBuilder copied = copyTypedefBuilder(lookedUpBuilder, true); - return copied; + final ModuleBuilder dependentModule = findDependentModule(modules, + builder, unknownTypeQName.getPrefix()); + final TypeDefinitionBuilder lookedUpBuilder = findTypedefBuilderByName( + dependentModule, unknownTypeQName.getLocalName()); + return copyTypedefBuilder(lookedUpBuilder, true); } - private TypeConstraints findConstraints(TypeAwareBuilder typeToResolve, - TypeConstraints constraints, - Map> modules, - ModuleBuilder builder) { - + private TypeConstraints findConstraints( + final TypeAwareBuilder nodeToResolve, + final TypeConstraints constraints, + final Map> modules, + final ModuleBuilder builder) { // union type cannot be restricted - if (typeToResolve instanceof UnionTypeBuilder) { + if (nodeToResolve instanceof UnionTypeBuilder) { return constraints; } // if referenced type is UnknownType again, search recursively with // current constraints - TypeDefinition referencedType = typeToResolve.getType(); + final TypeDefinition referencedType = nodeToResolve.getType(); + List ranges = Collections.emptyList(); + List lengths = Collections.emptyList(); + List patterns = Collections.emptyList(); + Integer fractionDigits = null; if (referencedType == null) { - TypeDefinitionBuilder tdb = (TypeDefinitionBuilder) typeToResolve; - final List ranges = tdb.getRanges(); + final TypeDefinitionBuilder tdb = (TypeDefinitionBuilder) nodeToResolve; + ranges = tdb.getRanges(); constraints.addRanges(ranges); - final List lengths = tdb.getLengths(); + lengths = tdb.getLengths(); constraints.addLengths(lengths); - final List patterns = tdb.getPatterns(); + patterns = tdb.getPatterns(); constraints.addPatterns(patterns); - final Integer fractionDigits = tdb.getFractionDigits(); + fractionDigits = tdb.getFractionDigits(); constraints.setFractionDigits(fractionDigits); return constraints; } else if (referencedType instanceof ExtendedType) { - ExtendedType ext = (ExtendedType) referencedType; - final List ranges = ext.getRanges(); + final ExtendedType ext = (ExtendedType) referencedType; + ranges = ext.getRanges(); constraints.addRanges(ranges); - final List lengths = ext.getLengths(); + lengths = ext.getLengths(); constraints.addLengths(lengths); - final List patterns = ext.getPatterns(); + patterns = ext.getPatterns(); constraints.addPatterns(patterns); - final Integer fractionDigits = ext.getFractionDigits(); + fractionDigits = ext.getFractionDigits(); constraints.setFractionDigits(fractionDigits); return findConstraints( - findTypedef(ext.getQName(), modules, builder), constraints, - modules, builder); + findTypedefBuilder(ext.getQName(), modules, builder), + constraints, modules, builder); } else if (referencedType instanceof UnknownType) { - UnknownType unknown = (UnknownType) referencedType; - - final List ranges = unknown.getRangeStatements(); + final UnknownType unknown = (UnknownType) referencedType; + ranges = unknown.getRangeStatements(); constraints.addRanges(ranges); - final List lengths = unknown - .getLengthStatements(); + lengths = unknown.getLengthStatements(); constraints.addLengths(lengths); - final List patterns = unknown.getPatterns(); + patterns = unknown.getPatterns(); constraints.addPatterns(patterns); - final Integer fractionDigits = unknown.getFractionDigits(); + fractionDigits = unknown.getFractionDigits(); constraints.setFractionDigits(fractionDigits); String unknownTypePrefix = unknown.getQName().getPrefix(); if (unknownTypePrefix == null || "".equals(unknownTypePrefix)) { unknownTypePrefix = builder.getPrefix(); } - ModuleBuilder dependentModule = findDependentModule(modules, + final ModuleBuilder dependentModule = findDependentModule(modules, builder, unknown.getQName().getPrefix()); - TypeDefinitionBuilder unknownTypeBuilder = findTypedef( + final TypeDefinitionBuilder utBuilder = findTypedefBuilder( unknown.getQName(), modules, builder); - return findConstraints(unknownTypeBuilder, constraints, modules, + return findConstraints(utBuilder, constraints, modules, dependentModule); } else { // HANDLE BASE YANG TYPE mergeConstraints(referencedType, constraints); return constraints; } - } /** @@ -523,9 +542,11 @@ public class YangModelParserImpl implements YangModelParser { * name of searched typedef * @return typedef with name equals to given name */ - private TypeDefinitionBuilder findTypedefBuilder( - Set typedefs, String name) { + private TypeDefinitionBuilder findTypedefBuilderByName( + final ModuleBuilder dependentModule, final String name) { TypeDefinitionBuilder result = null; + final Set typedefs = dependentModule + .getModuleTypedefs(); for (TypeDefinitionBuilder td : typedefs) { if (td.getQName().getLocalName().equals(name)) { result = td; @@ -533,8 +554,9 @@ public class YangModelParserImpl implements YangModelParser { } } if (result == null) { - throw new YangParseException( - "Target module does not contain typedef '" + name + "'."); + throw new YangParseException("Target module '" + + dependentModule.getName() + + "' does not contain typedef '" + name + "'."); } return result; } @@ -545,8 +567,8 @@ public class YangModelParserImpl implements YangModelParser { * @param referencedType * @param constraints */ - private void mergeConstraints(TypeDefinition referencedType, - TypeConstraints constraints) { + private void mergeConstraints(final TypeDefinition referencedType, + final TypeConstraints constraints) { if (referencedType instanceof DecimalTypeDefinition) { constraints.addRanges(((DecimalTypeDefinition) referencedType) @@ -569,55 +591,117 @@ public class YangModelParserImpl implements YangModelParser { } /** - * Go through all augmentation definitions and resolve them. This means find - * referenced node and add child nodes to it. + * Go through all augmentation definitions and resolve them. This method + * also finds referenced node and add child nodes to it. * * @param modules * all available modules - * @param module - * current module */ private void resolveAugments( - Map> modules, - ModuleBuilder module) { - Set augmentBuilders = module - .getAddedAugments(); - - Set augments = new HashSet(); - for (AugmentationSchemaBuilder augmentBuilder : augmentBuilders) { - SchemaPath augmentTargetSchemaPath = augmentBuilder.getTargetPath(); - String prefix = null; - List augmentTargetPath = new ArrayList(); - - for (QName pathPart : augmentTargetSchemaPath.getPath()) { - prefix = pathPart.getPrefix(); - augmentTargetPath.add(pathPart.getLocalName()); + final Map> modules) { + final List allModulesList = new ArrayList(); + final Set allModulesSet = new HashSet(); + for (Map.Entry> entry : modules + .entrySet()) { + for (Map.Entry inner : entry.getValue() + .entrySet()) { + allModulesList.add(inner.getValue()); + allModulesSet.add(inner.getValue()); } - ModuleBuilder dependentModule = findDependentModule(modules, - module, prefix); - augmentTargetPath.add(0, dependentModule.getName()); + } - AugmentationTargetBuilder augmentTarget = (AugmentationTargetBuilder) dependentModule - .getNode(augmentTargetPath); - AugmentationSchema result = augmentBuilder.build(); - augmentTarget.addAugmentation(result); - fillAugmentTarget(augmentBuilder, (ChildNodeBuilder) augmentTarget); - augments.add(result); + for (int i = 0; i < allModulesList.size(); i++) { + final ModuleBuilder module = allModulesList.get(i); + // try to resolve augments in module + resolveAugment(modules, module); + // while all augments are not resolved + final Iterator allModulesIterator = allModulesSet + .iterator(); + while (!(module.getAugmentsResolved() == module.getAddedAugments() + .size())) { + ModuleBuilder nextModule = null; + // try resolve other module augments + try { + nextModule = allModulesIterator.next(); + resolveAugment(modules, nextModule); + } catch (NoSuchElementException e) { + throw new YangParseException( + "Failed to resolve augments in module '" + + module.getName() + "'.", e); + } + // then try to resolve first module again + resolveAugment(modules, module); + } } - module.setAugmentations(augments); } /** - * Add all augment's child nodes to given target. * - * @param augment - * @param target + * @param modules + * all available modules + * @param module + * current module */ - private void fillAugmentTarget(AugmentationSchemaBuilder augment, - ChildNodeBuilder target) { - for (DataSchemaNodeBuilder builder : augment.getChildNodes()) { - builder.setAugmenting(true); - target.addChildNode(builder); + private void resolveAugment( + final Map> modules, + final ModuleBuilder module) { + if (module.getAugmentsResolved() < module.getAddedAugments().size()) { + for (AugmentationSchemaBuilder augmentBuilder : module + .getAddedAugments()) { + final SchemaPath augmentTargetSchemaPath = augmentBuilder + .getTargetPath(); + final List path = augmentTargetSchemaPath.getPath(); + + int i = 0; + final QName qname = path.get(i); + String prefix = qname.getPrefix(); + if (prefix == null) { + prefix = module.getPrefix(); + } + + DataSchemaNodeBuilder currentParent = null; + final ModuleBuilder dependentModule = findDependentModule( + modules, module, prefix); + for (DataSchemaNodeBuilder child : dependentModule + .getChildNodes()) { + final QName childQName = child.getQName(); + if (childQName.getLocalName().equals(qname.getLocalName())) { + currentParent = child; + i++; + break; + } + } + + for (; i < path.size(); i++) { + final QName currentQName = path.get(i); + DataSchemaNodeBuilder newParent = null; + for (DataSchemaNodeBuilder child : ((ChildNodeBuilder) currentParent) + .getChildNodes()) { + final QName childQName = child.getQName(); + if (childQName.getLocalName().equals( + currentQName.getLocalName())) { + newParent = child; + break; + } + } + if (newParent == null) { + break; // node not found, quit search + } else { + currentParent = newParent; + } + } + + final QName currentQName = currentParent.getQName(); + final QName lastAugmentPathElement = path.get(path.size() - 1); + if (currentQName.getLocalName().equals( + lastAugmentPathElement.getLocalName())) { + ParserUtils.fillAugmentTarget(augmentBuilder, + (ChildNodeBuilder) currentParent); + ((AugmentationTargetBuilder) currentParent) + .addAugmentation(augmentBuilder); + module.augmentResolved(); + } + } } } @@ -631,26 +715,27 @@ public class YangModelParserImpl implements YangModelParser { * module being resolved */ private void resolveIdentities( - Map> modules, - ModuleBuilder module) { - Set identities = module.getAddedIdentities(); + final Map> modules, + final ModuleBuilder module) { + final Set identities = module + .getAddedIdentities(); for (IdentitySchemaNodeBuilder identity : identities) { - String baseIdentityName = identity.getBaseIdentityName(); + final String baseIdentityName = identity.getBaseIdentityName(); if (baseIdentityName != null) { String baseIdentityPrefix = null; String baseIdentityLocalName = null; if (baseIdentityName.contains(":")) { - String[] splitted = baseIdentityName.split(":"); + final String[] splitted = baseIdentityName.split(":"); baseIdentityPrefix = splitted[0]; baseIdentityLocalName = splitted[1]; } else { baseIdentityPrefix = module.getPrefix(); baseIdentityLocalName = baseIdentityName; } - ModuleBuilder dependentModule = findDependentModule(modules, - module, baseIdentityPrefix); + final ModuleBuilder dependentModule = findDependentModule( + modules, module, baseIdentityPrefix); - Set dependentModuleIdentities = dependentModule + final Set dependentModuleIdentities = dependentModule .getAddedIdentities(); for (IdentitySchemaNodeBuilder idBuilder : dependentModuleIdentities) { if (idBuilder.getQName().getLocalName() @@ -662,6 +747,267 @@ public class YangModelParserImpl implements YangModelParser { } } + /** + * Go through uses statements defined in current module and resolve their + * refine statements. + * + * @param modules + * all modules + * @param module + * module being resolved + */ + private void resolveUses( + final Map> modules, + final ModuleBuilder module) { + final Map, UsesNodeBuilder> moduleUses = module + .getAddedUsesNodes(); + for (Map.Entry, UsesNodeBuilder> entry : moduleUses + .entrySet()) { + final List key = entry.getKey(); + final UsesNodeBuilder usesNode = entry.getValue(); + + final String groupingName = key.get(key.size() - 1); + + for (RefineHolder refine : usesNode.getRefines()) { + // refine statements + final String defaultStr = refine.getDefaultStr(); + final Boolean mandatory = refine.isMandatory(); + final MustDefinition must = refine.getMust(); + final Boolean presence = refine.isPresence(); + final Integer min = refine.getMinElements(); + final Integer max = refine.getMaxElements(); + final List unknownNodes = refine + .getUnknownNodes(); + + Builder refineTarget = getRefineTargetBuilder(groupingName, + refine, modules, module); + if (refineTarget instanceof LeafSchemaNodeBuilder) { + final LeafSchemaNodeBuilder leaf = (LeafSchemaNodeBuilder) refineTarget; + if (defaultStr != null && !("".equals(defaultStr))) { + leaf.setDefaultStr(defaultStr); + } + if (mandatory != null) { + leaf.getConstraints().setMandatory(mandatory); + } + if (must != null) { + leaf.getConstraints().addMustDefinition(must); + } + if (unknownNodes != null) { + for (UnknownSchemaNodeBuilder unknown : unknownNodes) { + leaf.addUnknownSchemaNode(unknown); + } + } + usesNode.addRefineNode(leaf); + } else if (refineTarget instanceof ContainerSchemaNodeBuilder) { + final ContainerSchemaNodeBuilder container = (ContainerSchemaNodeBuilder) refineTarget; + if (presence != null) { + container.setPresence(presence); + } + if (must != null) { + container.getConstraints().addMustDefinition(must); + } + if (unknownNodes != null) { + for (UnknownSchemaNodeBuilder unknown : unknownNodes) { + container.addUnknownSchemaNode(unknown); + } + } + usesNode.addRefineNode(container); + } else if (refineTarget instanceof ListSchemaNodeBuilder) { + final ListSchemaNodeBuilder list = (ListSchemaNodeBuilder) refineTarget; + if (must != null) { + list.getConstraints().addMustDefinition(must); + } + if (min != null) { + list.getConstraints().setMinElements(min); + } + if (max != null) { + list.getConstraints().setMaxElements(max); + } + if (unknownNodes != null) { + for (UnknownSchemaNodeBuilder unknown : unknownNodes) { + list.addUnknownSchemaNode(unknown); + } + } + } else if (refineTarget instanceof LeafListSchemaNodeBuilder) { + final LeafListSchemaNodeBuilder leafList = (LeafListSchemaNodeBuilder) getRefineTargetBuilder( + groupingName, refine, modules, module); + if (must != null) { + leafList.getConstraints().addMustDefinition(must); + } + if (min != null) { + leafList.getConstraints().setMinElements(min); + } + if (max != null) { + leafList.getConstraints().setMaxElements(max); + } + if (unknownNodes != null) { + for (UnknownSchemaNodeBuilder unknown : unknownNodes) { + leafList.addUnknownSchemaNode(unknown); + } + } + } else if (refineTarget instanceof ChoiceBuilder) { + final ChoiceBuilder choice = (ChoiceBuilder) refineTarget; + if (defaultStr != null) { + choice.setDefaultCase(defaultStr); + } + if (mandatory != null) { + choice.getConstraints().setMandatory(mandatory); + } + if (unknownNodes != null) { + for (UnknownSchemaNodeBuilder unknown : unknownNodes) { + choice.addUnknownSchemaNode(unknown); + } + } + } else if (refineTarget instanceof AnyXmlBuilder) { + final AnyXmlBuilder anyXml = (AnyXmlBuilder) refineTarget; + if (mandatory != null) { + anyXml.getConstraints().setMandatory(mandatory); + } + if (must != null) { + anyXml.getConstraints().addMustDefinition(must); + } + if (unknownNodes != null) { + for (UnknownSchemaNodeBuilder unknown : unknownNodes) { + anyXml.addUnknownSchemaNode(unknown); + } + } + } + } + } + } + + /** + * Find original builder of refine node and return copy of this builder. + * + * @param groupingPath + * path to grouping which contains node to refine + * @param refine + * refine object containing informations about refine + * @param modules + * all loaded modules + * @param module + * current module + * @return copy of Builder object of node to be refined if it is present in + * grouping, null otherwise + */ + private Builder getRefineTargetBuilder(final String groupingPath, + final RefineHolder refine, + final Map> modules, + final ModuleBuilder module) { + Builder result = null; + final Builder lookedUpBuilder = findRefineTargetBuilder(groupingPath, + refine.getName(), modules, module); + if (lookedUpBuilder instanceof LeafSchemaNodeBuilder) { + result = ParserUtils + .copyLeafBuilder((LeafSchemaNodeBuilder) lookedUpBuilder); + } else if (lookedUpBuilder instanceof ContainerSchemaNodeBuilder) { + result = ParserUtils + .copyContainerBuilder((ContainerSchemaNodeBuilder) lookedUpBuilder); + } else if (lookedUpBuilder instanceof ListSchemaNodeBuilder) { + result = ParserUtils + .copyListBuilder((ListSchemaNodeBuilder) lookedUpBuilder); + } else if (lookedUpBuilder instanceof LeafListSchemaNodeBuilder) { + result = ParserUtils + .copyLeafListBuilder((LeafListSchemaNodeBuilder) lookedUpBuilder); + } else if (lookedUpBuilder instanceof ChoiceBuilder) { + result = ParserUtils + .copyChoiceBuilder((ChoiceBuilder) lookedUpBuilder); + } else if (lookedUpBuilder instanceof AnyXmlBuilder) { + result = ParserUtils + .copyAnyXmlBuilder((AnyXmlBuilder) lookedUpBuilder); + } else { + throw new YangParseException("Target '" + refine.getName() + + "' can not be refined"); + } + return result; + } + + /** + * Find builder of refine node. + * + * @param groupingPath + * path to grouping which contains node to refine + * @param refineNodeName + * name of node to be refined + * @param modules + * all loaded modules + * @param module + * current module + * @return Builder object of refine node if it is present in grouping, null + * otherwise + */ + private Builder findRefineTargetBuilder(final String groupingPath, + final String refineNodeName, + final Map> modules, + final ModuleBuilder module) { + final SchemaPath path = ParserUtils.parseUsesPath(groupingPath); + final List builderPath = new ArrayList(); + String prefix = null; + for (QName qname : path.getPath()) { + builderPath.add(qname.getLocalName()); + prefix = qname.getPrefix(); + } + if (prefix == null) { + prefix = module.getPrefix(); + } + + final ModuleBuilder dependentModule = findDependentModule(modules, + module, prefix); + builderPath.add(0, "grouping"); + builderPath.add(0, dependentModule.getName()); + final GroupingBuilder builder = (GroupingBuilder) dependentModule + .getNode(builderPath); + + return builder.getChildNode(refineNodeName); + } + + private QName findFullQName( + final Map> modules, + final ModuleBuilder module, final IdentityrefTypeBuilder idref) { + QName result = null; + String baseString = idref.getBaseString(); + if (baseString.contains(":")) { + String[] splittedBase = baseString.split(":"); + if (splittedBase.length > 2) { + throw new YangParseException( + "Failed to parse identityref base: " + baseString); + } + String prefix = splittedBase[0]; + String name = splittedBase[1]; + ModuleBuilder dependentModule = findDependentModule(modules, + module, prefix); + result = new QName(dependentModule.getNamespace(), + dependentModule.getRevision(), prefix, name); + } else { + result = new QName(module.getNamespace(), module.getRevision(), + module.getPrefix(), baseString); + } + return result; + } + + private void resolveUnknownNodes( + final Map> modules, + final ModuleBuilder module) { + for (UnknownSchemaNodeBuilder usnb : module.getAddedUnknownNodes()) { + QName nodeType = usnb.getNodeType(); + if (nodeType.getNamespace() == null + || nodeType.getRevision() == null) { + try { + ModuleBuilder dependentModule = findDependentModule( + modules, module, nodeType.getPrefix()); + QName newNodeType = new QName( + dependentModule.getNamespace(), + dependentModule.getRevision(), + nodeType.getPrefix(), nodeType.getLocalName()); + usnb.setNodeType(newNodeType); + } catch (YangParseException e) { + logger.debug("Failed to find unknown node type: " + + nodeType); + } + } + } + } + /** * Find dependent module based on given prefix * @@ -674,24 +1020,32 @@ public class YangModelParserImpl implements YangModelParser { * @return */ private ModuleBuilder findDependentModule( - Map> modules, - ModuleBuilder module, String prefix) { + final Map> modules, + final ModuleBuilder module, final String prefix) { ModuleBuilder dependentModule = null; Date dependentModuleRevision = null; if (prefix.equals(module.getPrefix())) { dependentModule = module; } else { - ModuleImport dependentModuleImport = getModuleImport(module, prefix); + final ModuleImport dependentModuleImport = ParserUtils + .getModuleImport(module, prefix); if (dependentModuleImport == null) { throw new YangParseException("No import found with prefix '" + prefix + "' in module " + module.getName() + "'."); } - String dependentModuleName = dependentModuleImport.getModuleName(); + final String dependentModuleName = dependentModuleImport + .getModuleName(); dependentModuleRevision = dependentModuleImport.getRevision(); - TreeMap moduleBuildersByRevision = modules + final TreeMap moduleBuildersByRevision = modules .get(dependentModuleName); + if (moduleBuildersByRevision == null) { + throw new YangParseException( + "Failed to find dependent module '" + + dependentModuleName + "' needed by module '" + + module.getName() + "'."); + } if (dependentModuleRevision == null) { dependentModule = moduleBuildersByRevision.lastEntry() .getValue(); @@ -710,36 +1064,10 @@ public class YangModelParserImpl implements YangModelParser { return dependentModule; } - /** - * Get module import referenced by given prefix. - * - * @param builder - * module to search - * @param prefix - * prefix associated with import - * @return ModuleImport based on given prefix - */ - private ModuleImport getModuleImport(ModuleBuilder builder, String prefix) { - ModuleImport moduleImport = null; - for (ModuleImport mi : builder.getModuleImports()) { - if (mi.getPrefix().equals(prefix)) { - moduleImport = mi; - break; - } - } - return moduleImport; - } - - private Date createEpochTime() { - Calendar calendar = Calendar.getInstance(); - calendar.setTimeInMillis(0); - return calendar.getTime(); - } - private static class SchemaContextImpl implements SchemaContext { private final Set modules; - private SchemaContextImpl(Set modules) { + private SchemaContextImpl(final Set modules) { this.modules = modules; } @@ -783,6 +1111,31 @@ public class YangModelParserImpl implements YangModelParser { } return extensions; } + + @Override + public Module findModuleByName(final String name, final Date revision) { + if ((name != null) && (revision != null)) { + for (final Module module : modules) { + if (module.getName().equals(name) + && module.getRevision().equals(revision)) { + return module; + } + } + } + return null; + } + + @Override + public Module findModuleByNamespace(final URI namespace) { + if (namespace != null) { + for (final Module module : modules) { + if (module.getNamespace().equals(namespace)) { + return module; + } + } + } + return null; + } } }