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;
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;
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;
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;
@Override
public Module parseYangModel(String yangFile) {
- final Map<String, TreeMap<Date, ModuleBuilder>> modules = loadFiles(yangFile);
+ final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuildersFromStreams(yangFile);
Set<Module> result = build(modules);
return result.iterator().next();
}
@Override
public Set<Module> parseYangModels(String... yangFiles) {
- final Map<String, TreeMap<Date, ModuleBuilder>> modules = loadFiles(yangFiles);
+ final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuildersFromStreams(yangFiles);
+ Set<Module> result = build(modules);
+ return result;
+ }
+
+ @Override
+ public Set<Module> parseYangModelsFromStreams(
+ InputStream... yangModelStreams) {
+ final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuildersFromStreams(yangModelStreams);
Set<Module> result = build(modules);
return result;
}
return new SchemaContextImpl(modules);
}
+ private Map<String, TreeMap<Date, ModuleBuilder>> 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<String, TreeMap<Date, ModuleBuilder>> resolveModuleBuildersFromStreams(
+ InputStream... yangFiles) {
+ final Map<String, TreeMap<Date, ModuleBuilder>> modules = new HashMap<String, TreeMap<Date, ModuleBuilder>>();
+
+ final YangModelParserListenerImpl yangModelParser = new YangModelParserListenerImpl();
+ final ParseTreeWalker walker = new ParseTreeWalker();
+
+ List<ParseTree> 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<Date, ModuleBuilder> builderByRevision = modules
+ .get(builderName);
+ if (builderByRevision == null) {
+ builderByRevision = new TreeMap<Date, ModuleBuilder>();
+ }
+ builderByRevision.put(builderRevision, builder);
+
+ modules.put(builderName, builderByRevision);
+ }
+ return modules;
+ }
+
+ private List<ParseTree> parseStreams(InputStream... yangStreams) {
+ List<ParseTree> trees = new ArrayList<ParseTree>();
+ 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<Module> build(Map<String, TreeMap<Date, ModuleBuilder>> modules) {
// first validate
- for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
- for (Map.Entry<Date, ModuleBuilder> childEntry : entry.getValue().entrySet()) {
+ for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules
+ .entrySet()) {
+ for (Map.Entry<Date, ModuleBuilder> childEntry : entry.getValue()
+ .entrySet()) {
ModuleBuilder moduleBuilder = childEntry.getValue();
validateBuilder(modules, moduleBuilder);
}
}
-
// then build
final Set<Module> result = new HashSet<Module>();
- for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
+ for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules
+ .entrySet()) {
final Map<Date, Module> modulesByRevision = new HashMap<Date, Module>();
- for (Map.Entry<Date, ModuleBuilder> childEntry : entry.getValue().entrySet()) {
+ for (Map.Entry<Date, ModuleBuilder> childEntry : entry.getValue()
+ .entrySet()) {
ModuleBuilder moduleBuilder = childEntry.getValue();
- modulesByRevision.put(childEntry.getKey(),moduleBuilder.build());
+ modulesByRevision.put(childEntry.getKey(),
+ moduleBuilder.build());
result.add(moduleBuilder.build());
}
}
return result;
}
- private void validateBuilder(Map<String, TreeMap<Date, ModuleBuilder>> modules, ModuleBuilder builder) {
+ private void validateBuilder(
+ Map<String, TreeMap<Date, ModuleBuilder>> modules,
+ ModuleBuilder builder) {
resolveTypedefs(modules, builder);
resolveAugments(modules, builder);
}
- private void resolveTypedefs(Map<String, TreeMap<Date, ModuleBuilder>> modules, ModuleBuilder builder) {
- Map<List<String>, 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<String, TreeMap<Date, ModuleBuilder>> modules,
+ ModuleBuilder module) {
+ Map<List<String>, TypeAwareBuilder> dirtyNodes = module
+ .getDirtyNodes();
if (dirtyNodes.size() == 0) {
return;
} else {
- for (Map.Entry<List<String>, TypeAwareBuilder> entry : dirtyNodes.entrySet()) {
- TypeAwareBuilder tab = entry.getValue();
- TypeDefinitionBuilder tdb = findTypeDefinitionBuilder(modules,entry.getValue(), builder);
- tab.setType(tdb.build());
+ for (Map.Entry<List<String>, 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<String, TreeMap<Date, ModuleBuilder>> 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<String, TreeMap<Date, ModuleBuilder>> modules,
+ ModuleBuilder builder, UnionTypeBuilder unionTypeBuilderToResolve) {
+ List<TypeDefinition<?>> resolvedTypes = new ArrayList<TypeDefinition<?>>();
+ List<TypeDefinition<?>> typesToRemove = new ArrayList<TypeDefinition<?>>();
+
+ for (TypeDefinition<?> td : unionTypeBuilderToResolve.getTypes()) {
+ if (td instanceof UnknownType) {
+ TypeDefinition<?> resolvedType = findTargetType(
+ (UnknownType) td, modules, builder);
+ resolvedTypes.add(resolvedType);
+ typesToRemove.add(td);
+ }
+ }
+
+ List<TypeDefinition<?>> unionTypeBuilderTypes = unionTypeBuilderToResolve
+ .getTypes();
+ unionTypeBuilderTypes.addAll(resolvedTypes);
+ unionTypeBuilderTypes.removeAll(typesToRemove);
+
+ return unionTypeBuilderToResolve;
+ }
+
+ private TypeDefinition<?> findTargetType(UnknownType ut,
+ Map<String, TreeMap<Date, ModuleBuilder>> modules,
+ ModuleBuilder builder) {
+
+ Map<TypeDefinitionBuilder, TypeConstraints> 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<RangeConstraint> ranges = ut.getRangeStatements();
+ resolveRanges(ranges, targetType, modules, builder);
+
+ // LENGTH
+ List<LengthConstraint> lengths = ut.getLengthStatements();
+ resolveLengths(lengths, targetType, modules, builder);
+
+ // PATTERN
+ List<PatternConstraint> 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<RangeConstraint> fullRanges = new ArrayList<RangeConstraint>();
+ 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<RangeConstraint> fullRanges = new ArrayList<RangeConstraint>();
+ 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<LengthConstraint> fullLengths = new ArrayList<LengthConstraint>();
+ fullLengths.addAll(constraints.getLengths());
+ fullLengths.addAll(lengths);
+ List<PatternConstraint> fullPatterns = new ArrayList<PatternConstraint>();
+ fullPatterns.addAll(constraints.getPatterns());
+ fullPatterns.addAll(patterns);
+ targetTypeBaseType = new StringType(fullLengths, fullPatterns);
+ } else if (targetTypeBaseType instanceof BitsTypeDefinition) {
+ BitsTypeDefinition bitsType = (BitsTypeDefinition) targetTypeBaseType;
+ List<Bit> 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<String, TreeMap<Date, ModuleBuilder>> modules,
+ UnknownType unknownType, ModuleBuilder builder) {
+ Map<TypeDefinitionBuilder, TypeConstraints> result = findTypeDefinitionBuilderWithConstraints(
+ modules, unknownType, builder);
+ return result.entrySet().iterator().next().getKey();
+ }
+
+ private Map<TypeDefinitionBuilder, TypeConstraints> findTypeDefinitionBuilderWithConstraints(
+ Map<String, TreeMap<Date, ModuleBuilder>> 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<TypeDefinitionBuilder, TypeConstraints> findTypeDefinitionBuilderWithConstraints(
+ TypeConstraints constraints,
+ Map<String, TreeMap<Date, ModuleBuilder>> modules,
+ UnknownType unknownType, ModuleBuilder builder) {
+ Map<TypeDefinitionBuilder, TypeConstraints> result = new HashMap<TypeDefinitionBuilder, TypeConstraints>();
+
+ // 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<Date, ModuleBuilder> moduleBuildersByRevision = modules.get(dependentModuleName);
- if(dependentModuleRevision == null) {
- dependentModuleBuilder = moduleBuildersByRevision.lastEntry().getValue();
+ TreeMap<Date, ModuleBuilder> moduleBuildersByRevision = modules
+ .get(dependentModuleName);
+ if (dependentModuleRevision == null) {
+ dependentModuleBuilder = moduleBuildersByRevision.lastEntry()
+ .getValue();
} else {
- dependentModuleBuilder = moduleBuildersByRevision.get(dependentModuleRevision);
+ dependentModuleBuilder = moduleBuildersByRevision
+ .get(dependentModuleRevision);
}
}
- final Set<TypeDefinitionBuilder> typedefs = dependentModuleBuilder.getModuleTypedefs();
-
+ // pull all typedef statements from dependent module...
+ final Set<TypeDefinitionBuilder> 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<RangeConstraint> ranges = unknown.getRangeStatements();
+ constraints.addRanges(ranges);
+ final List<LengthConstraint> lengths = unknown
+ .getLengthStatements();
+ constraints.addLengths(lengths);
+ final List<PatternConstraint> 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<String, TreeMap<Date, ModuleBuilder>> modules, ModuleBuilder builder) {
- Set<AugmentationSchemaBuilder> 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<String, TreeMap<Date, ModuleBuilder>> modules,
+ ModuleBuilder module) {
+ Set<AugmentationSchemaBuilder> augmentBuilders = module
+ .getAddedAugments();
Set<AugmentationSchema> augments = new HashSet<AugmentationSchema>();
for (AugmentationSchemaBuilder augmentBuilder : augmentBuilders) {
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<Date, ModuleBuilder> moduleBuildersByRevision = modules.get(dependentModuleName);
+ TreeMap<Date, ModuleBuilder> 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()) {
}
}
- private Map<String, TreeMap<Date, ModuleBuilder>> loadFiles(String... yangFiles) {
- final Map<String, TreeMap<Date, ModuleBuilder>> modules = new HashMap<String, TreeMap<Date, ModuleBuilder>>();
-
- final YangModelParserListenerImpl yangModelParser = new YangModelParserListenerImpl();
- final ParseTreeWalker walker = new ParseTreeWalker();
-
- List<ParseTree> 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<Date, ModuleBuilder> builderByRevision = modules.get(builderName);
- if (builderByRevision == null) {
- builderByRevision = new TreeMap<Date, ModuleBuilder>();
+ /**
+ * 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<ParseTree> parseFiles(String... yangFileNames) {
- List<ParseTree> trees = new ArrayList<ParseTree>();
- 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<RangeConstraint> ranges,
+ TypeDefinitionBuilder targetType,
+ Map<String, TreeMap<Date, ModuleBuilder>> 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<LengthConstraint> lengths,
+ TypeDefinitionBuilder targetType,
+ Map<String, TreeMap<Date, ModuleBuilder>> 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<String, TreeMap<Date, ModuleBuilder>> modules,
+ ModuleBuilder builder) {
+ TypeDefinition<?> targetBaseType = targetType.getBaseType();
+
+ if (targetBaseType instanceof IntegerTypeDefinition) {
+ IntegerTypeDefinition itd = (IntegerTypeDefinition) targetBaseType;
+ List<RangeConstraint> 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<RangeConstraint> 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() {
}
}
+ private static class TypeConstraints {
+ private final List<RangeConstraint> ranges = new ArrayList<RangeConstraint>();
+ private final List<LengthConstraint> lengths = new ArrayList<LengthConstraint>();
+ private final List<PatternConstraint> patterns = new ArrayList<PatternConstraint>();
+ private Integer fractionDigits;
+
+ public List<RangeConstraint> getRanges() {
+ return ranges;
+ }
+
+ public void addRanges(List<RangeConstraint> ranges) {
+ this.ranges.addAll(0, ranges);
+ }
+
+ public List<LengthConstraint> getLengths() {
+ return lengths;
+ }
+
+ public void addLengths(List<LengthConstraint> lengths) {
+ this.lengths.addAll(0, lengths);
+ }
+
+ public List<PatternConstraint> getPatterns() {
+ return patterns;
+ }
+
+ public void addPatterns(List<PatternConstraint> patterns) {
+ this.patterns.addAll(0, patterns);
+ }
+
+ public Integer getFractionDigits() {
+ return fractionDigits;
+ }
+
+ public void setFractionDigits(Integer fractionDigits) {
+ if (fractionDigits != null) {
+ this.fractionDigits = fractionDigits;
+ }
+ }
+ }
+
}