}
}
- private Map<ByteSource, ParseTree> parseYangSources(final Collection<ByteSource> sources) throws IOException,
- YangSyntaxErrorException {
+ 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));
+ try (InputStream stream = source.openStream()) {
+ trees.put(source, parseYangSource(stream));
+ }
}
return trees;
}
- 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();
+ public static YangContext parseYangSource(final InputStream stream) throws IOException, YangSyntaxErrorException {
+ final YangLexer lexer = new YangLexer(new ANTLRInputStream(stream));
+ final CommonTokenStream tokens = new CommonTokenStream(lexer);
+ final YangParser parser = new YangParser(tokens);
+ parser.removeErrorListeners();
- final YangErrorListener errorListener = new YangErrorListener();
- parser.addErrorListener(errorListener);
+ final YangErrorListener errorListener = new YangErrorListener();
+ parser.addErrorListener(errorListener);
- final YangContext result = parser.yang();
- errorListener.validate();
+ final YangContext result = parser.yang();
+ errorListener.validate();
- return result;
- }
+ return result;
}
/**
import com.google.common.base.Optional;
import com.google.common.collect.ImmutableSet;
+
import java.io.InputStream;
import java.util.Date;
import java.util.List;
+
+import org.antlr.v4.runtime.ParserRuleContext;
import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Belongs_to_stmtContext;
import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Import_stmtContext;
import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.Include_stmtContext;
import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.YangContext;
import org.opendaylight.yangtools.yang.common.QName;
import org.opendaylight.yangtools.yang.model.api.ModuleImport;
+import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
/**
private final ImmutableSet<ModuleImport> dependencies;
YangModelDependencyInfo(final String name, final String formattedRevision,
- final ImmutableSet<ModuleImport> imports, final ImmutableSet<ModuleImport> includes) {
+ final ImmutableSet<ModuleImport> imports, final ImmutableSet<ModuleImport> includes) {
this.name = name;
this.formattedRevision = formattedRevision;
this.revision = QName.parseRevision(formattedRevision);
return true;
}
+ /**
+ * Extracts {@link YangModelDependencyInfo} from an abstract syntax tree
+ * of a YANG model.
+ *
+ * @param tree Abstract syntax tree
+ * @return {@link YangModelDependencyInfo}
+ * @throws YangSyntaxErrorException
+ * If the AST is not a valid YANG module/submodule
+ */
+ public static YangModelDependencyInfo fromAST(final String name, final ParserRuleContext tree) throws YangSyntaxErrorException {
+ final Optional<Module_stmtContext> moduleCtx = getFirstContext(tree, Module_stmtContext.class);
+ if (moduleCtx.isPresent()) {
+ return parseModuleContext(moduleCtx.get());
+ }
+
+ final Optional<Submodule_stmtContext> submoduleCtx = getFirstContext(tree, Submodule_stmtContext.class);
+ if (submoduleCtx.isPresent()) {
+ return parseSubmoduleContext(submoduleCtx.get());
+ }
+
+ throw new YangSyntaxErrorException(name, 0, 0, "Unknown YANG text type");
+ }
+
/**
* Extracts {@link YangModelDependencyInfo} from input stream
* containing YANG model.
--- /dev/null
+/*
+ * Copyright (c) 2014 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.yangtools.yang.parser.util;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Preconditions;
+
+import javax.annotation.Nonnull;
+
+import org.antlr.v4.runtime.ParserRuleContext;
+import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
+import org.opendaylight.yangtools.yang.model.repo.api.SchemaSourceRepresentation;
+import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
+import org.opendaylight.yangtools.yang.parser.impl.util.YangModelDependencyInfo;
+
+/**
+ * Abstract Syntax Tree representation of a schema source. This representation
+ * is internal to the YANG parser implementation, as it relies on ANTLR types.
+ *
+ * Instances of this representation are used for caching purposes, as they
+ * are a natural intermediate step in YANG text processing pipeline: the text
+ * has been successfully parsed, so we know it is syntactically correct. It also
+ * passes basic semantic validation and we were able to extract dependency
+ * information.
+ */
+public final class ASTSchemaSource implements SchemaSourceRepresentation {
+ private final YangModelDependencyInfo depInfo;
+ private final ParserRuleContext tree;
+ private final SourceIdentifier id;
+
+ private ASTSchemaSource(final @Nonnull SourceIdentifier id, @Nonnull final ParserRuleContext tree, final @Nonnull YangModelDependencyInfo depInfo) {
+ this.depInfo = Preconditions.checkNotNull(depInfo);
+ this.tree = Preconditions.checkNotNull(tree);
+ this.id = Preconditions.checkNotNull(id);
+ }
+
+ /**
+ * Create a new instance of AST representation for a abstract syntax tree,
+ * performing minimal semantic analysis to acquire dependency information.
+ *
+ * @param name YANG source name. Used only for error reporting.
+ * @param tree ANTLR abstract syntax tree
+ * @return A new representation instance.
+ * @throws YangSyntaxErrorException if we fail to extract dependency information.
+ */
+ public static final ASTSchemaSource create(final @Nonnull String name, final @Nonnull ParserRuleContext tree) throws YangSyntaxErrorException {
+ final YangModelDependencyInfo depInfo = YangModelDependencyInfo.fromAST(name, tree);
+ final SourceIdentifier id = new SourceIdentifier(depInfo.getName(), Optional.of(depInfo.getFormattedRevision()));
+ return new ASTSchemaSource(id, tree, depInfo);
+ }
+
+ @Override
+ public SourceIdentifier getIdentifier() {
+ return id;
+ }
+
+ @Override
+ public Class<? extends SchemaSourceRepresentation> getType() {
+ return ASTSchemaSource.class;
+ }
+
+ /**
+ * Return the underlying abstract syntax tree.
+ *
+ * @return Underlying AST.
+ */
+ public @Nonnull ParserRuleContext getAST() {
+ return tree;
+ }
+
+ /**
+ * Return the dependency information as extracted from the AST.
+ *
+ * FIXME: this method should be extracted into a public interface in the
+ * model.api.repo class, relying solely on model.api types.
+ *
+ * @return Dependency information.
+ */
+ public @Nonnull YangModelDependencyInfo getDependencyInformation() {
+ return depInfo;
+ }
+}
--- /dev/null
+/*
+ * Copyright (c) 2014 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.yangtools.yang.parser.util;
+
+import com.google.common.base.Function;
+import com.google.common.base.Preconditions;
+import com.google.common.util.concurrent.CheckedFuture;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListeningExecutorService;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.concurrent.Callable;
+
+import org.opendaylight.yangtools.antlrv4.code.gen.YangParser.YangContext;
+import org.opendaylight.yangtools.util.concurrent.ExceptionMapper;
+import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
+import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
+import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceTransformationException;
+import org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceTransformer;
+import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
+
+/**
+ * A {@link SchemaSourceTransformer} which handles translation of models from
+ * {@link YangTextSchemaSource} representation into {@link ASTSchemaSource}.
+ *
+ * While this class is currently used explicitly, its long-term purpose is to
+ * be registered with a {@link org.opendaylight.yangtools.yang.model.repo.spi.SchemaSourceRegistry}
+ * and be invoked on demand when the processing pipeline requests the
+ * ASTSchemaSource representation.
+ */
+public final class TextToASTTransformer implements SchemaSourceTransformer<YangTextSchemaSource, ASTSchemaSource> {
+ private static final Function<Exception, SchemaSourceTransformationException> MAPPER = new ExceptionMapper<SchemaSourceTransformationException>("Source transformation", SchemaSourceTransformationException.class) {
+ @Override
+ protected SchemaSourceTransformationException newWithCause(final String message, final Throwable cause) {
+ return new SchemaSourceTransformationException(message, cause);
+ }
+ };
+ private final ListeningExecutorService executor;
+
+ TextToASTTransformer(final ListeningExecutorService executor) {
+ this.executor = Preconditions.checkNotNull(executor);
+ }
+
+ @Override
+ public Class<YangTextSchemaSource> getInputRepresentation() {
+ return YangTextSchemaSource.class;
+ }
+
+ @Override
+ public Class<ASTSchemaSource> getOutputRepresentation() {
+ return ASTSchemaSource.class;
+ }
+
+ @Override
+ public CheckedFuture<ASTSchemaSource, SchemaSourceTransformationException> transformSchemaSource(final YangTextSchemaSource source) {
+ return Futures.makeChecked(executor.submit(new Callable<ASTSchemaSource>() {
+ @Override
+ public ASTSchemaSource call() throws IOException, YangSyntaxErrorException {
+ try (InputStream is = source.openStream()) {
+ final YangContext ctx = YangParserImpl.parseYangSource(is);
+ return ASTSchemaSource.create(source.getIdentifier().getName(), ctx);
+ }
+ }
+ }), MAPPER);
+ }
+
+ @Override
+ public int getCost() {
+ // We perform a direct translation, so the cost is 1.
+ return 1;
+ }
+}