X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?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=27a65c1168f24fa822f1c13175d4c4a5a0cef0e2;hb=6e72d221f55cfac71ee6e594b62cb5af9672614a;hp=d7c6711affb740de272f754e76e331561782f8ba;hpb=09ea3cfd65c19cca18d9bc6dff42fb78a0d74836;p=controller.git 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 d7c6711aff..27a65c1168 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 @@ -9,7 +9,9 @@ package org.opendaylight.controller.yang.model.parser.impl; import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; @@ -26,22 +28,6 @@ import org.antlr.v4.runtime.tree.ParseTree; 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.model.api.type.BinaryTypeDefinition; -import org.opendaylight.controller.model.api.type.BitsTypeDefinition; -import org.opendaylight.controller.model.api.type.BitsTypeDefinition.Bit; -import org.opendaylight.controller.model.api.type.DecimalTypeDefinition; -import org.opendaylight.controller.model.api.type.InstanceIdentifierTypeDefinition; -import org.opendaylight.controller.model.api.type.IntegerTypeDefinition; -import org.opendaylight.controller.model.api.type.LengthConstraint; -import org.opendaylight.controller.model.api.type.PatternConstraint; -import org.opendaylight.controller.model.api.type.RangeConstraint; -import org.opendaylight.controller.model.api.type.StringTypeDefinition; -import org.opendaylight.controller.model.util.BaseConstraints; -import org.opendaylight.controller.model.util.BinaryType; -import org.opendaylight.controller.model.util.BitsType; -import org.opendaylight.controller.model.util.StringType; -import org.opendaylight.controller.model.util.UnknownType; -import org.opendaylight.controller.model.util.YangTypesConverter; import org.opendaylight.controller.yang.common.QName; import org.opendaylight.controller.yang.model.api.AugmentationSchema; import org.opendaylight.controller.yang.model.api.DataSchemaNode; @@ -53,6 +39,13 @@ import org.opendaylight.controller.yang.model.api.RpcDefinition; import org.opendaylight.controller.yang.model.api.SchemaContext; import org.opendaylight.controller.yang.model.api.SchemaPath; import org.opendaylight.controller.yang.model.api.TypeDefinition; +import org.opendaylight.controller.yang.model.api.type.BinaryTypeDefinition; +import org.opendaylight.controller.yang.model.api.type.DecimalTypeDefinition; +import org.opendaylight.controller.yang.model.api.type.IntegerTypeDefinition; +import org.opendaylight.controller.yang.model.api.type.LengthConstraint; +import org.opendaylight.controller.yang.model.api.type.PatternConstraint; +import org.opendaylight.controller.yang.model.api.type.RangeConstraint; +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; @@ -60,7 +53,14 @@ import org.opendaylight.controller.yang.model.parser.builder.api.ChildNodeBuilde import org.opendaylight.controller.yang.model.parser.builder.api.DataSchemaNodeBuilder; 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.impl.IdentitySchemaNodeBuilder; 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.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.UnknownType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -70,36 +70,58 @@ public class YangModelParserImpl implements YangModelParser { .getLogger(YangModelParserImpl.class); @Override - public Module parseYangModel(String yangFile) { - final Map> modules = loadFiles(yangFile); - Set result = build(modules); + public Module parseYangModel(final String yangFile) { + final Map> modules = resolveModuleBuildersFromStreams(yangFile); + final Set result = build(modules); return result.iterator().next(); } @Override - public Set parseYangModels(String... yangFiles) { - final Map> modules = loadFiles(yangFiles); - Set result = build(modules); - return result; + public Set parseYangModels(final String... yangFiles) { + final Map> modules = resolveModuleBuildersFromStreams(yangFiles); + return build(modules); + } + + @Override + public Set parseYangModelsFromStreams( + final InputStream... yangModelStreams) { + final Map> modules = resolveModuleBuildersFromStreams(yangModelStreams); + return build(modules); } @Override - public SchemaContext resolveSchemaContext(Set modules) { + public SchemaContext resolveSchemaContext(final Set modules) { return new SchemaContextImpl(modules); } - private Map> loadFiles( + private Map> resolveModuleBuildersFromStreams( String... yangFiles) { - final Map> modules = new HashMap>(); + 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); + } - final YangModelParserListenerImpl yangModelParser = new YangModelParserListenerImpl(); + private Map> resolveModuleBuildersFromStreams( + InputStream... yangFiles) { + final Map> modules = new HashMap>(); final ParseTreeWalker walker = new ParseTreeWalker(); + final List trees = parseStreams(yangFiles); + final ModuleBuilder[] builders = new ModuleBuilder[trees.size()]; - List trees = parseFiles(yangFiles); - - ModuleBuilder[] builders = new ModuleBuilder[trees.size()]; - + YangModelParserListenerImpl yangModelParser = null; for (int i = 0; i < trees.size(); i++) { + yangModelParser = new YangModelParserListenerImpl(); walker.walk(yangModelParser, trees.get(i)); builders[i] = yangModelParser.getModuleBuilder(); } @@ -110,54 +132,51 @@ public class YangModelParserImpl implements YangModelParser { if (builderRevision == null) { builderRevision = createEpochTime(); } - TreeMap builderByRevision = modules .get(builderName); if (builderByRevision == null) { builderByRevision = new TreeMap(); } builderByRevision.put(builderRevision, builder); - modules.put(builderName, builderByRevision); } return modules; } - private List parseFiles(String... yangFileNames) { - List trees = new ArrayList(); - for (String fileName : yangFileNames) { - trees.add(parseFile(fileName)); + private List parseStreams(InputStream... yangStreams) { + final List trees = new ArrayList(); + for (InputStream yangStream : yangStreams) { + trees.add(parseStream(yangStream)); } return trees; } - private ParseTree parseFile(String yangFileName) { + private ParseTree parseStream(InputStream yangStream) { ParseTree result = null; try { - final File yangFile = new File(yangFileName); - final FileInputStream inStream = new FileInputStream(yangFile); - final ANTLRInputStream input = new ANTLRInputStream(inStream); + final ANTLRInputStream input = new ANTLRInputStream(yangStream); final YangLexer lexer = new YangLexer(input); final CommonTokenStream tokens = new CommonTokenStream(lexer); final YangParser parser = new YangParser(tokens); result = parser.yang(); } catch (IOException e) { - logger.warn("Exception while reading yang file: " + yangFileName, e); + logger.warn("Exception while reading yang file: " + yangStream, e); } return result; } private Set build(Map> modules) { - // first validate + // validate for (Map.Entry> entry : modules .entrySet()) { for (Map.Entry childEntry : entry.getValue() .entrySet()) { ModuleBuilder moduleBuilder = childEntry.getValue(); - validateBuilder(modules, moduleBuilder); + validateModule(modules, moduleBuilder); } } - // then build + + // build final Set result = new HashSet(); for (Map.Entry> entry : modules .entrySet()) { @@ -165,20 +184,20 @@ public class YangModelParserImpl implements YangModelParser { for (Map.Entry childEntry : entry.getValue() .entrySet()) { ModuleBuilder moduleBuilder = childEntry.getValue(); - modulesByRevision.put(childEntry.getKey(), - moduleBuilder.build()); - result.add(moduleBuilder.build()); + Module module = moduleBuilder.build(); + modulesByRevision.put(childEntry.getKey(), module); + result.add(module); } } - return result; } - private void validateBuilder( + private void validateModule( Map> modules, ModuleBuilder builder) { - resolveTypedefs(modules, builder); + resolveDirtyNodes(modules, builder); resolveAugments(modules, builder); + resolveIdentities(modules, builder); } /** @@ -187,176 +206,284 @@ public class YangModelParserImpl implements YangModelParser { * * @param modules * all available modules - * @param builder + * @param module * current module */ - private void resolveTypedefs( + private void resolveDirtyNodes( Map> modules, - ModuleBuilder builder) { - Map, TypeAwareBuilder> dirtyNodes = builder + ModuleBuilder module) { + final Map, TypeAwareBuilder> dirtyNodes = module .getDirtyNodes(); - if (dirtyNodes.size() == 0) { - return; - } else { + if (!dirtyNodes.isEmpty()) { for (Map.Entry, TypeAwareBuilder> entry : dirtyNodes .entrySet()) { + TypeAwareBuilder typeToResolve = entry.getValue(); - Map foundedTypeDefinitionBuilder = findTypeDefinitionBuilderWithConstraints( - modules, entry.getValue(), builder); - TypeDefinitionBuilder targetType = foundedTypeDefinitionBuilder - .entrySet().iterator().next().getKey(); - TypeConstraints constraints = foundedTypeDefinitionBuilder - .entrySet().iterator().next().getValue(); - - UnknownType ut = (UnknownType) typeToResolve.getType(); - - // RANGE - List ranges = ut.getRangeStatements(); - resolveRanges(ranges, typeToResolve, targetType, modules, - builder); - - // LENGTH - List lengths = ut.getLengthStatements(); - resolveLengths(lengths, typeToResolve, targetType, modules, - builder); - - // PATTERN - List patterns = ut.getPatterns(); - - // Fraction Digits - Integer fractionDigits = ut.getFractionDigits(); - - TypeDefinition type = targetType.getBaseType(); - String typeName = type.getQName().getLocalName(); - - // MERGE CONSTRAINTS (enumeration and leafref omitted because - // they have no restrictions) - if (type instanceof DecimalTypeDefinition) { - List fullRanges = new ArrayList(); - fullRanges.addAll(constraints.getRanges()); - fullRanges.addAll(ranges); - Integer fd = fractionDigits == null ? constraints - .getFractionDigits() : fractionDigits; - type = YangTypesConverter.javaTypeForBaseYangDecimal64Type( - fullRanges, fd); - } else if (type instanceof IntegerTypeDefinition) { - List fullRanges = new ArrayList(); - fullRanges.addAll(constraints.getRanges()); - fullRanges.addAll(ranges); - if (typeName.startsWith("int")) { - type = YangTypesConverter - .javaTypeForBaseYangSignedIntegerType(typeName, - fullRanges); - } else { - type = YangTypesConverter - .javaTypeForBaseYangUnsignedIntegerType( - typeName, fullRanges); + if (typeToResolve instanceof UnionTypeBuilder) { + UnionTypeBuilder union = (UnionTypeBuilder) typeToResolve; + List> unionTypes = union.getTypes(); + List toRemove = new ArrayList(); + for (TypeDefinition td : unionTypes) { + if (td instanceof UnknownType) { + UnknownType unknownType = (UnknownType) td; + TypeDefinitionBuilder resolvedType = findTargetTypeUnion( + typeToResolve, unknownType, modules, module); + union.setType(resolvedType); + toRemove.add(unknownType); + } } - } else if (type instanceof StringTypeDefinition) { - List fullLengths = new ArrayList(); - fullLengths.addAll(constraints.getLengths()); - fullLengths.addAll(lengths); - List fullPatterns = new ArrayList(); - fullPatterns.addAll(constraints.getPatterns()); - fullPatterns.addAll(patterns); - type = new StringType(fullLengths, fullPatterns); - } else if (type instanceof BitsTypeDefinition) { - // TODO: add 'length' restriction to BitsType - BitsTypeDefinition bitsType = (BitsTypeDefinition) type; - List bits = bitsType.getBits(); - type = new BitsType(bits); - } else if (type instanceof BinaryTypeDefinition) { - type = new BinaryType(null, lengths, null); - } else if (typeName.equals("instance-identifier")) { - // TODO: instance-identifier - /* - * boolean requireInstance = isRequireInstance(typeBody); - * type = new InstanceIdentifier(null, requireInstance); - */ + unionTypes.removeAll(toRemove); + } else { + TypeDefinitionBuilder resolvedType = findTargetType( + typeToResolve, modules, module); + typeToResolve.setType(resolvedType); } - typeToResolve.setType(type); } } } - private TypeDefinitionBuilder findTypeDefinitionBuilder( + private TypeDefinitionBuilder findTargetType( + TypeAwareBuilder typeToResolve, Map> modules, - TypeAwareBuilder typeBuilder, ModuleBuilder builder) { - Map result = findTypeDefinitionBuilderWithConstraints( - modules, typeBuilder, builder); - return result.entrySet().iterator().next().getKey(); + ModuleBuilder builder) { + TypeConstraints constraints = new TypeConstraints(); + + TypeDefinitionBuilder targetType = findTypedef(typeToResolve, modules, + builder); + TypeConstraints tConstraints = findConstraints(typeToResolve, + constraints, modules, builder); + targetType.setRanges(tConstraints.getRange()); + targetType.setLengths(tConstraints.getLength()); + targetType.setPatterns(tConstraints.getPatterns()); + targetType.setFractionDigits(tConstraints.getFractionDigits()); + + return targetType; } - private Map findTypeDefinitionBuilderWithConstraints( + private TypeDefinitionBuilder findTargetTypeUnion( + TypeAwareBuilder typeToResolve, UnknownType unknownType, Map> modules, - TypeAwareBuilder typeBuilder, ModuleBuilder builder) { - return findTypeDefinitionBuilderWithConstraints(new TypeConstraints(), - modules, typeBuilder, builder); + ModuleBuilder builder) { + TypeConstraints constraints = new TypeConstraints(); + + TypeDefinitionBuilder targetType = findTypedefUnion(typeToResolve, + unknownType, modules, builder); + TypeConstraints tConstraints = findConstraints(typeToResolve, + constraints, modules, builder); + targetType.setRanges(tConstraints.getRange()); + targetType.setLengths(tConstraints.getLength()); + targetType.setPatterns(tConstraints.getPatterns()); + targetType.setFractionDigits(tConstraints.getFractionDigits()); + + return targetType; } - /** - * Traverse through all referenced types chain until base YANG type is - * founded. - * - * @param constraints - * current type constraints - * @param modules - * all available modules - * @param typeBuilder - * type builder which contains type - * @param builder - * current module - * @return map, where key is type referenced and value is its constraints - */ - private Map findTypeDefinitionBuilderWithConstraints( - TypeConstraints constraints, + private TypeDefinitionBuilder findTypedef(TypeAwareBuilder typeToResolve, Map> modules, - TypeAwareBuilder typeBuilder, ModuleBuilder builder) { - Map result = new HashMap(); + ModuleBuilder builder) { - UnknownType type = (UnknownType) typeBuilder.getType(); - QName typeQName = type.getQName(); - String typeName = type.getQName().getLocalName(); - String prefix = typeQName.getPrefix(); + TypeDefinition baseTypeToResolve = typeToResolve.getType(); + if (baseTypeToResolve != null + && !(baseTypeToResolve instanceof UnknownType)) { + return (TypeDefinitionBuilder) typeToResolve; + } + + UnknownType unknownType = (UnknownType) typeToResolve.getType(); + + QName unknownTypeQName = unknownType.getQName(); + String unknownTypeName = unknownTypeQName.getLocalName(); + String unknownTypePrefix = unknownTypeQName.getPrefix(); // search for module which contains referenced typedef - ModuleBuilder dependentModuleBuilder; - if (prefix.equals(builder.getPrefix())) { - dependentModuleBuilder = builder; - } else { - ModuleImport dependentModuleImport = getModuleImport(builder, - prefix); - String dependentModuleName = dependentModuleImport.getModuleName(); - Date dependentModuleRevision = dependentModuleImport.getRevision(); - TreeMap moduleBuildersByRevision = modules - .get(dependentModuleName); - if (dependentModuleRevision == null) { - dependentModuleBuilder = moduleBuildersByRevision.lastEntry() - .getValue(); - } else { - dependentModuleBuilder = moduleBuildersByRevision - .get(dependentModuleRevision); + ModuleBuilder dependentModule = findDependentModule(modules, builder, + unknownTypePrefix); + TypeDefinitionBuilder lookedUpBuilder = findTypedefBuilder( + dependentModule.getModuleTypedefs(), unknownTypeName); + + TypeDefinitionBuilder lookedUpBuilderCopy = copyTypedefBuilder( + lookedUpBuilder, typeToResolve instanceof TypeDefinitionBuilder); + TypeDefinitionBuilder resolvedCopy = resolveCopiedBuilder( + lookedUpBuilderCopy, modules, dependentModule); + return resolvedCopy; + } + + private TypeDefinitionBuilder findTypedefUnion( + TypeAwareBuilder typeToResolve, UnknownType unknownType, + Map> modules, + ModuleBuilder builder) { + + TypeDefinition baseTypeToResolve = typeToResolve.getType(); + if (baseTypeToResolve != null + && !(baseTypeToResolve instanceof UnknownType)) { + return (TypeDefinitionBuilder) typeToResolve; + } + + QName unknownTypeQName = unknownType.getQName(); + String unknownTypeName = unknownTypeQName.getLocalName(); + String unknownTypePrefix = unknownTypeQName.getPrefix(); + + // 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( + lookedUpBuilderCopy, modules, dependentModule); + return resolvedCopy; + } + + private TypeDefinitionBuilder copyTypedefBuilder(TypeDefinitionBuilder old, + boolean seekByTypedefBuilder) { + if (old instanceof UnionTypeBuilder) { + UnionTypeBuilder oldUnion = (UnionTypeBuilder) old; + UnionTypeBuilder newUnion = new UnionTypeBuilder(); + for (TypeDefinition td : oldUnion.getTypes()) { + newUnion.setType(td); } + for (TypeDefinitionBuilder tdb : oldUnion.getTypedefs()) { + newUnion.setType(copyTypedefBuilder(tdb, true)); + } + return newUnion; } - // pull all typedef statements from dependent module... - final Set typedefs = dependentModuleBuilder - .getModuleTypedefs(); - // and search for referenced typedef - TypeDefinitionBuilder lookedUpBuilder = null; - for (TypeDefinitionBuilder tdb : typedefs) { - QName qname = tdb.getQName(); - if (qname.getLocalName().equals(typeName)) { - lookedUpBuilder = tdb; - break; + QName oldQName = old.getQName(); + QName newQName = new QName(oldQName.getNamespace(), + oldQName.getRevision(), oldQName.getPrefix(), + oldQName.getLocalName()); + TypeDefinitionBuilder tdb = new TypedefBuilder(newQName); + + tdb.setRanges(old.getRanges()); + tdb.setLengths(old.getLengths()); + tdb.setPatterns(old.getPatterns()); + + TypeDefinition oldType = old.getType(); + if (oldType == null) { + tdb.setType(old.getTypedef()); + } else { + tdb.setType(oldType); + } + + if (!seekByTypedefBuilder) { + tdb.setDescription(old.getDescription()); + tdb.setReference(old.getReference()); + tdb.setStatus(old.getStatus()); + tdb.setDefaultValue(old.getDefaultValue()); + tdb.setUnits(old.getUnits()); + } + return tdb; + } + + 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(); + for (TypeDefinition td : unionTypes) { + if (td instanceof UnknownType) { + UnknownType unknownType = (UnknownType) td; + TypeDefinitionBuilder resolvedType = findTargetTypeUnion( + union, unknownType, modules, builder); + union.setType(resolvedType); + toRemove.add(unknownType); + } } + unionTypes.removeAll(toRemove); + + return union; + } + + TypeDefinition base = copied.getType(); + TypeDefinitionBuilder baseTdb = copied.getTypedef(); + if (base != null && !(base instanceof UnknownType)) { + return copied; + } else if (base instanceof UnknownType) { + UnknownType unknownType = (UnknownType) base; + QName unknownTypeQName = unknownType.getQName(); + String unknownTypePrefix = unknownTypeQName.getPrefix(); + ModuleBuilder dependentModule = findDependentModule(modules, + builder, unknownTypePrefix); + TypeDefinitionBuilder unknownTypeBuilder = findTypedef(copied, + modules, dependentModule); + copied.setType(unknownTypeBuilder); + return copied; + } else if (base == null && baseTdb != null) { + // make a copy of baseTypeDef and call again + TypeDefinitionBuilder baseTdbCopy = copyTypedefBuilder(baseTdb, + true); + TypeDefinitionBuilder baseTdbCopyResolved = resolveCopiedBuilder( + baseTdbCopy, modules, builder); + copied.setType(baseTdbCopyResolved); + return copied; + } else { + throw new IllegalStateException( + "TypeDefinitionBuilder in unexpected state"); + } + } + + private TypeDefinitionBuilder findTypedef(QName unknownTypeQName, + Map> modules, + ModuleBuilder builder) { + + String unknownTypeName = unknownTypeQName.getLocalName(); + String unknownTypePrefix = unknownTypeQName.getPrefix(); + + // 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; + } + + private TypeConstraints findConstraints(TypeAwareBuilder typeToResolve, + TypeConstraints constraints, + Map> modules, + ModuleBuilder builder) { + + // union type cannot be restricted + if (typeToResolve instanceof UnionTypeBuilder) { + return constraints; } // if referenced type is UnknownType again, search recursively with // current constraints - TypeDefinition referencedType = lookedUpBuilder.getBaseType(); - if (referencedType instanceof UnknownType) { - UnknownType unknown = (UnknownType) lookedUpBuilder.getBaseType(); + TypeDefinition referencedType = typeToResolve.getType(); + if (referencedType == null) { + TypeDefinitionBuilder tdb = (TypeDefinitionBuilder) typeToResolve; + final List ranges = tdb.getRanges(); + constraints.addRanges(ranges); + final List lengths = tdb.getLengths(); + constraints.addLengths(lengths); + final List patterns = tdb.getPatterns(); + constraints.addPatterns(patterns); + final Integer fractionDigits = tdb.getFractionDigits(); + constraints.setFractionDigits(fractionDigits); + return constraints; + } else if (referencedType instanceof ExtendedType) { + ExtendedType ext = (ExtendedType) referencedType; + final List ranges = ext.getRanges(); + constraints.addRanges(ranges); + final List lengths = ext.getLengths(); + constraints.addLengths(lengths); + final List patterns = ext.getPatterns(); + constraints.addPatterns(patterns); + final Integer fractionDigits = ext.getFractionDigits(); + constraints.setFractionDigits(fractionDigits); + return findConstraints( + findTypedef(ext.getQName(), modules, builder), constraints, + modules, builder); + } else if (referencedType instanceof UnknownType) { + UnknownType unknown = (UnknownType) referencedType; final List ranges = unknown.getRangeStatements(); constraints.addRanges(ranges); @@ -365,35 +492,79 @@ public class YangModelParserImpl implements YangModelParser { constraints.addLengths(lengths); final List patterns = unknown.getPatterns(); constraints.addPatterns(patterns); - return findTypeDefinitionBuilderWithConstraints(constraints, - modules, (TypeAwareBuilder) lookedUpBuilder, - dependentModuleBuilder); + final Integer fractionDigits = unknown.getFractionDigits(); + constraints.setFractionDigits(fractionDigits); + + String unknownTypePrefix = unknown.getQName().getPrefix(); + if (unknownTypePrefix == null || "".equals(unknownTypePrefix)) { + unknownTypePrefix = builder.getPrefix(); + } + ModuleBuilder dependentModule = findDependentModule(modules, + builder, unknown.getQName().getPrefix()); + TypeDefinitionBuilder unknownTypeBuilder = findTypedef( + unknown.getQName(), modules, builder); + return findConstraints(unknownTypeBuilder, constraints, modules, + dependentModule); } else { - // pull restriction from this base type and add them to - // 'constraints' - if (referencedType instanceof DecimalTypeDefinition) { - constraints.addRanges(((DecimalTypeDefinition) referencedType) - .getRangeStatements()); - constraints - .setFractionDigits(((DecimalTypeDefinition) referencedType) - .getFractionDigits()); - } else if (referencedType instanceof IntegerTypeDefinition) { - constraints.addRanges(((IntegerTypeDefinition) referencedType) - .getRangeStatements()); - } else if (referencedType instanceof StringTypeDefinition) { - constraints.addPatterns(((StringTypeDefinition) referencedType) - .getPatterns()); - } else if (referencedType instanceof BitsTypeDefinition) { - // TODO: add 'length' restriction to BitsType - } else if (referencedType instanceof BinaryTypeDefinition) { - // TODO - } else if (referencedType instanceof InstanceIdentifierTypeDefinition) { - // TODO: instance-identifier + // HANDLE BASE YANG TYPE + mergeConstraints(referencedType, constraints); + return constraints; + } + + } + + /** + * Go through all typedef statements from given module and search for one + * with given name + * + * @param typedefs + * typedef statements to search + * @param name + * name of searched typedef + * @return typedef with name equals to given name + */ + private TypeDefinitionBuilder findTypedefBuilder( + Set typedefs, String name) { + TypeDefinitionBuilder result = null; + for (TypeDefinitionBuilder td : typedefs) { + if (td.getQName().getLocalName().equals(name)) { + result = td; + break; } + } + if (result == null) { + throw new YangParseException( + "Target module does not contain typedef '" + name + "'."); + } + return result; + } - result.put(lookedUpBuilder, constraints); - // return lookedUpBuilder; - return result; + /** + * Pull restriction from referenced type and add them to given constraints + * + * @param referencedType + * @param constraints + */ + private void mergeConstraints(TypeDefinition referencedType, + TypeConstraints constraints) { + + if (referencedType instanceof DecimalTypeDefinition) { + constraints.addRanges(((DecimalTypeDefinition) referencedType) + .getRangeStatements()); + constraints + .setFractionDigits(((DecimalTypeDefinition) referencedType) + .getFractionDigits()); + } else if (referencedType instanceof IntegerTypeDefinition) { + constraints.addRanges(((IntegerTypeDefinition) referencedType) + .getRangeStatements()); + } else if (referencedType instanceof StringTypeDefinition) { + constraints.addPatterns(((StringTypeDefinition) referencedType) + .getPatterns()); + constraints.addLengths(((StringTypeDefinition) referencedType) + .getLengthStatements()); + } else if (referencedType instanceof BinaryTypeDefinition) { + constraints.addLengths(((BinaryTypeDefinition) referencedType) + .getLengthConstraints()); } } @@ -403,13 +574,13 @@ public class YangModelParserImpl implements YangModelParser { * * @param modules * all available modules - * @param builder + * @param module * current module */ private void resolveAugments( Map> modules, - ModuleBuilder builder) { - Set augmentBuilders = builder + ModuleBuilder module) { + Set augmentBuilders = module .getAddedAugments(); Set augments = new HashSet(); @@ -417,27 +588,14 @@ public class YangModelParserImpl implements YangModelParser { SchemaPath augmentTargetSchemaPath = augmentBuilder.getTargetPath(); String prefix = null; List augmentTargetPath = new ArrayList(); + for (QName pathPart : augmentTargetSchemaPath.getPath()) { prefix = pathPart.getPrefix(); augmentTargetPath.add(pathPart.getLocalName()); } - ModuleImport dependentModuleImport = getModuleImport(builder, - prefix); - String dependentModuleName = dependentModuleImport.getModuleName(); - augmentTargetPath.add(0, dependentModuleName); - - Date dependentModuleRevision = dependentModuleImport.getRevision(); - - TreeMap moduleBuildersByRevision = modules - .get(dependentModuleName); - ModuleBuilder dependentModule; - if (dependentModuleRevision == null) { - dependentModule = moduleBuildersByRevision.lastEntry() - .getValue(); - } else { - dependentModule = moduleBuildersByRevision - .get(dependentModuleRevision); - } + ModuleBuilder dependentModule = findDependentModule(modules, + module, prefix); + augmentTargetPath.add(0, dependentModule.getName()); AugmentationTargetBuilder augmentTarget = (AugmentationTargetBuilder) dependentModule .getNode(augmentTargetPath); @@ -446,7 +604,7 @@ public class YangModelParserImpl implements YangModelParser { fillAugmentTarget(augmentBuilder, (ChildNodeBuilder) augmentTarget); augments.add(result); } - builder.setAugmentations(augments); + module.setAugmentations(augments); } /** @@ -464,148 +622,118 @@ public class YangModelParserImpl implements YangModelParser { } /** - * Get module import referenced by given prefix. + * Go through identity statements defined in current module and resolve + * their 'base' statement if present. * - * @param builder - * module to search - * @param prefix - * prefix associated with import - * @return ModuleImport based on given prefix + * @param modules + * all modules + * @param module + * module being resolved */ - private ModuleImport getModuleImport(ModuleBuilder builder, String prefix) { - ModuleImport moduleImport = null; - for (ModuleImport mi : builder.getModuleImports()) { - if (mi.getPrefix().equals(prefix)) { - moduleImport = mi; - break; + private void resolveIdentities( + Map> modules, + ModuleBuilder module) { + Set identities = module.getAddedIdentities(); + for (IdentitySchemaNodeBuilder identity : identities) { + String baseIdentityName = identity.getBaseIdentityName(); + if (baseIdentityName != null) { + String baseIdentityPrefix = null; + String baseIdentityLocalName = null; + if (baseIdentityName.contains(":")) { + String[] splitted = baseIdentityName.split(":"); + baseIdentityPrefix = splitted[0]; + baseIdentityLocalName = splitted[1]; + } else { + baseIdentityPrefix = module.getPrefix(); + baseIdentityLocalName = baseIdentityName; + } + ModuleBuilder dependentModule = findDependentModule(modules, + module, baseIdentityPrefix); + + Set dependentModuleIdentities = dependentModule + .getAddedIdentities(); + for (IdentitySchemaNodeBuilder idBuilder : dependentModuleIdentities) { + if (idBuilder.getQName().getLocalName() + .equals(baseIdentityLocalName)) { + identity.setBaseIdentity(idBuilder); + } + } } } - return moduleImport; } /** - * Helper method for resolving special 'min' or 'max' values in range - * constraint + * Find dependent module based on given prefix * - * @param ranges - * ranges to resolve - * @param typeToResolve - * type to resolve - * @param targetType - * target type * @param modules * all available modules - * @param builder + * @param module * current module + * @param prefix + * target module prefix + * @return */ - private void resolveRanges(List ranges, - TypeAwareBuilder typeToResolve, TypeDefinitionBuilder targetType, + private ModuleBuilder findDependentModule( Map> modules, - ModuleBuilder builder) { - if (ranges != null && ranges.size() > 0) { - Long min = (Long) ranges.get(0).getMin(); - Long max = (Long) ranges.get(ranges.size() - 1).getMax(); - // if range contains one of the special values 'min' or 'max' - if (min.equals(Long.MIN_VALUE) || max.equals(Long.MAX_VALUE)) { - Long[] values = parseRangeConstraint(typeToResolve, targetType, - modules, builder); - if (min.equals(Long.MIN_VALUE)) { - min = values[0]; - RangeConstraint oldFirst = ranges.get(0); - RangeConstraint newFirst = BaseConstraints.rangeConstraint( - min, oldFirst.getMax(), oldFirst.getDescription(), - oldFirst.getReference()); - ranges.set(0, newFirst); - } - if (max.equals(Long.MAX_VALUE)) { - max = values[1]; - RangeConstraint oldLast = ranges.get(ranges.size() - 1); - RangeConstraint newLast = BaseConstraints.rangeConstraint( - oldLast.getMin(), max, oldLast.getDescription(), - oldLast.getReference()); - ranges.set(ranges.size() - 1, newLast); - } + ModuleBuilder module, String prefix) { + ModuleBuilder dependentModule = null; + Date dependentModuleRevision = null; + + if (prefix.equals(module.getPrefix())) { + dependentModule = module; + } else { + ModuleImport dependentModuleImport = getModuleImport(module, prefix); + if (dependentModuleImport == null) { + throw new YangParseException("No import found with prefix '" + + prefix + "' in module " + module.getName() + "'."); + } + String dependentModuleName = dependentModuleImport.getModuleName(); + dependentModuleRevision = dependentModuleImport.getRevision(); + + TreeMap moduleBuildersByRevision = modules + .get(dependentModuleName); + if (dependentModuleRevision == null) { + dependentModule = moduleBuildersByRevision.lastEntry() + .getValue(); + } else { + dependentModule = moduleBuildersByRevision + .get(dependentModuleRevision); } } + + if (dependentModule == null) { + throw new YangParseException( + "Failed to find dependent module with prefix '" + prefix + + "' and revision '" + dependentModuleRevision + + "'."); + } + return dependentModule; } /** - * Helper method for resolving special 'min' or 'max' values in length - * constraint + * Get module import referenced by given prefix. * - * @param ranges - * ranges to resolve - * @param typeToResolve - * type to resolve - * @param targetType - * target type - * @param modules - * all available modules * @param builder - * current module + * module to search + * @param prefix + * prefix associated with import + * @return ModuleImport based on given prefix */ - private void resolveLengths(List lengths, - TypeAwareBuilder typeToResolve, TypeDefinitionBuilder targetType, - Map> modules, - ModuleBuilder builder) { - if (lengths != null && lengths.size() > 0) { - Long min = lengths.get(0).getMin(); - Long max = lengths.get(lengths.size() - 1).getMax(); - // if length contains one of the special values 'min' or 'max' - if (min.equals(Long.MIN_VALUE) || max.equals(Long.MAX_VALUE)) { - Long[] values = parseRangeConstraint(typeToResolve, targetType, - modules, builder); - if (min.equals(Long.MIN_VALUE)) { - min = values[0]; - LengthConstraint oldFirst = lengths.get(0); - LengthConstraint newFirst = BaseConstraints - .lengthConstraint(min, oldFirst.getMax(), - oldFirst.getDescription(), - oldFirst.getReference()); - lengths.set(0, newFirst); - } - if (max.equals(Long.MAX_VALUE)) { - max = values[1]; - LengthConstraint oldLast = lengths.get(lengths.size() - 1); - LengthConstraint newLast = BaseConstraints - .lengthConstraint(oldLast.getMin(), max, - oldLast.getDescription(), - oldLast.getReference()); - lengths.set(lengths.size() - 1, newLast); - } + private ModuleImport getModuleImport(ModuleBuilder builder, String prefix) { + ModuleImport moduleImport = null; + for (ModuleImport mi : builder.getModuleImports()) { + if (mi.getPrefix().equals(prefix)) { + moduleImport = mi; + break; } } - } - - private Long[] parseRangeConstraint(TypeAwareBuilder typeToResolve, - TypeDefinitionBuilder targetType, - Map> modules, - ModuleBuilder builder) { - TypeDefinition targetBaseType = targetType.getBaseType(); - - if (targetBaseType instanceof IntegerTypeDefinition) { - IntegerTypeDefinition itd = (IntegerTypeDefinition) targetBaseType; - List ranges = itd.getRangeStatements(); - Long min = (Long) ranges.get(0).getMin(); - Long max = (Long) ranges.get(ranges.size() - 1).getMax(); - return new Long[] { min, max }; - } else if (targetBaseType instanceof DecimalTypeDefinition) { - DecimalTypeDefinition dtd = (DecimalTypeDefinition) targetBaseType; - List ranges = dtd.getRangeStatements(); - Long min = (Long) ranges.get(0).getMin(); - Long max = (Long) ranges.get(ranges.size() - 1).getMax(); - return new Long[] { min, max }; - } else { - return parseRangeConstraint(typeToResolve, - findTypeDefinitionBuilder(modules, typeToResolve, builder), - modules, builder); - } + return moduleImport; } private Date createEpochTime() { - Calendar c = Calendar.getInstance(); - c.setTimeInMillis(0); - return c.getTime(); + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis(0); + return calendar.getTime(); } private static class SchemaContextImpl implements SchemaContext { @@ -657,45 +785,4 @@ public class YangModelParserImpl implements YangModelParser { } } - private static class TypeConstraints { - private final List ranges = new ArrayList(); - private final List lengths = new ArrayList(); - private final List patterns = new ArrayList(); - private Integer fractionDigits; - - public List getRanges() { - return ranges; - } - - public void addRanges(List ranges) { - this.ranges.addAll(0, ranges); - } - - public List getLengths() { - return lengths; - } - - public void addLengths(List lengths) { - this.lengths.addAll(0, lengths); - } - - public List getPatterns() { - return patterns; - } - - public void addPatterns(List patterns) { - this.patterns.addAll(0, patterns); - } - - public Integer getFractionDigits() { - return fractionDigits; - } - - public void setFractionDigits(Integer fractionDigits) { - if (fractionDigits != null) { - this.fractionDigits = fractionDigits; - } - } - } - }