*/
package org.opendaylight.yangtools.yang.parser.impl;
+import java.util.ArrayList;
+import java.util.List;
+
import org.antlr.v4.runtime.BaseErrorListener;
import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Recognizer;
-import org.opendaylight.yangtools.yang.parser.util.YangParseException;
-
-import java.util.ArrayList;
-import java.util.List;
+import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
final class YangErrorListener extends BaseErrorListener {
- private final List<Exception> exceptions = new ArrayList<>();
+ private static final Logger LOG = LoggerFactory.getLogger(YangErrorListener.class);
+ private final List<YangSyntaxErrorException> exceptions = new ArrayList<>();
@Override
- public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine,
- String msg, RecognitionException e) {
- String module = getModuleName(recognizer);
- exceptions.add(new YangParseException(module, line, msg));
+ public void syntaxError(final Recognizer<?, ?> recognizer, final Object offendingSymbol, final int line,
+ final int charPositionInLine, final String msg, final RecognitionException e) {
+ LOG.debug("Syntax error at {}:{}: {}", line, charPositionInLine, msg, e);
+
+ final String module = getModuleName(recognizer);
+ exceptions.add(new YangSyntaxErrorException(module, line, charPositionInLine, msg, e));
}
- private String getModuleName(Recognizer<?, ?> recognizer) {
- String result;
- if (recognizer instanceof Parser) {
- try {
- Parser parser = (Parser) recognizer;
- String model = parser.getInputStream().getTokenSource().getInputStream().toString();
- model = model.substring(0, model.indexOf("\n"));
- model = model.substring(model.indexOf("module") + 6);
- model = model.substring(0, model.indexOf("{"));
- model = model.trim();
- result = model;
- } catch (Exception e) {
- result = "";
- }
- } else {
- result = "";
+ private static String getModuleName(final Recognizer<?, ?> recognizer) {
+ if (!(recognizer instanceof Parser)) {
+ return null;
+ }
+
+ final Parser parser = (Parser) recognizer;
+ try {
+ String model = parser.getInputStream().getTokenSource().getInputStream().toString();
+ model = model.substring(0, model.indexOf("\n"));
+ model = model.substring(model.indexOf("module") + 6);
+ model = model.substring(0, model.indexOf("{"));
+ model = model.trim();
+ return model;
+ } catch (Exception e) {
+ LOG.debug("Failed to extract module name from parser {}", parser, e);
+ return null;
}
- return result;
}
- public void validate() {
- if (!exceptions.isEmpty()) {
- StringBuilder sb = new StringBuilder();
- for (Exception e : exceptions) {
- sb.append("\n");
- sb.append(e.getMessage());
+ public void validate() throws YangSyntaxErrorException {
+ if (exceptions.isEmpty()) {
+ return;
+ }
+
+ // Single exception: just throw it
+ if (exceptions.size() == 1) {
+ throw exceptions.get(0);
+ }
+
+ final StringBuilder sb = new StringBuilder();
+ String module = null;
+ boolean first = true;
+ for (YangSyntaxErrorException e : exceptions) {
+ if (module == null) {
+ module = e.getModule();
}
- throw new YangParseException(sb.toString());
+ if (first) {
+ first = false;
+ } else {
+ sb.append('\n');
+ }
+
+ sb.append(e.getFormattedMessage());
}
- }
+ throw new YangSyntaxErrorException(module, 0, 0, sb.toString());
+ }
}
import static org.opendaylight.yangtools.yang.parser.util.TypeUtils.resolveTypeUnionWithContext;
import static org.opendaylight.yangtools.yang.parser.util.TypeUtils.resolveTypeWithContext;
-import com.google.common.base.Preconditions;
-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.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.opendaylight.yangtools.yang.model.api.SchemaNode;
import org.opendaylight.yangtools.yang.model.api.SchemaPath;
import org.opendaylight.yangtools.yang.model.parser.api.YangContextParser;
+import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationSchemaBuilder;
import org.opendaylight.yangtools.yang.parser.builder.api.AugmentationTargetBuilder;
import org.opendaylight.yangtools.yang.parser.builder.api.Builder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Preconditions;
+import com.google.common.collect.HashBiMap;
+import com.google.common.io.ByteSource;
+
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.";
@Override
+ @Deprecated
public Set<Module> parseYangModels(final File yangFile, final File directory) {
try {
return parseFile(yangFile, directory).getModules();
- } catch (IOException e) {
+ } catch (IOException | YangSyntaxErrorException e) {
throw new YangParseException("Failed to parse yang data", e);
}
}
@Override
- public SchemaContext parseFile(final File yangFile, final File directory) throws IOException {
+ public SchemaContext parseFile(final File yangFile, final File directory) throws IOException, YangSyntaxErrorException {
Preconditions.checkState(yangFile.exists(), yangFile + " does not exists");
Preconditions.checkState(directory.exists(), directory + " does not exists");
Preconditions.checkState(directory.isDirectory(), directory + " is not a directory");
}
@Override
+ @Deprecated
public Set<Module> parseYangModels(final List<File> yangFiles) {
return parseFiles(yangFiles).getModules();
}
}
@Override
+ @Deprecated
public Set<Module> parseYangModels(final List<File> yangFiles, final SchemaContext context) {
try {
return parseFiles(yangFiles, context).getModules();
- } catch (IOException e) {
+ } catch (IOException | YangSyntaxErrorException e) {
throw new YangParseException("Failed to parse yang data", e);
}
}
@Override
- public SchemaContext parseFiles(final Collection<File> yangFiles, final SchemaContext context) throws IOException {
+ public SchemaContext parseFiles(final Collection<File> yangFiles, final SchemaContext context) throws IOException, YangSyntaxErrorException {
if (yangFiles == null) {
return resolveSchemaContext(Collections.<Module> emptySet());
}
}
@Override
+ @Deprecated
public Set<Module> parseYangModelsFromStreams(final List<InputStream> yangModelStreams) {
Collection<ByteSource> sources = ParserUtils.streamsToByteSources(yangModelStreams);
try {
return parseSources(sources).getModules();
- } catch (IOException e) {
+ } catch (IOException | YangSyntaxErrorException e) {
throw new YangParseException("Failed to parse yang data", e);
}
}
@Override
- public SchemaContext parseSources(Collection<ByteSource> sources) throws IOException {
+ public SchemaContext parseSources(final Collection<ByteSource> sources) throws IOException, YangSyntaxErrorException {
Collection<Module> unsorted = parseYangModelSources(sources).values();
Set<Module> sorted = new LinkedHashSet<>(
ModuleDependencySort.sort(unsorted.toArray(new Module[unsorted.size()])));
}
@Override
- public Set<Module> parseYangModelsFromStreams(final List<InputStream> yangModelStreams, SchemaContext context) {
+ @Deprecated
+ public Set<Module> parseYangModelsFromStreams(final List<InputStream> yangModelStreams, final SchemaContext context) {
Collection<ByteSource> sources = ParserUtils.streamsToByteSources(yangModelStreams);
try {
return parseSources(sources, context).getModules();
- } catch (IOException e) {
+ } catch (IOException | YangSyntaxErrorException e) {
throw new YangParseException("Failed to parse yang data", e);
}
}
@Override
- public SchemaContext parseSources(Collection<ByteSource> sources, SchemaContext context) throws IOException {
+ public SchemaContext parseSources(final Collection<ByteSource> sources, final SchemaContext context) throws IOException, YangSyntaxErrorException {
if (sources == null) {
return resolveSchemaContext(Collections.<Module> emptySet());
}
}
@Override
- public Map<File, Module> parseYangModelsMapped(Collection<File> yangFiles) {
+ public Map<File, Module> parseYangModelsMapped(final Collection<File> yangFiles) {
if (yangFiles == null || yangFiles.isEmpty()) {
return Collections.emptyMap();
}
Map<ByteSource, Module> byteSourceToModule;
try {
byteSourceToModule = parseYangModelSources(byteSourceToFile.keySet());
- } catch (IOException e) {
+ } catch (IOException | YangSyntaxErrorException e) {
throw new YangParseException("Failed to parse yang data", e);
}
Map<File, Module> result = new LinkedHashMap<>();
Map<ByteSource, Module> sourceToModule;
try {
sourceToModule = parseYangModelSources(sourceToStream.keySet());
- } catch (IOException e) {
+ } catch (IOException | YangSyntaxErrorException e) {
throw new YangParseException("Failed to parse yang data", e);
}
Map<InputStream, Module> result = new LinkedHashMap<>();
return new SchemaContextImpl(modules, identifiersToSources);
}
- private Map<ByteSource, Module> parseYangModelSources(final Collection<ByteSource> sources) throws IOException {
+ private Map<ByteSource, Module> parseYangModelSources(final Collection<ByteSource> sources) throws IOException, YangSyntaxErrorException {
if (sources == null || sources.isEmpty()) {
return Collections.emptyMap();
}
* collection of streams to parse
* @return map, where key is source stream and value is module builder
* parsed from stream
+ * @throws YangSyntaxErrorException
*/
- private Map<ByteSource, ModuleBuilder> resolveSources(Collection<ByteSource> streams) throws IOException {
+ 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;
}
- private Map<ByteSource, ModuleBuilder> parseSourcesToBuilders(Collection<ByteSource> sources) throws IOException {
+ private Map<ByteSource, ModuleBuilder> parseSourcesToBuilders(final Collection<ByteSource> sources) throws IOException, YangSyntaxErrorException {
final ParseTreeWalker walker = new ParseTreeWalker();
final Map<ByteSource, ParseTree> sourceToTree = parseYangSources(sources);
final Map<ByteSource, ModuleBuilder> sourceToBuilder = new LinkedHashMap<>();
return sourceToBuilder;
}
- private Map<ByteSource, ModuleBuilder> resolveSubmodules(Map<ByteSource, ModuleBuilder> builders) {
+ private Map<ByteSource, ModuleBuilder> resolveSubmodules(final Map<ByteSource, ModuleBuilder> builders) {
Map<ByteSource, ModuleBuilder> modules = new HashMap<>();
Set<ModuleBuilder> submodules = new HashSet<>();
for (Map.Entry<ByteSource, ModuleBuilder> entry : builders.entrySet()) {
* collection of builders containing modules and submodules
* @return collection of module builders
*/
- private Collection<ModuleBuilder> resolveSubmodules(Collection<ModuleBuilder> builders) {
+ private Collection<ModuleBuilder> resolveSubmodules(final Collection<ModuleBuilder> builders) {
Collection<ModuleBuilder> modules = new HashSet<>();
Set<ModuleBuilder> submodules = new HashSet<>();
for (ModuleBuilder moduleBuilder : builders) {
return modules;
}
- private void addSubmoduleToModule(ModuleBuilder submodule, ModuleBuilder module) {
+ private void addSubmoduleToModule(final ModuleBuilder submodule, final ModuleBuilder module) {
submodule.setParent(module);
module.getDirtyNodes().addAll(submodule.getDirtyNodes());
module.getModuleImports().addAll(submodule.getModuleImports());
}
private Map<String, TreeMap<Date, ModuleBuilder>> resolveModuleBuilders(
- final Collection<ByteSource> yangFileStreams, final SchemaContext context) throws IOException {
+ final Collection<ByteSource> yangFileStreams, final SchemaContext context) throws IOException, YangSyntaxErrorException {
Map<ByteSource, ModuleBuilder> parsedBuilders = resolveSources(yangFileStreams);
ModuleBuilder[] builders = new ModuleBuilder[parsedBuilders.size()];
parsedBuilders.values().toArray(builders);
* modules to order
* @return modules ordered by name and revision
*/
- private LinkedHashMap<String, TreeMap<Date, ModuleBuilder>> orderModules(List<ModuleBuilder> modules) {
+ private LinkedHashMap<String, TreeMap<Date, ModuleBuilder>> orderModules(final List<ModuleBuilder> modules) {
final LinkedHashMap<String, TreeMap<Date, ModuleBuilder>> result = new LinkedHashMap<>();
for (final ModuleBuilder builder : modules) {
if (builder == null) {
* @param filtered
* collection to fill up
*/
- private void filterImports(ModuleBuilder main, Collection<ModuleBuilder> other, Collection<ModuleBuilder> filtered) {
+ private void filterImports(final ModuleBuilder main, final Collection<ModuleBuilder> other, final Collection<ModuleBuilder> filtered) {
Set<ModuleImport> imports = main.getModuleImports();
// if this is submodule, add parent to filtered and pick its imports
}
}
- private Map<ByteSource, ParseTree> parseYangSources(final Collection<ByteSource> sources) throws IOException {
+ private Map<ByteSource, ParseTree> parseYangSources(final Collection<ByteSource> sources) throws IOException, YangSyntaxErrorException {
final Map<ByteSource, ParseTree> trees = new HashMap<>();
for (ByteSource source : sources) {
trees.put(source, parseYangSource(source));
return trees;
}
- private ParseTree parseYangSource(final ByteSource source) throws IOException {
- ParseTree result = null;
- InputStream stream = null;
- try {
- stream = source.openStream();
+ private YangContext parseYangSource(final ByteSource source) throws IOException, YangSyntaxErrorException {
+ try (InputStream stream = source.openStream()) {
final ANTLRInputStream input = new ANTLRInputStream(stream);
final YangLexer lexer = new YangLexer(input);
final CommonTokenStream tokens = new CommonTokenStream(lexer);
final YangParser parser = new YangParser(tokens);
parser.removeErrorListeners();
- YangErrorListener errorListener = new YangErrorListener();
+
+ final YangErrorListener errorListener = new YangErrorListener();
parser.addErrorListener(errorListener);
- result = parser.yang();
+
+ final YangContext result = parser.yang();
errorListener.validate();
- } finally {
- if (stream != null) {
- try {
- stream.close();
- } catch (IOException e) {
- LOG.warn("Failed to close stream {}", stream);
- }
- }
- }
- return result;
+
+ return result;
+ }
}
public static YangContext parseStreamWithoutErrorListeners(final InputStream yangStream) {
}
private void resolveDirtyNodesWithContext(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
- final ModuleBuilder module, SchemaContext context) {
+ final ModuleBuilder module, final SchemaContext context) {
final Set<TypeAwareBuilder> dirtyNodes = module.getDirtyNodes();
if (!dirtyNodes.isEmpty()) {
for (TypeAwareBuilder nodeToResolve : dirtyNodes) {
* SchemaContext containing already resolved modules
*/
private void resolveAugmentsTargetPath(final Map<String, TreeMap<Date, ModuleBuilder>> modules,
- SchemaContext context) {
+ final SchemaContext context) {
// collect augments from all loaded modules
final List<AugmentationSchemaBuilder> allAugments = new ArrayList<>();
for (Map.Entry<String, TreeMap<Date, ModuleBuilder>> entry : modules.entrySet()) {
* @param parentPath
* schema path of parent node
*/
- private void correctPathForAugmentNodes(DataSchemaNodeBuilder node, SchemaPath parentPath) {
+ private void correctPathForAugmentNodes(final DataSchemaNodeBuilder node, final SchemaPath parentPath) {
SchemaPath newPath = ParserUtils.createSchemaPath(parentPath, node.getQName());
node.setPath(newPath);
if (node instanceof DataNodeContainerBuilder) {
* @param augments
* augments to check
*/
- private void checkAugmentMandatoryNodes(Collection<AugmentationSchemaBuilder> augments) {
+ private void checkAugmentMandatoryNodes(final Collection<AugmentationSchemaBuilder> augments) {
for (AugmentationSchemaBuilder augment : augments) {
String augmentPrefix = augment.getTargetPath().getPath().get(0).getPrefix();
ModuleBuilder module = ParserUtils.getParentModule(augment);
* @param context
* SchemaContext containing already resolved modules
*/
- private void resolveUses(UsesNodeBuilder usesNode,
+ private void resolveUses(final UsesNodeBuilder usesNode,
final Map<String, TreeMap<Date, ModuleBuilder>> modules, final SchemaContext context) {
if (!usesNode.isResolved()) {
DataNodeContainerBuilder parent = usesNode.getParent();
* @param context
* SchemaContext containing already resolved modules
*/
- private void resolveUsesWithContext(UsesNodeBuilder usesNode) {
+ private void resolveUsesWithContext(final UsesNodeBuilder usesNode) {
final int line = usesNode.getLine();
DataNodeContainerBuilder parent = usesNode.getParent();
ModuleBuilder module = ParserUtils.getParentModule(parent);