Update ParserListenerUtils to use SchemaPath
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / impl / YangParserImpl.java
index 77d390f8f7a9aeb0742590d1e71e3aaadc92299d..cea011edcbd4652a155d15b8185ad1d457e637a8 100644 (file)
@@ -27,24 +27,29 @@ import static org.opendaylight.yangtools.yang.parser.builder.impl.TypeUtils.reso
 
 import com.google.common.base.Optional;
 import com.google.common.base.Preconditions;
+import com.google.common.base.Splitter;
 import com.google.common.collect.HashBiMap;
 import com.google.common.io.ByteSource;
+
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
-import java.net.URI;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
+
+import javax.annotation.concurrent.Immutable;
+
 import org.antlr.v4.runtime.ANTLRInputStream;
 import org.antlr.v4.runtime.CommonTokenStream;
 import org.antlr.v4.runtime.tree.ParseTree;
@@ -98,10 +103,16 @@ import org.opendaylight.yangtools.yang.parser.util.YangParseException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+@Immutable
 public final class YangParserImpl implements YangContextParser {
     private static final Logger LOG = LoggerFactory.getLogger(YangParserImpl.class);
-
     private static final String FAIL_DEVIATION_TARGET = "Failed to find deviation target.";
+    private static final Splitter COLON_SPLITTER = Splitter.on(':');
+    private static final YangParserImpl INSTANCE = new YangParserImpl();
+
+    public static YangParserImpl getInstance() {
+        return INSTANCE;
+    }
 
     @Override
     @Deprecated
@@ -186,8 +197,7 @@ public final class YangParserImpl implements YangContextParser {
         }
 
         Collection<ByteSource> sources = BuilderUtils.filesToByteSources(yangFiles);
-        SchemaContext result = parseSources(sources, context);
-        return result;
+        return parseSources(sources, context);
     }
 
     @Override
