X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;ds=sidebyside;f=opendaylight%2Fsal%2Fyang-prototype%2Fcode-generator%2Fyang-model-parser-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fcontroller%2Fyang%2Fmodel%2Fparser%2Fimpl%2FYangModelParserImpl.java;h=fce723edff9ea6ebd32b7d814ad371d00abaa53a;hb=refs%2Fchanges%2F03%2F103%2F3;hp=d86b49d78bccc6c219a475ea2d9ad89ac491bd7b;hpb=ca85a6f3a39b406ab122fe985ee010a41489f658;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 d86b49d78b..fce723edff 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,7 +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.util.UnknownType; import org.opendaylight.controller.yang.common.QName; import org.opendaylight.controller.yang.model.api.AugmentationSchema; import org.opendaylight.controller.yang.model.api.DataSchemaNode; @@ -37,6 +38,17 @@ import org.opendaylight.controller.yang.model.api.NotificationDefinition; 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.BitsTypeDefinition; +import org.opendaylight.controller.yang.model.api.type.DecimalTypeDefinition; +import org.opendaylight.controller.yang.model.api.type.InstanceIdentifierTypeDefinition; +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.api.type.BitsTypeDefinition.Bit; 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; @@ -45,6 +57,13 @@ import org.opendaylight.controller.yang.model.parser.builder.api.DataSchemaNodeB 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.ModuleBuilder; +import org.opendaylight.controller.yang.model.parser.builder.impl.UnionTypeBuilder; +import org.opendaylight.controller.yang.model.util.BaseConstraints; +import org.opendaylight.controller.yang.model.util.BinaryType; +import org.opendaylight.controller.yang.model.util.BitsType; +import org.opendaylight.controller.yang.model.util.StringType; +import org.opendaylight.controller.yang.model.util.UnknownType; +import org.opendaylight.controller.yang.model.util.YangTypesConverter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -55,14 +74,22 @@ public class YangModelParserImpl implements YangModelParser { @Override public Module parseYangModel(String yangFile) { - final Map> modules = loadFiles(yangFile); + final Map> modules = resolveModuleBuildersFromStreams(yangFile); Set result = build(modules); return result.iterator().next(); } @Override public Set parseYangModels(String... yangFiles) { - final Map> modules = loadFiles(yangFiles); + final Map> modules = resolveModuleBuildersFromStreams(yangFiles); + Set result = build(modules); + return result; + } + + @Override + public Set parseYangModelsFromStreams( + InputStream... yangModelStreams) { + final Map> modules = resolveModuleBuildersFromStreams(yangModelStreams); Set result = build(modules); return result; } @@ -72,22 +99,100 @@ public class YangModelParserImpl implements YangModelParser { return new SchemaContextImpl(modules); } + private Map> resolveModuleBuildersFromStreams( + String... yangFiles) { + InputStream[] streams = new InputStream[yangFiles.length]; + for(int i = 0; i < yangFiles.length; i++) { + final String yangFileName = yangFiles[i]; + final File yangFile = new File(yangFileName); + FileInputStream inStream = null; + 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) { + final Map> modules = new HashMap>(); + + final YangModelParserListenerImpl yangModelParser = new YangModelParserListenerImpl(); + final ParseTreeWalker walker = new ParseTreeWalker(); + + List trees = parseStreams(yangFiles); + + ModuleBuilder[] builders = new ModuleBuilder[trees.size()]; + + for (int i = 0; i < trees.size(); i++) { + walker.walk(yangModelParser, trees.get(i)); + builders[i] = yangModelParser.getModuleBuilder(); + } + + for (ModuleBuilder builder : builders) { + final String builderName = builder.getName(); + Date builderRevision = builder.getRevision(); + 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 parseStreams(InputStream... yangStreams) { + List trees = new ArrayList(); + for (InputStream yangStream : yangStreams) { + trees.add(parseStream(yangStream)); + } + return trees; + } + + private ParseTree parseStream(InputStream yangStream) { + ParseTree result = null; + try { + 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: " + yangStream, e); + } + return result; + } + private Set build(Map> modules) { // first validate - for (Map.Entry> entry : modules.entrySet()) { - for (Map.Entry childEntry : entry.getValue().entrySet()) { + for (Map.Entry> entry : modules + .entrySet()) { + for (Map.Entry childEntry : entry.getValue() + .entrySet()) { ModuleBuilder moduleBuilder = childEntry.getValue(); validateBuilder(modules, moduleBuilder); } } - // then build final Set result = new HashSet(); - for (Map.Entry> entry : modules.entrySet()) { + for (Map.Entry> entry : modules + .entrySet()) { final Map modulesByRevision = new HashMap(); - for (Map.Entry childEntry : entry.getValue().entrySet()) { + for (Map.Entry childEntry : entry.getValue() + .entrySet()) { ModuleBuilder moduleBuilder = childEntry.getValue(); - modulesByRevision.put(childEntry.getKey(),moduleBuilder.build()); + modulesByRevision.put(childEntry.getKey(), + moduleBuilder.build()); result.add(moduleBuilder.build()); } } @@ -95,65 +200,274 @@ public class YangModelParserImpl implements YangModelParser { return result; } - private void validateBuilder(Map> modules, ModuleBuilder builder) { + private void validateBuilder( + Map> modules, + ModuleBuilder builder) { resolveTypedefs(modules, builder); resolveAugments(modules, builder); } - private void resolveTypedefs(Map> modules, ModuleBuilder builder) { - Map, TypeAwareBuilder> dirtyNodes = builder.getDirtyNodes(); + /** + * Search for dirty nodes (node which contains UnknownType) and resolve + * unknown types. + * + * @param modules + * all available modules + * @param module + * current module + */ + private void resolveTypedefs( + Map> modules, + ModuleBuilder module) { + Map, TypeAwareBuilder> dirtyNodes = module + .getDirtyNodes(); if (dirtyNodes.size() == 0) { return; } else { - for (Map.Entry, TypeAwareBuilder> entry : dirtyNodes.entrySet()) { - TypeAwareBuilder tab = entry.getValue(); - TypeDefinitionBuilder tdb = findTypeDefinitionBuilder(modules,entry.getValue(), builder); - tab.setType(tdb.build()); + for (Map.Entry, TypeAwareBuilder> entry : dirtyNodes + .entrySet()) { + TypeAwareBuilder typeToResolve = entry.getValue(); + + if (typeToResolve instanceof UnionTypeBuilder) { + resolveUnionTypeBuilder(modules, module, + (UnionTypeBuilder) typeToResolve); + } else { + UnknownType ut = (UnknownType) typeToResolve.getType(); + TypeDefinition resolvedType = findTargetType(ut, + modules, module); + typeToResolve.setType(resolvedType); + } } } } - private TypeDefinitionBuilder findTypeDefinitionBuilder(Map> modules, TypeAwareBuilder typeBuilder, ModuleBuilder builder) { - UnknownType type = (UnknownType) typeBuilder.getType(); - QName typeQName = type.getQName(); - String typeName = type.getQName().getLocalName(); - String prefix = typeQName.getPrefix(); + private UnionTypeBuilder resolveUnionTypeBuilder( + Map> modules, + ModuleBuilder builder, UnionTypeBuilder unionTypeBuilderToResolve) { + List> resolvedTypes = new ArrayList>(); + List> typesToRemove = new ArrayList>(); + + for (TypeDefinition td : unionTypeBuilderToResolve.getTypes()) { + if (td instanceof UnknownType) { + TypeDefinition resolvedType = findTargetType( + (UnknownType) td, modules, builder); + resolvedTypes.add(resolvedType); + typesToRemove.add(td); + } + } + + List> unionTypeBuilderTypes = unionTypeBuilderToResolve + .getTypes(); + unionTypeBuilderTypes.addAll(resolvedTypes); + unionTypeBuilderTypes.removeAll(typesToRemove); + + return unionTypeBuilderToResolve; + } + + private TypeDefinition findTargetType(UnknownType ut, + Map> modules, + ModuleBuilder builder) { + + Map foundedTypeDefinitionBuilder = findTypeDefinitionBuilderWithConstraints( + modules, ut, builder); + TypeDefinitionBuilder targetType = foundedTypeDefinitionBuilder + .entrySet().iterator().next().getKey(); + TypeConstraints constraints = foundedTypeDefinitionBuilder.entrySet() + .iterator().next().getValue(); + + TypeDefinition targetTypeBaseType = targetType.getBaseType(); + String targetTypeBaseTypeName = targetTypeBaseType.getQName() + .getLocalName(); + + // RANGE + List ranges = ut.getRangeStatements(); + resolveRanges(ranges, targetType, modules, builder); + + // LENGTH + List lengths = ut.getLengthStatements(); + resolveLengths(lengths, targetType, modules, builder); + + // PATTERN + List patterns = ut.getPatterns(); + + // Fraction Digits + Integer fractionDigits = ut.getFractionDigits(); + + // MERGE CONSTRAINTS (enumeration and leafref omitted + // because + // they have no restrictions) + if (targetTypeBaseType instanceof DecimalTypeDefinition) { + List fullRanges = new ArrayList(); + fullRanges.addAll(constraints.getRanges()); + fullRanges.addAll(ranges); + Integer fd = fractionDigits == null ? constraints + .getFractionDigits() : fractionDigits; + targetTypeBaseType = YangTypesConverter + .javaTypeForBaseYangDecimal64Type(fullRanges, fd); + } else if (targetTypeBaseType instanceof IntegerTypeDefinition) { + List fullRanges = new ArrayList(); + fullRanges.addAll(constraints.getRanges()); + fullRanges.addAll(ranges); + if (targetTypeBaseTypeName.startsWith("int")) { + targetTypeBaseType = YangTypesConverter + .javaTypeForBaseYangSignedIntegerType( + targetTypeBaseTypeName, fullRanges); + } else { + targetTypeBaseType = YangTypesConverter + .javaTypeForBaseYangUnsignedIntegerType( + targetTypeBaseTypeName, fullRanges); + } + } else if (targetTypeBaseType instanceof StringTypeDefinition) { + List fullLengths = new ArrayList(); + fullLengths.addAll(constraints.getLengths()); + fullLengths.addAll(lengths); + List fullPatterns = new ArrayList(); + fullPatterns.addAll(constraints.getPatterns()); + fullPatterns.addAll(patterns); + targetTypeBaseType = new StringType(fullLengths, fullPatterns); + } else if (targetTypeBaseType instanceof BitsTypeDefinition) { + BitsTypeDefinition bitsType = (BitsTypeDefinition) targetTypeBaseType; + List bits = bitsType.getBits(); + targetTypeBaseType = new BitsType(bits); + } else if (targetTypeBaseType instanceof BinaryTypeDefinition) { + targetTypeBaseType = new BinaryType(null, lengths, null); + } else if (targetTypeBaseTypeName.equals("instance-identifier")) { + // TODO: instance-identifier + /* + * boolean requireInstance = isRequireInstance(typeBody); type = new + * InstanceIdentifier(null, requireInstance); + */ + } + + return targetTypeBaseType; + } + + private TypeDefinitionBuilder findTypeDefinitionBuilder( + Map> modules, + UnknownType unknownType, ModuleBuilder builder) { + Map result = findTypeDefinitionBuilderWithConstraints( + modules, unknownType, builder); + return result.entrySet().iterator().next().getKey(); + } + + private Map findTypeDefinitionBuilderWithConstraints( + Map> modules, + UnknownType unknownType, ModuleBuilder builder) { + return findTypeDefinitionBuilderWithConstraints(new TypeConstraints(), + modules, unknownType, builder); + } + + /** + * Traverse through all referenced types chain until base YANG type is + * founded. + * + * @param constraints current type constraints + * @param modules all available modules + * @param unknownType unknown type + * @param builder current module + * @return map, where key is type referenced and value is its constraints + */ + private Map findTypeDefinitionBuilderWithConstraints( + TypeConstraints constraints, + Map> modules, + UnknownType unknownType, ModuleBuilder builder) { + Map result = new HashMap(); + + // TypeDefinition unknownType = typeBuilder.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())) { + if (unknownTypePrefix.equals(builder.getPrefix())) { dependentModuleBuilder = builder; } else { - ModuleImport dependentModuleImport = getDependentModuleImport(builder, prefix); + ModuleImport dependentModuleImport = getModuleImport(builder, + unknownTypePrefix); String dependentModuleName = dependentModuleImport.getModuleName(); Date dependentModuleRevision = dependentModuleImport.getRevision(); - TreeMap moduleBuildersByRevision = modules.get(dependentModuleName); - if(dependentModuleRevision == null) { - dependentModuleBuilder = moduleBuildersByRevision.lastEntry().getValue(); + TreeMap moduleBuildersByRevision = modules + .get(dependentModuleName); + if (dependentModuleRevision == null) { + dependentModuleBuilder = moduleBuildersByRevision.lastEntry() + .getValue(); } else { - dependentModuleBuilder = moduleBuildersByRevision.get(dependentModuleRevision); + dependentModuleBuilder = moduleBuildersByRevision + .get(dependentModuleRevision); } } - final Set typedefs = dependentModuleBuilder.getModuleTypedefs(); - + // 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)) { + if (qname.getLocalName().equals(unknownTypeName)) { lookedUpBuilder = tdb; break; } } - if (lookedUpBuilder.getBaseType() instanceof UnknownType) { - return findTypeDefinitionBuilder(modules, (TypeAwareBuilder) lookedUpBuilder, dependentModuleBuilder); + // if referenced type is UnknownType again, search recursively with + // current constraints + TypeDefinition referencedType = lookedUpBuilder.getBaseType(); + if (referencedType instanceof UnknownType) { + UnknownType unknown = (UnknownType) lookedUpBuilder.getBaseType(); + + final List ranges = unknown.getRangeStatements(); + constraints.addRanges(ranges); + final List lengths = unknown + .getLengthStatements(); + constraints.addLengths(lengths); + final List patterns = unknown.getPatterns(); + constraints.addPatterns(patterns); + return findTypeDefinitionBuilderWithConstraints(constraints, + modules, unknown, dependentModuleBuilder); } else { - return lookedUpBuilder; + // 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 BinaryTypeDefinition) { + constraints.addLengths(((BinaryTypeDefinition) referencedType) + .getLengthConstraints()); + } else if (referencedType instanceof InstanceIdentifierTypeDefinition) { + // TODO: instance-identifier + } + + result.put(lookedUpBuilder, constraints); + return result; } } - private void resolveAugments(Map> modules, ModuleBuilder builder) { - Set augmentBuilders = builder.getAddedAugments(); + /** + * Go through all augmentation definitions and resolve them. This means find + * 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) { @@ -164,29 +478,40 @@ public class YangModelParserImpl implements YangModelParser { prefix = pathPart.getPrefix(); augmentTargetPath.add(pathPart.getLocalName()); } - ModuleImport dependentModuleImport = getDependentModuleImport(builder, prefix); + ModuleImport dependentModuleImport = getModuleImport(module, + prefix); String dependentModuleName = dependentModuleImport.getModuleName(); augmentTargetPath.add(0, dependentModuleName); Date dependentModuleRevision = dependentModuleImport.getRevision(); - TreeMap moduleBuildersByRevision = modules.get(dependentModuleName); + TreeMap moduleBuildersByRevision = modules + .get(dependentModuleName); ModuleBuilder dependentModule; - if(dependentModuleRevision == null) { - dependentModule = moduleBuildersByRevision.lastEntry().getValue(); + if (dependentModuleRevision == null) { + dependentModule = moduleBuildersByRevision.lastEntry() + .getValue(); } else { - dependentModule = moduleBuildersByRevision.get(dependentModuleRevision); + dependentModule = moduleBuildersByRevision + .get(dependentModuleRevision); } - AugmentationTargetBuilder augmentTarget = (AugmentationTargetBuilder) dependentModule.getNode(augmentTargetPath); + AugmentationTargetBuilder augmentTarget = (AugmentationTargetBuilder) dependentModule + .getNode(augmentTargetPath); AugmentationSchema result = augmentBuilder.build(); augmentTarget.addAugmentation(result); fillAugmentTarget(augmentBuilder, (ChildNodeBuilder) augmentTarget); augments.add(result); } - builder.setAugmentations(augments); + module.setAugmentations(augments); } + /** + * Add all augment's child nodes to given target. + * + * @param augment + * @param target + */ private void fillAugmentTarget(AugmentationSchemaBuilder augment, ChildNodeBuilder target) { for (DataSchemaNodeBuilder builder : augment.getChildNodes()) { @@ -195,72 +520,131 @@ public class YangModelParserImpl implements YangModelParser { } } - private Map> loadFiles(String... yangFiles) { - final Map> modules = new HashMap>(); - - final YangModelParserListenerImpl yangModelParser = new YangModelParserListenerImpl(); - final ParseTreeWalker walker = new ParseTreeWalker(); - - List trees = parseFiles(yangFiles); - - ModuleBuilder[] builders = new ModuleBuilder[trees.size()]; - - for (int i = 0; i < trees.size(); i++) { - walker.walk(yangModelParser, trees.get(i)); - builders[i] = yangModelParser.getModuleBuilder(); - } - - for (ModuleBuilder builder : builders) { - final String builderName = builder.getName(); - Date builderRevision = builder.getRevision(); - if(builderRevision == null) { - builderRevision = createEpochTime(); - } - - TreeMap builderByRevision = modules.get(builderName); - if (builderByRevision == null) { - builderByRevision = new TreeMap(); + /** + * 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; } - builderByRevision.put(builderRevision, builder); - - modules.put(builderName, builderByRevision); } - return modules; + return moduleImport; } - private List parseFiles(String... yangFileNames) { - List trees = new ArrayList(); - for (String fileName : yangFileNames) { - trees.add(parseFile(fileName)); + /** + * Helper method for resolving special 'min' or 'max' values in range + * constraint + * + * @param ranges ranges to resolve + * @param targetType target type + * @param modules all available modules + * @param builder current module + */ + private void resolveRanges(List ranges, + TypeDefinitionBuilder targetType, + 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(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); + } + } } - return trees; } - private ParseTree parseFile(String yangFileName) { - ParseTree result = null; - try { - final File yangFile = new File(yangFileName); - final FileInputStream inStream = new FileInputStream(yangFile); - final ANTLRInputStream input = new ANTLRInputStream(inStream); - 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); + /** + * Helper method for resolving special 'min' or 'max' values in length + * constraint + * + * @param lengths lengths to resolve + * @param targetType target type + * @param modules all available modules + * @param builder current module + */ + private void resolveLengths(List lengths, + 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(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); + } + } } - return result; } - private ModuleImport getDependentModuleImport(ModuleBuilder builder, String prefix) { - ModuleImport moduleImport = null; - for (ModuleImport mi : builder.getModuleImports()) { - if (mi.getPrefix().equals(prefix)) { - moduleImport = mi; - break; - } + private Long[] parseRangeConstraint(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( + findTypeDefinitionBuilder(modules, + (UnknownType) targetBaseType, builder), modules, + builder); } - return moduleImport; } private Date createEpochTime() { @@ -318,4 +702,45 @@ 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; + } + } + } + }