Update the API generation code and code generation sample
[controller.git] / opendaylight / sal / yang-prototype / code-generator / yang-model-parser-impl / src / main / java / org / opendaylight / controller / yang / model / parser / impl / YangModelParserImpl.java
index 81a5c9701f365a9df1f6964615623e18557a077f..5cc9f8e4aa065ca7a189ba2c31408c3894957267 100644 (file)
-/*
- * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-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.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-
-import org.antlr.v4.runtime.ANTLRInputStream;
-import org.antlr.v4.runtime.CommonTokenStream;
-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.yang.common.QName;
-import org.opendaylight.controller.yang.model.api.AugmentationSchema;
-import org.opendaylight.controller.yang.model.api.DataSchemaNode;
-import org.opendaylight.controller.yang.model.api.ExtensionDefinition;
-import org.opendaylight.controller.yang.model.api.Module;
-import org.opendaylight.controller.yang.model.api.ModuleImport;
-import org.opendaylight.controller.yang.model.api.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.BitsTypeDefinition.Bit;
-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;
-import org.opendaylight.controller.yang.model.parser.builder.api.ChildNodeBuilder;
-import org.opendaylight.controller.yang.model.parser.builder.api.DataSchemaNodeBuilder;
-import org.opendaylight.controller.yang.model.parser.builder.api.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.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.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;
-
-public class YangModelParserImpl implements YangModelParser {
-
-    private static final Logger logger = LoggerFactory
-            .getLogger(YangModelParserImpl.class);
-
-    @Override
-    public Module parseYangModel(String 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 = 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;
-    }
-
-    @Override
-    public SchemaContext resolveSchemaContext(Set<Module> modules) {
-        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 ParseTreeWalker walker = new ParseTreeWalker();
-        final List<ParseTree> trees = parseStreams(yangFiles);
-        final ModuleBuilder[] builders = new ModuleBuilder[trees.size()];
-
-        for (int i = 0; i < trees.size(); i++) {
-            final YangModelParserListenerImpl yangModelParser = new YangModelParserListenerImpl();
-            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) {
-        // validate
-        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);
-            }
-        }
-        // build
-        final Set<Module> result = new HashSet<Module>();
-        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()) {
-                ModuleBuilder moduleBuilder = childEntry.getValue();
-                modulesByRevision.put(childEntry.getKey(),
-                        moduleBuilder.build());
-                result.add(moduleBuilder.build());
-            }
-        }
-
-        return result;
-    }
-
-    private void validateBuilder(
-            Map<String, TreeMap<Date, ModuleBuilder>> modules,
-            ModuleBuilder builder) {
-        resolveTypedefs(modules, builder);
-        resolveAugments(modules, builder);
-        resolveIdentities(modules, builder);
-    }
-
-    /**
-     * 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 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 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) {
-
-        TypeConstraints constraints = new TypeConstraints();
-        // RANGE
-        List<RangeConstraint> ranges = ut.getRangeStatements();
-        constraints.addRanges(ranges);
-        // LENGTH
-        List<LengthConstraint> lengths = ut.getLengthStatements();
-        constraints.addLengths(lengths);
-        // PATTERN
-        List<PatternConstraint> patterns = ut.getPatterns();
-        constraints.addPatterns(patterns);
-        // Fraction Digits
-        Integer fractionDigits = ut.getFractionDigits();
-
-        Map<TypeDefinitionBuilder, TypeConstraints> foundedTypeDefinitionBuilder = findTypeDefinitionBuilderWithConstraints(
-                constraints, modules, ut, builder);
-        TypeDefinitionBuilder targetType = foundedTypeDefinitionBuilder
-                .entrySet().iterator().next().getKey();
-
-        TypeDefinition<?> targetTypeBaseType = targetType.getBaseType();
-        targetTypeBaseType = mergeConstraints(targetTypeBaseType, constraints,
-                fractionDigits);
-
-        return targetTypeBaseType;
-    }
-
-    /**
-     * 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>();
-        QName unknownTypeQName = unknownType.getQName();
-        String unknownTypeName = unknownTypeQName.getLocalName();
-        String unknownTypePrefix = unknownTypeQName.getPrefix();
-
-        // search for module which contains referenced typedef
-        ModuleBuilder dependentModuleBuilder = findDependentModule(modules,
-                builder, unknownTypePrefix);
-
-        TypeDefinitionBuilder lookedUpBuilder = findTypedefBuilder(
-                dependentModuleBuilder.getModuleTypedefs(), unknownTypeName);
-
-        // if referenced type is UnknownType again, search recursively with
-        // current constraints
-        TypeDefinition<?> referencedType = lookedUpBuilder.getBaseType();
-        if (referencedType instanceof UnknownType) {
-            UnknownType unknown = (UnknownType) referencedType;
-
-            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 {
-            mergeConstraints(referencedType, constraints);
-            result.put(lookedUpBuilder, constraints);
-            return result;
-        }
-    }
-
-    /**
-     * 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<TypeDefinitionBuilder> 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;
-    }
-
-    /**
-     * Merge curent constraints with founded type constraints
-     *
-     * @param targetTypeBaseType
-     * @param constraints
-     * @param fractionDigits
-     * @return
-     */
-    private TypeDefinition<?> mergeConstraints(
-            TypeDefinition<?> targetTypeBaseType, TypeConstraints constraints,
-            Integer fractionDigits) {
-        String targetTypeBaseTypeName = targetTypeBaseType.getQName()
-                .getLocalName();
-        // enumeration, leafref and identityref omitted because they have no
-        // restrictions
-        if (targetTypeBaseType instanceof DecimalTypeDefinition) {
-            List<RangeConstraint> ranges = constraints.getRange();
-            Integer fd = fractionDigits == null ? constraints
-                    .getFractionDigits() : fractionDigits;
-            targetTypeBaseType = YangTypesConverter
-                    .javaTypeForBaseYangDecimal64Type(ranges, fd);
-        } else if (targetTypeBaseType instanceof IntegerTypeDefinition) {
-            List<RangeConstraint> ranges = constraints.getRange();
-            if (targetTypeBaseTypeName.startsWith("int")) {
-                targetTypeBaseType = YangTypesConverter
-                        .javaTypeForBaseYangSignedIntegerType(
-                                targetTypeBaseTypeName, ranges);
-            } else {
-                targetTypeBaseType = YangTypesConverter
-                        .javaTypeForBaseYangUnsignedIntegerType(
-                                targetTypeBaseTypeName, ranges);
-            }
-        } else if (targetTypeBaseType instanceof StringTypeDefinition) {
-            List<LengthConstraint> lengths = constraints.getLength();
-            List<PatternConstraint> patterns = constraints.getPatterns();
-            targetTypeBaseType = new StringType(lengths, patterns);
-        } else if (targetTypeBaseType instanceof BitsTypeDefinition) {
-            BitsTypeDefinition bitsType = (BitsTypeDefinition) targetTypeBaseType;
-            List<Bit> bits = bitsType.getBits();
-            targetTypeBaseType = new BitsType(bits);
-        } else if (targetTypeBaseType instanceof BinaryTypeDefinition) {
-            List<LengthConstraint> lengths = constraints.getLength();
-            List<Byte> bytes = Collections.emptyList();
-            targetTypeBaseType = new BinaryType(bytes, lengths, null);
-        }
-        return targetTypeBaseType;
-    }
-
-    /**
-     * Pull restriction from base 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());
-        }
-    }
-
-    /**
-     * 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) {
-            SchemaPath augmentTargetSchemaPath = augmentBuilder.getTargetPath();
-            String prefix = null;
-            List<String> augmentTargetPath = new ArrayList<String>();
-
-            for (QName pathPart : augmentTargetSchemaPath.getPath()) {
-                prefix = pathPart.getPrefix();
-                augmentTargetPath.add(pathPart.getLocalName());
-            }
-            ModuleBuilder dependentModule = findDependentModule(modules,
-                    module, prefix);
-            augmentTargetPath.add(0, dependentModule.getName());
-
-            AugmentationTargetBuilder augmentTarget = (AugmentationTargetBuilder) dependentModule
-                    .getNode(augmentTargetPath);
-            AugmentationSchema result = augmentBuilder.build();
-            augmentTarget.addAugmentation(result);
-            fillAugmentTarget(augmentBuilder, (ChildNodeBuilder) augmentTarget);
-            augments.add(result);
-        }
-        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()) {
-            builder.setAugmenting(true);
-            target.addChildNode(builder);
-        }
-    }
-
-    /**
-     * Go through identity statements defined in current module and resolve
-     * their 'base' statement if present.
-     *
-     * @param modules
-     *            all modules
-     * @param module
-     *            module being resolved
-     */
-    private void resolveIdentities(
-            Map<String, TreeMap<Date, ModuleBuilder>> modules,
-            ModuleBuilder module) {
-        Set<IdentitySchemaNodeBuilder> 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<IdentitySchemaNodeBuilder> dependentModuleIdentities = dependentModule
-                        .getAddedIdentities();
-                for (IdentitySchemaNodeBuilder idBuilder : dependentModuleIdentities) {
-                    if (idBuilder.getQName().getLocalName()
-                            .equals(baseIdentityLocalName)) {
-                        identity.setBaseIdentity(idBuilder);
-                    }
-                }
-            }
-        }
-    }
-
-    /**
-     * Find dependent module based on given prefix
-     *
-     * @param modules
-     *            all available modules
-     * @param module
-     *            current module
-     * @param prefix
-     *            target module prefix
-     * @return
-     */
-    private ModuleBuilder findDependentModule(
-            Map<String, TreeMap<Date, ModuleBuilder>> modules,
-            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<Date, ModuleBuilder> 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;
-    }
-
-    /**
-     * Get module import referenced by given prefix.
-     *
-     * @param builder
-     *            module to search
-     * @param prefix
-     *            prefix associated with import
-     * @return ModuleImport based on given prefix
-     */
-    private ModuleImport getModuleImport(ModuleBuilder builder, String prefix) {
-        ModuleImport moduleImport = null;
-        for (ModuleImport mi : builder.getModuleImports()) {
-            if (mi.getPrefix().equals(prefix)) {
-                moduleImport = mi;
-                break;
-            }
-        }
-        return moduleImport;
-    }
-
-    private Date createEpochTime() {
-        Calendar c = Calendar.getInstance();
-        c.setTimeInMillis(0);
-        return c.getTime();
-    }
-
-    private static class SchemaContextImpl implements SchemaContext {
-        private final Set<Module> modules;
-
-        private SchemaContextImpl(Set<Module> modules) {
-            this.modules = modules;
-        }
-
-        @Override
-        public Set<DataSchemaNode> getDataDefinitions() {
-            final Set<DataSchemaNode> dataDefs = new HashSet<DataSchemaNode>();
-            for (Module m : modules) {
-                dataDefs.addAll(m.getChildNodes());
-            }
-            return dataDefs;
-        }
-
-        @Override
-        public Set<Module> getModules() {
-            return modules;
-        }
-
-        @Override
-        public Set<NotificationDefinition> getNotifications() {
-            final Set<NotificationDefinition> notifications = new HashSet<NotificationDefinition>();
-            for (Module m : modules) {
-                notifications.addAll(m.getNotifications());
-            }
-            return notifications;
-        }
-
-        @Override
-        public Set<RpcDefinition> getOperations() {
-            final Set<RpcDefinition> rpcs = new HashSet<RpcDefinition>();
-            for (Module m : modules) {
-                rpcs.addAll(m.getRpcs());
-            }
-            return rpcs;
-        }
-
-        @Override
-        public Set<ExtensionDefinition> getExtensions() {
-            final Set<ExtensionDefinition> extensions = new HashSet<ExtensionDefinition>();
-            for (Module m : modules) {
-                extensions.addAll(m.getExtensionSchemaNodes());
-            }
-            return extensions;
-        }
-    }
-
-}
+/*\r
+ * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.\r
+ *\r
+ * This program and the accompanying materials are made available under the\r
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,\r
+ * and is available at http://www.eclipse.org/legal/epl-v10.html\r
+ */\r
+package org.opendaylight.controller.yang.model.parser.impl;\r
+\r
+import java.io.File;\r
+import java.io.FileInputStream;\r
+import java.io.FileNotFoundException;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.util.ArrayList;\r
+import java.util.Calendar;\r
+import java.util.Date;\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+import java.util.List;\r
+import java.util.Map;\r
+import java.util.Set;\r
+import java.util.TreeMap;\r
+\r
+import org.antlr.v4.runtime.ANTLRInputStream;\r
+import org.antlr.v4.runtime.CommonTokenStream;\r
+import org.antlr.v4.runtime.tree.ParseTree;\r
+import org.antlr.v4.runtime.tree.ParseTreeWalker;\r
+import org.opendaylight.controller.antlrv4.code.gen.YangLexer;\r
+import org.opendaylight.controller.antlrv4.code.gen.YangParser;\r
+import org.opendaylight.controller.yang.common.QName;\r
+import org.opendaylight.controller.yang.model.api.AugmentationSchema;\r
+import org.opendaylight.controller.yang.model.api.DataSchemaNode;\r
+import org.opendaylight.controller.yang.model.api.ExtensionDefinition;\r
+import org.opendaylight.controller.yang.model.api.Module;\r
+import org.opendaylight.controller.yang.model.api.ModuleImport;\r
+import org.opendaylight.controller.yang.model.api.NotificationDefinition;\r
+import org.opendaylight.controller.yang.model.api.RpcDefinition;\r
+import org.opendaylight.controller.yang.model.api.SchemaContext;\r
+import org.opendaylight.controller.yang.model.api.SchemaPath;\r
+import org.opendaylight.controller.yang.model.api.TypeDefinition;\r
+import org.opendaylight.controller.yang.model.api.type.BinaryTypeDefinition;\r
+import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition;\r
+import org.opendaylight.controller.yang.model.api.type.BitsTypeDefinition.Bit;\r
+import org.opendaylight.controller.yang.model.api.type.DecimalTypeDefinition;\r
+import org.opendaylight.controller.yang.model.api.type.IntegerTypeDefinition;\r
+import org.opendaylight.controller.yang.model.api.type.LengthConstraint;\r
+import org.opendaylight.controller.yang.model.api.type.PatternConstraint;\r
+import org.opendaylight.controller.yang.model.api.type.RangeConstraint;\r
+import org.opendaylight.controller.yang.model.api.type.StringTypeDefinition;\r
+import org.opendaylight.controller.yang.model.parser.api.YangModelParser;\r
+import org.opendaylight.controller.yang.model.parser.builder.api.AugmentationSchemaBuilder;\r
+import org.opendaylight.controller.yang.model.parser.builder.api.AugmentationTargetBuilder;\r
+import org.opendaylight.controller.yang.model.parser.builder.api.ChildNodeBuilder;\r
+import org.opendaylight.controller.yang.model.parser.builder.api.DataSchemaNodeBuilder;\r
+import org.opendaylight.controller.yang.model.parser.builder.api.TypeAwareBuilder;\r
+import org.opendaylight.controller.yang.model.parser.builder.api.TypeDefinitionBuilder;\r
+import org.opendaylight.controller.yang.model.parser.builder.impl.IdentitySchemaNodeBuilder;\r
+import org.opendaylight.controller.yang.model.parser.builder.impl.ModuleBuilder;\r
+import org.opendaylight.controller.yang.model.parser.builder.impl.UnionTypeBuilder;\r
+import org.opendaylight.controller.yang.model.util.BaseConstraints;\r
+import org.opendaylight.controller.yang.model.util.BinaryType;\r
+import org.opendaylight.controller.yang.model.util.BitsType;\r
+import org.opendaylight.controller.yang.model.util.StringType;\r
+import org.opendaylight.controller.yang.model.util.UnknownType;\r
+import org.opendaylight.controller.yang.model.util.YangTypesConverter;\r
+import org.slf4j.Logger;\r
+import org.slf4j.LoggerFactory;\r
+\r
+public class YangModelParserImpl implements YangModelParser {\r
+\r
+    private static final Logger logger = LoggerFactory\r
+            .getLogger(YangModelParserImpl.class);\r
+\r
+    @Override\r
+    public Module parseYangModel(String yangFile) {\r
+        final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuildersFromStreams(yangFile);\r
+        Set<Module> result = build(modules);\r
+        return result.iterator().next();\r
+    }\r
+\r
+    @Override\r
+    public Set<Module> parseYangModels(String... yangFiles) {\r
+        final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuildersFromStreams(yangFiles);\r
+        Set<Module> result = build(modules);\r
+        return result;\r
+    }\r
+\r
+    @Override\r
+    public Set<Module> parseYangModelsFromStreams(\r
+            InputStream... yangModelStreams) {\r
+        final Map<String, TreeMap<Date, ModuleBuilder>> modules = resolveModuleBuildersFromStreams(yangModelStreams);\r
+        Set<Module> result = build(modules);\r
+        return result;\r
+    }\r
+\r
+    @Override\r
+    public SchemaContext resolveSchemaContext(Set<Module> modules) {\r
+        return new SchemaContextImpl(modules);\r
+    }\r
+\r
+    private Map<String, TreeMap<Date, ModuleBuilder>> resolveModuleBuildersFromStreams(\r
+            String... yangFiles) {\r
+        InputStream[] streams = new InputStream[yangFiles.length];\r
+        for (int i = 0; i < yangFiles.length; i++) {\r
+            final String yangFileName = yangFiles[i];\r
+            final File yangFile = new File(yangFileName);\r
+            FileInputStream inStream = null;\r
+            try {\r
+                inStream = new FileInputStream(yangFile);\r
+            } catch (FileNotFoundException e) {\r
+                logger.warn("Exception while reading yang stream: " + inStream,\r
+                        e);\r
+            }\r
+            streams[i] = inStream;\r
+        }\r
+        return resolveModuleBuildersFromStreams(streams);\r
+    }\r
+\r
+    private Map<String, TreeMap<Date, ModuleBuilder>> resolveModuleBuildersFromStreams(\r
+            InputStream... yangFiles) {\r
+        final Map<String, TreeMap<Date, ModuleBuilder>> modules = new HashMap<String, TreeMap<Date, ModuleBuilder>>();\r
+        final ParseTreeWalker walker = new ParseTreeWalker();\r
+        final List<ParseTree> trees = parseStreams(yangFiles);\r
+        final ModuleBuilder[] builders = new ModuleBuilder[trees.size()];\r
+\r
+        for (int i = 0; i < trees.size(); i++) {\r
+            final YangModelParserListenerImpl yangModelParser = new YangModelParserListenerImpl();\r
+            walker.walk(yangModelParser, trees.get(i));\r
+            builders[i] = yangModelParser.getModuleBuilder();\r
+        }\r
+\r
+        for (ModuleBuilder builder : builders) {\r
+            final String builderName = builder.getName();\r
+            Date builderRevision = builder.getRevision();\r
+            if (builderRevision == null) {\r
+                builderRevision = createEpochTime();\r
+            }\r
+            TreeMap<Date, ModuleBuilder> builderByRevision = modules\r
+                    .get(builderName);\r
+            if (builderByRevision == null) {\r
+                builderByRevision = new TreeMap<Date, ModuleBuilder>();\r
+            }\r
+            builderByRevision.put(builderRevision, builder);\r
+            modules.put(builderName, builderByRevision);\r
+        }\r
+        return modules;\r
+    }\r
+\r
+    private List<ParseTree> parseStreams(InputStream... yangStreams) {\r
+        List<ParseTree> trees = new ArrayList<ParseTree>();\r
+        for (InputStream yangStream : yangStreams) {\r
+            trees.add(parseStream(yangStream));\r
+        }\r
+        return trees;\r
+    }\r
+\r
+    private ParseTree parseStream(InputStream yangStream) {\r
+        ParseTree result = null;\r
+        try {\r
+            final ANTLRInputStream input = new ANTLRInputStream(yangStream);\r
+            final YangLexer lexer = new YangLexer(input);\r
+            final CommonTokenStream tokens = new CommonTokenStream(lexer);\r
+            final YangParser parser = new YangParser(tokens);\r
+            result = parser.yang();\r
+        } catch (IOException e) {\r
+            logger.warn("Exception while reading yang file: " + yangStream, e);\r
+        }\r
+        return result;\r
+    }\r
+\r
+    private Set<Module> build(Map<String, TreeMap<Date, ModuleBuilder>> modules) {\r
+        // first validate\r
+        for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules\r
+                .entrySet()) {\r
+            for (Map.Entry<Date, ModuleBuilder> childEntry : entry.getValue()\r
+                    .entrySet()) {\r
+                ModuleBuilder moduleBuilder = childEntry.getValue();\r
+                validateBuilder(modules, moduleBuilder);\r
+            }\r
+        }\r
+        // then build\r
+        final Set<Module> result = new HashSet<Module>();\r
+        for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules\r
+                .entrySet()) {\r
+            final Map<Date, Module> modulesByRevision = new HashMap<Date, Module>();\r
+            for (Map.Entry<Date, ModuleBuilder> childEntry : entry.getValue()\r
+                    .entrySet()) {\r
+                ModuleBuilder moduleBuilder = childEntry.getValue();\r
+                modulesByRevision.put(childEntry.getKey(),\r
+                        moduleBuilder.build());\r
+                result.add(moduleBuilder.build());\r
+            }\r
+        }\r
+\r
+        return result;\r
+    }\r
+\r
+    private void validateBuilder(\r
+            Map<String, TreeMap<Date, ModuleBuilder>> modules,\r
+            ModuleBuilder builder) {\r
+        resolveTypedefs(modules, builder);\r
+        resolveAugments(modules, builder);\r
+        resolveIdentities(modules, builder);\r
+    }\r
+\r
+    /**\r
+     * Search for dirty nodes (node which contains UnknownType) and resolve\r
+     * unknown types.\r
+     *\r
+     * @param modules\r
+     *            all available modules\r
+     * @param module\r
+     *            current module\r
+     */\r
+    private void resolveTypedefs(\r
+            Map<String, TreeMap<Date, ModuleBuilder>> modules,\r
+            ModuleBuilder module) {\r
+        Map<List<String>, TypeAwareBuilder> dirtyNodes = module.getDirtyNodes();\r
+        if (dirtyNodes.size() == 0) {\r
+            return;\r
+        } else {\r
+            for (Map.Entry<List<String>, TypeAwareBuilder> entry : dirtyNodes\r
+                    .entrySet()) {\r
+                TypeAwareBuilder typeToResolve = entry.getValue();\r
+\r
+                if (typeToResolve instanceof UnionTypeBuilder) {\r
+                    resolveUnionTypeBuilder(modules, module,\r
+                            (UnionTypeBuilder) typeToResolve);\r
+                } else {\r
+                    UnknownType ut = (UnknownType) typeToResolve.getType();\r
+                    TypeDefinition<?> resolvedType = findTargetType(ut,\r
+                            modules, module);\r
+                    typeToResolve.setType(resolvedType);\r
+                }\r
+            }\r
+        }\r
+    }\r
+\r
+    private UnionTypeBuilder resolveUnionTypeBuilder(\r
+            Map<String, TreeMap<Date, ModuleBuilder>> modules,\r
+            ModuleBuilder builder, UnionTypeBuilder unionTypeBuilderToResolve) {\r
+        List<TypeDefinition<?>> resolvedTypes = new ArrayList<TypeDefinition<?>>();\r
+        List<TypeDefinition<?>> typesToRemove = new ArrayList<TypeDefinition<?>>();\r
+\r
+        for (TypeDefinition<?> td : unionTypeBuilderToResolve.getTypes()) {\r
+            if (td instanceof UnknownType) {\r
+                TypeDefinition<?> resolvedType = findTargetType(\r
+                        (UnknownType) td, modules, builder);\r
+                resolvedTypes.add(resolvedType);\r
+                typesToRemove.add(td);\r
+            }\r
+        }\r
+\r
+        List<TypeDefinition<?>> unionTypeBuilderTypes = unionTypeBuilderToResolve\r
+                .getTypes();\r
+        unionTypeBuilderTypes.addAll(resolvedTypes);\r
+        unionTypeBuilderTypes.removeAll(typesToRemove);\r
+\r
+        return unionTypeBuilderToResolve;\r
+    }\r
+\r
+    private TypeDefinition<?> findTargetType(UnknownType ut,\r
+            Map<String, TreeMap<Date, ModuleBuilder>> modules,\r
+            ModuleBuilder builder) {\r
+\r
+        Map<TypeDefinitionBuilder, TypeConstraints> foundedTypeDefinitionBuilder = findTypeDefinitionBuilderWithConstraints(\r
+                modules, ut, builder);\r
+        TypeDefinitionBuilder targetType = foundedTypeDefinitionBuilder\r
+                .entrySet().iterator().next().getKey();\r
+        TypeConstraints constraints = foundedTypeDefinitionBuilder.entrySet()\r
+                .iterator().next().getValue();\r
+\r
+        TypeDefinition<?> targetTypeBaseType = targetType.getBaseType();\r
+\r
+        // RANGE\r
+        List<RangeConstraint> ranges = ut.getRangeStatements();\r
+        resolveRanges(ranges, targetType, modules, builder);\r
+        // LENGTH\r
+        List<LengthConstraint> lengths = ut.getLengthStatements();\r
+        resolveLengths(lengths, targetType, modules, builder);\r
+        // PATTERN\r
+        List<PatternConstraint> patterns = ut.getPatterns();\r
+        // Fraction Digits\r
+        Integer fractionDigits = ut.getFractionDigits();\r
+\r
+        targetTypeBaseType = mergeConstraints(targetTypeBaseType, constraints, ranges, lengths,\r
+                patterns, fractionDigits);\r
+\r
+        return targetTypeBaseType;\r
+    }\r
+\r
+    /**\r
+     * Merge curent constraints with founded type constraints\r
+     *\r
+     * @param targetTypeBaseType\r
+     * @param constraints\r
+     * @param ranges\r
+     * @param lengths\r
+     * @param patterns\r
+     * @param fractionDigits\r
+     */\r
+    private TypeDefinition<?> mergeConstraints(TypeDefinition<?> targetTypeBaseType,\r
+            TypeConstraints constraints, List<RangeConstraint> ranges,\r
+            List<LengthConstraint> lengths, List<PatternConstraint> patterns,\r
+            Integer fractionDigits) {\r
+        String targetTypeBaseTypeName = targetTypeBaseType.getQName()\r
+                .getLocalName();\r
+        // enumeration, leafref and identityref omitted because they have no\r
+        // restrictions\r
+        if (targetTypeBaseType instanceof DecimalTypeDefinition) {\r
+            List<RangeConstraint> fullRanges = new ArrayList<RangeConstraint>();\r
+            fullRanges.addAll(constraints.getRanges());\r
+            fullRanges.addAll(ranges);\r
+            Integer fd = fractionDigits == null ? constraints\r
+                    .getFractionDigits() : fractionDigits;\r
+            targetTypeBaseType = YangTypesConverter\r
+                    .javaTypeForBaseYangDecimal64Type(fullRanges, fd);\r
+        } else if (targetTypeBaseType instanceof IntegerTypeDefinition) {\r
+            List<RangeConstraint> fullRanges = new ArrayList<RangeConstraint>();\r
+            fullRanges.addAll(constraints.getRanges());\r
+            fullRanges.addAll(ranges);\r
+            if (targetTypeBaseTypeName.startsWith("int")) {\r
+                targetTypeBaseType = YangTypesConverter\r
+                        .javaTypeForBaseYangSignedIntegerType(\r
+                                targetTypeBaseTypeName, fullRanges);\r
+            } else {\r
+                targetTypeBaseType = YangTypesConverter\r
+                        .javaTypeForBaseYangUnsignedIntegerType(\r
+                                targetTypeBaseTypeName, fullRanges);\r
+            }\r
+        } else if (targetTypeBaseType instanceof StringTypeDefinition) {\r
+            List<LengthConstraint> fullLengths = new ArrayList<LengthConstraint>();\r
+            fullLengths.addAll(constraints.getLengths());\r
+            fullLengths.addAll(lengths);\r
+            List<PatternConstraint> fullPatterns = new ArrayList<PatternConstraint>();\r
+            fullPatterns.addAll(constraints.getPatterns());\r
+            fullPatterns.addAll(patterns);\r
+            targetTypeBaseType = new StringType(fullLengths, fullPatterns);\r
+        } else if (targetTypeBaseType instanceof BitsTypeDefinition) {\r
+            BitsTypeDefinition bitsType = (BitsTypeDefinition) targetTypeBaseType;\r
+            List<Bit> bits = bitsType.getBits();\r
+            targetTypeBaseType = new BitsType(bits);\r
+        } else if (targetTypeBaseType instanceof BinaryTypeDefinition) {\r
+            targetTypeBaseType = new BinaryType(null, lengths, null);\r
+        }\r
+        return targetTypeBaseType;\r
+    }\r
+\r
+    private TypeDefinitionBuilder findTypeDefinitionBuilder(\r
+            Map<String, TreeMap<Date, ModuleBuilder>> modules,\r
+            UnknownType unknownType, ModuleBuilder builder) {\r
+        Map<TypeDefinitionBuilder, TypeConstraints> result = findTypeDefinitionBuilderWithConstraints(\r
+                modules, unknownType, builder);\r
+        return result.entrySet().iterator().next().getKey();\r
+    }\r
+\r
+    private Map<TypeDefinitionBuilder, TypeConstraints> findTypeDefinitionBuilderWithConstraints(\r
+            Map<String, TreeMap<Date, ModuleBuilder>> modules,\r
+            UnknownType unknownType, ModuleBuilder builder) {\r
+        return findTypeDefinitionBuilderWithConstraints(new TypeConstraints(),\r
+                modules, unknownType, builder);\r
+    }\r
+\r
+    /**\r
+     * Traverse through all referenced types chain until base YANG type is\r
+     * founded.\r
+     *\r
+     * @param constraints\r
+     *            current type constraints\r
+     * @param modules\r
+     *            all available modules\r
+     * @param unknownType\r
+     *            unknown type\r
+     * @param builder\r
+     *            current module\r
+     * @return map, where key is type referenced and value is its constraints\r
+     */\r
+    private Map<TypeDefinitionBuilder, TypeConstraints> findTypeDefinitionBuilderWithConstraints(\r
+            TypeConstraints constraints,\r
+            Map<String, TreeMap<Date, ModuleBuilder>> modules,\r
+            UnknownType unknownType, ModuleBuilder builder) {\r
+        Map<TypeDefinitionBuilder, TypeConstraints> result = new HashMap<TypeDefinitionBuilder, TypeConstraints>();\r
+        QName unknownTypeQName = unknownType.getQName();\r
+        String unknownTypeName = unknownTypeQName.getLocalName();\r
+        String unknownTypePrefix = unknownTypeQName.getPrefix();\r
+\r
+        // search for module which contains referenced typedef\r
+        ModuleBuilder dependentModuleBuilder;\r
+        if (unknownTypePrefix.equals(builder.getPrefix())) {\r
+            dependentModuleBuilder = builder;\r
+        } else {\r
+            dependentModuleBuilder = findDependentModule(modules, builder,\r
+                    unknownTypePrefix);\r
+        }\r
+\r
+        // pull all typedef statements from dependent module...\r
+        final Set<TypeDefinitionBuilder> typedefs = dependentModuleBuilder\r
+                .getModuleTypedefs();\r
+        // and search for referenced typedef\r
+        TypeDefinitionBuilder lookedUpBuilder = null;\r
+        for (TypeDefinitionBuilder tdb : typedefs) {\r
+            QName qname = tdb.getQName();\r
+            if (qname.getLocalName().equals(unknownTypeName)) {\r
+                lookedUpBuilder = tdb;\r
+                break;\r
+            }\r
+        }\r
+\r
+        // if referenced type is UnknownType again, search recursively with\r
+        // current constraints\r
+        TypeDefinition<?> referencedType = lookedUpBuilder.getBaseType();\r
+        if (referencedType instanceof UnknownType) {\r
+            UnknownType unknown = (UnknownType) lookedUpBuilder.getBaseType();\r
+\r
+            final List<RangeConstraint> ranges = unknown.getRangeStatements();\r
+            constraints.addRanges(ranges);\r
+            final List<LengthConstraint> lengths = unknown\r
+                    .getLengthStatements();\r
+            constraints.addLengths(lengths);\r
+            final List<PatternConstraint> patterns = unknown.getPatterns();\r
+            constraints.addPatterns(patterns);\r
+            return findTypeDefinitionBuilderWithConstraints(constraints,\r
+                    modules, unknown, dependentModuleBuilder);\r
+        } else {\r
+            // pull restriction from this base type and add them to\r
+            // 'constraints'\r
+            if (referencedType instanceof DecimalTypeDefinition) {\r
+                constraints.addRanges(((DecimalTypeDefinition) referencedType)\r
+                        .getRangeStatements());\r
+                constraints\r
+                        .setFractionDigits(((DecimalTypeDefinition) referencedType)\r
+                                .getFractionDigits());\r
+            } else if (referencedType instanceof IntegerTypeDefinition) {\r
+                constraints.addRanges(((IntegerTypeDefinition) referencedType)\r
+                        .getRangeStatements());\r
+            } else if (referencedType instanceof StringTypeDefinition) {\r
+                constraints.addPatterns(((StringTypeDefinition) referencedType)\r
+                        .getPatterns());\r
+            } else if (referencedType instanceof BinaryTypeDefinition) {\r
+                constraints.addLengths(((BinaryTypeDefinition) referencedType)\r
+                        .getLengthConstraints());\r
+            }\r
+            result.put(lookedUpBuilder, constraints);\r
+            return result;\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Go through all augmentation definitions and resolve them. This means find\r
+     * referenced node and add child nodes to it.\r
+     *\r
+     * @param modules\r
+     *            all available modules\r
+     * @param module\r
+     *            current module\r
+     */\r
+    private void resolveAugments(\r
+            Map<String, TreeMap<Date, ModuleBuilder>> modules,\r
+            ModuleBuilder module) {\r
+        Set<AugmentationSchemaBuilder> augmentBuilders = module\r
+                .getAddedAugments();\r
+\r
+        Set<AugmentationSchema> augments = new HashSet<AugmentationSchema>();\r
+        for (AugmentationSchemaBuilder augmentBuilder : augmentBuilders) {\r
+            SchemaPath augmentTargetSchemaPath = augmentBuilder.getTargetPath();\r
+            String prefix = null;\r
+            List<String> augmentTargetPath = new ArrayList<String>();\r
+\r
+            for (QName pathPart : augmentTargetSchemaPath.getPath()) {\r
+                prefix = pathPart.getPrefix();\r
+                augmentTargetPath.add(pathPart.getLocalName());\r
+            }\r
+            ModuleBuilder dependentModule = findDependentModule(modules,\r
+                    module, prefix);\r
+            //\r
+            augmentTargetPath.add(0, dependentModule.getName());\r
+            //\r
+\r
+\r
+            AugmentationTargetBuilder augmentTarget = (AugmentationTargetBuilder) dependentModule\r
+                    .getNode(augmentTargetPath);\r
+            AugmentationSchema result = augmentBuilder.build();\r
+            augmentTarget.addAugmentation(result);\r
+            fillAugmentTarget(augmentBuilder, (ChildNodeBuilder) augmentTarget);\r
+            augments.add(result);\r
+        }\r
+        module.setAugmentations(augments);\r
+    }\r
+\r
+    /**\r
+     * Add all augment's child nodes to given target.\r
+     *\r
+     * @param augment\r
+     * @param target\r
+     */\r
+    private void fillAugmentTarget(AugmentationSchemaBuilder augment,\r
+            ChildNodeBuilder target) {\r
+        for (DataSchemaNodeBuilder builder : augment.getChildNodes()) {\r
+            builder.setAugmenting(true);\r
+            target.addChildNode(builder);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Go through identity statements defined in current module and resolve\r
+     * their 'base' statement if present.\r
+     *\r
+     * @param modules\r
+     *            all modules\r
+     * @param module\r
+     *            module being resolved\r
+     */\r
+    private void resolveIdentities(\r
+            Map<String, TreeMap<Date, ModuleBuilder>> modules,\r
+            ModuleBuilder module) {\r
+        Set<IdentitySchemaNodeBuilder> identities = module.getAddedIdentities();\r
+        for (IdentitySchemaNodeBuilder identity : identities) {\r
+            String baseIdentityName = identity.getBaseIdentityName();\r
+            if (baseIdentityName != null) {\r
+                String baseIdentityPrefix = null;\r
+                String baseIdentityLocalName = null;\r
+                if (baseIdentityName.contains(":")) {\r
+                    String[] splitted = baseIdentityName.split(":");\r
+                    baseIdentityPrefix = splitted[0];\r
+                    baseIdentityLocalName = splitted[1];\r
+                } else {\r
+                    baseIdentityPrefix = module.getPrefix();\r
+                    baseIdentityLocalName = baseIdentityName;\r
+                }\r
+                ModuleBuilder dependentModule;\r
+                if (baseIdentityPrefix.equals(module.getPrefix())) {\r
+                    dependentModule = module;\r
+                } else {\r
+                    dependentModule = findDependentModule(modules, module,\r
+                            baseIdentityPrefix);\r
+                }\r
+\r
+                Set<IdentitySchemaNodeBuilder> dependentModuleIdentities = dependentModule\r
+                        .getAddedIdentities();\r
+                for (IdentitySchemaNodeBuilder idBuilder : dependentModuleIdentities) {\r
+                    if (idBuilder.getQName().getLocalName()\r
+                            .equals(baseIdentityLocalName)) {\r
+                        identity.setBaseIdentity(idBuilder);\r
+                    }\r
+                }\r
+            }\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Find dependent module based on given prefix\r
+     *\r
+     * @param modules\r
+     *            all available modules\r
+     * @param module\r
+     *            current module\r
+     * @param prefix\r
+     *            target module prefix\r
+     * @return dependent module builder\r
+     */\r
+    private ModuleBuilder findDependentModule(\r
+            Map<String, TreeMap<Date, ModuleBuilder>> modules,\r
+            ModuleBuilder module, String prefix) {\r
+        ModuleImport dependentModuleImport = getModuleImport(module, prefix);\r
+        String dependentModuleName = dependentModuleImport.getModuleName();\r
+        Date dependentModuleRevision = dependentModuleImport.getRevision();\r
+\r
+        TreeMap<Date, ModuleBuilder> moduleBuildersByRevision = modules\r
+                .get(dependentModuleName);\r
+        ModuleBuilder dependentModule;\r
+        if (dependentModuleRevision == null) {\r
+            dependentModule = moduleBuildersByRevision.lastEntry().getValue();\r
+        } else {\r
+            dependentModule = moduleBuildersByRevision\r
+                    .get(dependentModuleRevision);\r
+        }\r
+        return dependentModule;\r
+    }\r
+\r
+    /**\r
+     * Get module import referenced by given prefix.\r
+     *\r
+     * @param builder\r
+     *            module to search\r
+     * @param prefix\r
+     *            prefix associated with import\r
+     * @return ModuleImport based on given prefix\r
+     */\r
+    private ModuleImport getModuleImport(ModuleBuilder builder, String prefix) {\r
+        ModuleImport moduleImport = null;\r
+        for (ModuleImport mi : builder.getModuleImports()) {\r
+            if (mi.getPrefix().equals(prefix)) {\r
+                moduleImport = mi;\r
+                break;\r
+            }\r
+        }\r
+        return moduleImport;\r
+    }\r
+\r
+    /**\r
+     * Helper method for resolving special 'min' or 'max' values in range\r
+     * constraint\r
+     *\r
+     * @param ranges\r
+     *            ranges to resolve\r
+     * @param targetType\r
+     *            target type\r
+     * @param modules\r
+     *            all available modules\r
+     * @param builder\r
+     *            current module\r
+     */\r
+    private void resolveRanges(List<RangeConstraint> ranges,\r
+            TypeDefinitionBuilder targetType,\r
+            Map<String, TreeMap<Date, ModuleBuilder>> modules,\r
+            ModuleBuilder builder) {\r
+        if (ranges != null && ranges.size() > 0) {\r
+            Long min = (Long) ranges.get(0).getMin();\r
+            Long max = (Long) ranges.get(ranges.size() - 1).getMax();\r
+            // if range contains one of the special values 'min' or 'max'\r
+            if (min.equals(Long.MIN_VALUE) || max.equals(Long.MAX_VALUE)) {\r
+                Long[] values = parseRangeConstraint(targetType, modules,\r
+                        builder);\r
+                if (min.equals(Long.MIN_VALUE)) {\r
+                    min = values[0];\r
+                    RangeConstraint oldFirst = ranges.get(0);\r
+                    RangeConstraint newFirst = BaseConstraints.rangeConstraint(\r
+                            min, oldFirst.getMax(), oldFirst.getDescription(),\r
+                            oldFirst.getReference());\r
+                    ranges.set(0, newFirst);\r
+                }\r
+                if (max.equals(Long.MAX_VALUE)) {\r
+                    max = values[1];\r
+                    RangeConstraint oldLast = ranges.get(ranges.size() - 1);\r
+                    RangeConstraint newLast = BaseConstraints.rangeConstraint(\r
+                            oldLast.getMin(), max, oldLast.getDescription(),\r
+                            oldLast.getReference());\r
+                    ranges.set(ranges.size() - 1, newLast);\r
+                }\r
+            }\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Helper method for resolving special 'min' or 'max' values in length\r
+     * constraint\r
+     *\r
+     * @param lengths\r
+     *            lengths to resolve\r
+     * @param targetType\r
+     *            target type\r
+     * @param modules\r
+     *            all available modules\r
+     * @param builder\r
+     *            current module\r
+     */\r
+    private void resolveLengths(List<LengthConstraint> lengths,\r
+            TypeDefinitionBuilder targetType,\r
+            Map<String, TreeMap<Date, ModuleBuilder>> modules,\r
+            ModuleBuilder builder) {\r
+        if (lengths != null && lengths.size() > 0) {\r
+            Long min = lengths.get(0).getMin().longValue();\r
+            Long max = lengths.get(lengths.size() - 1).getMax().longValue();\r
+            // if length contains one of the special values 'min' or 'max'\r
+            if (min.equals(Long.MIN_VALUE) || max.equals(Long.MAX_VALUE)) {\r
+                Long[] values = parseRangeConstraint(targetType, modules,\r
+                        builder);\r
+                if (min.equals(Long.MIN_VALUE)) {\r
+                    min = values[0];\r
+                    LengthConstraint oldFirst = lengths.get(0);\r
+                    LengthConstraint newFirst = BaseConstraints\r
+                            .lengthConstraint(min, oldFirst.getMax(),\r
+                                    oldFirst.getDescription(),\r
+                                    oldFirst.getReference());\r
+                    lengths.set(0, newFirst);\r
+                }\r
+                if (max.equals(Long.MAX_VALUE)) {\r
+                    max = values[1];\r
+                    LengthConstraint oldLast = lengths.get(lengths.size() - 1);\r
+                    LengthConstraint newLast = BaseConstraints\r
+                            .lengthConstraint(oldLast.getMin(), max,\r
+                                    oldLast.getDescription(),\r
+                                    oldLast.getReference());\r
+                    lengths.set(lengths.size() - 1, newLast);\r
+                }\r
+            }\r
+        }\r
+    }\r
+\r
+    private Long[] parseRangeConstraint(TypeDefinitionBuilder targetType,\r
+            Map<String, TreeMap<Date, ModuleBuilder>> modules,\r
+            ModuleBuilder builder) {\r
+        TypeDefinition<?> targetBaseType = targetType.getBaseType();\r
+\r
+        if (targetBaseType instanceof IntegerTypeDefinition) {\r
+            IntegerTypeDefinition itd = (IntegerTypeDefinition) targetBaseType;\r
+            List<RangeConstraint> ranges = itd.getRangeStatements();\r
+            Long min = (Long) ranges.get(0).getMin();\r
+            Long max = (Long) ranges.get(ranges.size() - 1).getMax();\r
+            return new Long[] { min, max };\r
+        } else if (targetBaseType instanceof DecimalTypeDefinition) {\r
+            DecimalTypeDefinition dtd = (DecimalTypeDefinition) targetBaseType;\r
+            List<RangeConstraint> ranges = dtd.getRangeStatements();\r
+            Long min = (Long) ranges.get(0).getMin();\r
+            Long max = (Long) ranges.get(ranges.size() - 1).getMax();\r
+            return new Long[] { min, max };\r
+        } else {\r
+            return parseRangeConstraint(\r
+                    findTypeDefinitionBuilder(modules,\r
+                            (UnknownType) targetBaseType, builder), modules,\r
+                    builder);\r
+        }\r
+    }\r
+\r
+    private Date createEpochTime() {\r
+        Calendar c = Calendar.getInstance();\r
+        c.setTimeInMillis(0);\r
+        return c.getTime();\r
+    }\r
+\r
+    private static class SchemaContextImpl implements SchemaContext {\r
+        private final Set<Module> modules;\r
+\r
+        private SchemaContextImpl(Set<Module> modules) {\r
+            this.modules = modules;\r
+        }\r
+\r
+        @Override\r
+        public Set<DataSchemaNode> getDataDefinitions() {\r
+            final Set<DataSchemaNode> dataDefs = new HashSet<DataSchemaNode>();\r
+            for (Module m : modules) {\r
+                dataDefs.addAll(m.getChildNodes());\r
+            }\r
+            return dataDefs;\r
+        }\r
+\r
+        @Override\r
+        public Set<Module> getModules() {\r
+            return modules;\r
+        }\r
+\r
+        @Override\r
+        public Set<NotificationDefinition> getNotifications() {\r
+            final Set<NotificationDefinition> notifications = new HashSet<NotificationDefinition>();\r
+            for (Module m : modules) {\r
+                notifications.addAll(m.getNotifications());\r
+            }\r
+            return notifications;\r
+        }\r
+\r
+        @Override\r
+        public Set<RpcDefinition> getOperations() {\r
+            final Set<RpcDefinition> rpcs = new HashSet<RpcDefinition>();\r
+            for (Module m : modules) {\r
+                rpcs.addAll(m.getRpcs());\r
+            }\r
+            return rpcs;\r
+        }\r
+\r
+        @Override\r
+        public Set<ExtensionDefinition> getExtensions() {\r
+            final Set<ExtensionDefinition> extensions = new HashSet<ExtensionDefinition>();\r
+            for (Module m : modules) {\r
+                extensions.addAll(m.getExtensionSchemaNodes());\r
+            }\r
+            return extensions;\r
+        }\r
+    }\r
+\r
+    private static class TypeConstraints {\r
+        private final List<RangeConstraint> ranges = new ArrayList<RangeConstraint>();\r
+        private final List<LengthConstraint> lengths = new ArrayList<LengthConstraint>();\r
+        private final List<PatternConstraint> patterns = new ArrayList<PatternConstraint>();\r
+        private Integer fractionDigits;\r
+\r
+        public List<RangeConstraint> getRanges() {\r
+            return ranges;\r
+        }\r
+\r
+        public void addRanges(List<RangeConstraint> ranges) {\r
+            this.ranges.addAll(0, ranges);\r
+        }\r
+\r
+        public List<LengthConstraint> getLengths() {\r
+            return lengths;\r
+        }\r
+\r
+        public void addLengths(List<LengthConstraint> lengths) {\r
+            this.lengths.addAll(0, lengths);\r
+        }\r
+\r
+        public List<PatternConstraint> getPatterns() {\r
+            return patterns;\r
+        }\r
+\r
+        public void addPatterns(List<PatternConstraint> patterns) {\r
+            this.patterns.addAll(0, patterns);\r
+        }\r
+\r
+        public Integer getFractionDigits() {\r
+            return fractionDigits;\r
+        }\r
+\r
+        public void setFractionDigits(Integer fractionDigits) {\r
+            if (fractionDigits != null) {\r
+                this.fractionDigits = fractionDigits;\r
+            }\r
+        }\r
+    }\r
+\r
+}\r