@@ -323,7 +333,6 @@ public final class YangParserImpl implements YangContextParser {
         Map<ByteSource, ModuleBuilder> sourceToBuilder = resolveSources(sources);
         // sort and check for duplicates
         List<ModuleBuilder> sorted = ModuleDependencySort.sort(sourceToBuilder.values());
-        BuilderUtils.setSourceToBuilder(sourceToBuilder);
         Map<String, TreeMap<Date, ModuleBuilder>> modules = orderModules(sorted);
         Map<ModuleBuilder, Module> builderToModule = build(modules);
         Map<ModuleBuilder, ByteSource> builderToSource = HashBiMap.create(sourceToBuilder).inverse();
@@ -347,11 +356,11 @@ public final class YangParserImpl implements YangContextParser {
      *         parsed from stream
      * @throws YangSyntaxErrorException
      */
-    private Map<ByteSource, ModuleBuilder> resolveSources(final Collection<ByteSource> streams) throws IOException,
-    YangSyntaxErrorException {
+    // TODO: remove ByteSource result after removing YangModelParser
+    private Map<ByteSource, ModuleBuilder> resolveSources(final Collection<ByteSource> streams)
+            throws IOException, YangSyntaxErrorException {
         Map<ByteSource, ModuleBuilder> builders = parseSourcesToBuilders(streams);
-        Map<ByteSource, ModuleBuilder> result = resolveSubmodules(builders);
-        return result;
+        return resolveSubmodules(builders);
     }
 
     private Map<ByteSource, ModuleBuilder> parseSourcesToBuilders(final Collection<ByteSource> sources)
@@ -366,24 +375,19 @@ public final class YangParserImpl implements YangContextParser {
         YangParserListenerImpl yangModelParser;
         for (Map.Entry<ByteSource, ParseTree> entry : sourceToTree.entrySet()) {
             ByteSource source = entry.getKey();
-            String path = null;
-            InputStream stream = source.openStream();
-            if (stream instanceof NamedInputStream) {
-                path = stream.toString();
-            }
-            try {
-                stream.close();
-            } catch (IOException e) {
-                LOG.warn("Failed to close stream {}", stream);
+            String path = null; // TODO refactor to Optional
+            //TODO refactor so that path can be retrieved without opening stream: NamedInputStream -> NamedByteSource ?
+            try(InputStream stream = source.openStream()) {
+                if (stream instanceof NamedInputStream) {
+                    path = stream.toString();
+                }
             }
-
             yangModelParser = new YangParserListenerImpl(path);
             walker.walk(yangModelParser, entry.getValue());
             ModuleBuilder moduleBuilder = yangModelParser.getModuleBuilder();
+            moduleBuilder.setSource(source);
             sourceToBuilder.put(source, moduleBuilder);
         }
-
-        BuilderUtils.setSourceToBuilder(sourceToBuilder);
         return sourceToBuilder;
     }
 
@@ -593,6 +597,11 @@ public final class YangParserImpl implements YangContextParser {
         }
     }
 
+    /**
+     * Mini parser: This parsing context does not validate full YANG module, only
+     * parses header up to the revisions and imports.
+     * @see org.opendaylight.yangtools.yang.parser.impl.util.YangModelDependencyInfo
+     */
     public static YangContext parseStreamWithoutErrorListeners(final InputStream yangStream) {
         YangContext result = null;
         try {
@@ -832,32 +841,27 @@ public final class YangParserImpl implements YangContextParser {
             DataNodeContainerBuilder usesParent = ((UsesNodeBuilder) parent).getParent();
             newPath.addAll(usesParent.getPath().getPath());
 
-            URI ns;
-            Date revision;
-            String prefix;
-            QName baseQName = usesParent.getQName();
+            final QName baseQName = usesParent.getQName();
+            final QNameModule qnm;
+            final String prefix;
             if (baseQName == null) {
                 ModuleBuilder m = BuilderUtils.getParentModule(usesParent);
-                ns = m.getNamespace();
-                revision = m.getRevision();
+                qnm = m.getQNameModule();
                 prefix = m.getPrefix();
             } else {
-                ns = baseQName.getNamespace();
-                revision = baseQName.getRevision();
+                qnm = baseQName.getModule();
                 prefix = baseQName.getPrefix();
             }
 
-            final QNameModule qm = QNameModule.create(ns, revision);
             for (QName qn : oldSchemaPath.getPathFromRoot()) {
-                newPath.add(QName.create(qm, prefix, qn.getLocalName()));
+                newPath.add(QName.create(qnm, prefix, qn.getLocalName()));
             }
         } else {
             Iterable<QName> oldPath = oldSchemaPath.getPathFromRoot();
             for (QName qn : oldPath) {
-                URI ns = module.getNamespace();
-                Date rev = module.getRevision();
+                QNameModule qnm = module.getQNameModule();
                 String localPrefix = qn.getPrefix();
-                if (localPrefix != null && !("".equals(localPrefix))) {
+                if (localPrefix != null && !localPrefix.isEmpty()) {
                     ModuleBuilder currentModule = BuilderUtils.findModuleFromBuilders(modules, module, localPrefix,
                             augment.getLine());
                     if (currentModule == null) {
@@ -866,14 +870,12 @@ public final class YangParserImpl implements YangContextParser {
                             throw new YangParseException(module.getName(), augment.getLine(), "Module with prefix "
                                     + localPrefix + " not found.");
                         }
-                        ns = m.getNamespace();
-                        rev = m.getRevision();
+                        qnm = m.getQNameModule();
                     } else {
-                        ns = currentModule.getNamespace();
-                        rev = currentModule.getRevision();
+                        qnm = currentModule.getQNameModule();
                     }
                 }
-                newPath.add(new QName(ns, rev, localPrefix, qn.getLocalName()));
+                newPath.add(new QName(qnm.getNamespace(), qnm.getRevision(), localPrefix, qn.getLocalName()));
             }
         }
         augment.setTargetNodeSchemaPath(SchemaPath.create(newPath, true));
@@ -1079,10 +1081,10 @@ public final class YangParserImpl implements YangContextParser {
      */
     private ModuleBuilder findTargetModule(final QName qname, final ModuleBuilder module,
             final Map<String, TreeMap<Date, ModuleBuilder>> modules, final SchemaContext context, final int line) {
-        ModuleBuilder targetModule = null;
+        ModuleBuilder targetModule;
 
         String prefix = qname.getPrefix();
-        if (prefix == null || prefix.equals("")) {
+        if (prefix == null || prefix.isEmpty()) {
             targetModule = module;
         } else {
             targetModule = findModuleFromBuilders(modules, module, qname.getPrefix(), line);
@@ -1106,7 +1108,7 @@ public final class YangParserImpl implements YangContextParser {
 
     private ModuleBuilder findTargetModule(final String prefix, final ModuleBuilder module,
             final Map<String, TreeMap<Date, ModuleBuilder>> modules, final SchemaContext context, final int line) {
-        ModuleBuilder targetModule = null;
+        ModuleBuilder targetModule;
 
         if (prefix == null || prefix.equals("")) {
             targetModule = module;
@@ -1184,14 +1186,15 @@ public final class YangParserImpl implements YangContextParser {
                     if (baseIdentityName != null) {
 
                         IdentitySchemaNodeBuilder result = null;
-                        if (baseIdentityName.contains(":")) {
-                            String[] splittedBase = baseIdentityName.split(":");
-                            if (splittedBase.length > 2) {
+                        if (baseIdentityName.indexOf(':') != -1) {
+                            final Iterator<String> split = COLON_SPLITTER.split(baseIdentityName).iterator();
+                            final String prefix = split.next();
+                            final String name = split.next();
+                            if (split.hasNext()) {
                                 throw new YangParseException(module.getName(), line,
                                         "Failed to parse identityref base: " + baseIdentityName);
                             }
-                            String prefix = splittedBase[0];
-                            String name = splittedBase[1];
+
                             ModuleBuilder dependentModule = findTargetModule(prefix, module, modules, context, line);
                             if (dependentModule != null) {
                                 result = BuilderUtils.findIdentity(dependentModule.getAddedIdentities(), name);
@@ -1343,49 +1346,44 @@ public final class YangParserImpl implements YangContextParser {
         DataNodeContainerBuilder parent = usesNode.getParent();
         ModuleBuilder module = BuilderUtils.getParentModule(parent);
         SchemaPath parentPath;
-        URI ns = null;
-        Date rev = null;
-        String pref = null;
+
+        final QName parentQName;
         if (parent instanceof AugmentationSchemaBuilder || parent instanceof ModuleBuilder) {
-            ns = module.getNamespace();
-            rev = module.getRevision();
-            pref = module.getPrefix();
+            parentQName = QName.create(module.getQNameModule(), module.getPrefix(), "dummy");
             if (parent instanceof AugmentationSchemaBuilder) {
                 parentPath = ((AugmentationSchemaBuilder) parent).getTargetNodeSchemaPath();
             } else {
-                parentPath = ((ModuleBuilder) parent).getPath();
+                parentPath = parent.getPath();
             }
         } else {
-            ns = ((DataSchemaNodeBuilder) parent).getQName().getNamespace();
-            rev = ((DataSchemaNodeBuilder) parent).getQName().getRevision();
-            pref = ((DataSchemaNodeBuilder) parent).getQName().getPrefix();
-            parentPath = ((DataSchemaNodeBuilder) parent).getPath();
+            parentQName = parent.getQName();
+            parentPath = parent.getPath();
         }
 
         GroupingDefinition gd = usesNode.getGroupingDefinition();
 
         Set<DataSchemaNodeBuilder> childNodes = wrapChildNodes(module.getModuleName(), line, gd.getChildNodes(),
-                parentPath, ns, rev, pref);
+                parentPath, parentQName);
         parent.getChildNodeBuilders().addAll(childNodes);
         for (DataSchemaNodeBuilder childNode : childNodes) {
             setNodeAddedByUses(childNode);
         }
 
-        Set<TypeDefinitionBuilder> typedefs = wrapTypedefs(module.getModuleName(), line, gd, parentPath, ns, rev, pref);
+        Set<TypeDefinitionBuilder> typedefs = wrapTypedefs(module.getModuleName(), line, gd, parentPath, parentQName);
         parent.getTypeDefinitionBuilders().addAll(typedefs);
         for (TypeDefinitionBuilder typedef : typedefs) {
             setNodeAddedByUses(typedef);
         }
 
         Set<GroupingBuilder> groupings = wrapGroupings(module.getModuleName(), line, usesNode.getGroupingDefinition()
-                .getGroupings(), parentPath, ns, rev, pref);
+                .getGroupings(), parentPath, parentQName);
         parent.getGroupingBuilders().addAll(groupings);
         for (GroupingBuilder gb : groupings) {
             setNodeAddedByUses(gb);
         }
 
         List<UnknownSchemaNodeBuilderImpl> unknownNodes = wrapUnknownNodes(module.getModuleName(), line,
-                gd.getUnknownSchemaNodes(), parentPath, ns, rev, pref);
+                gd.getUnknownSchemaNodes(), parentPath, parentQName);
         parent.getUnknownNodes().addAll(unknownNodes);
         for (UnknownSchemaNodeBuilder un : unknownNodes) {
             un.setAddedByUses(true);