2 * Copyright (c) 2017 Pantheon Technologies, s.r.o. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.yangtools.yang.parser.rfc7950.repo;
10 import static com.google.common.base.Preconditions.checkArgument;
12 import com.google.common.annotations.Beta;
13 import com.google.common.base.MoreObjects;
14 import com.google.common.base.Preconditions;
15 import com.google.common.collect.ImmutableList;
16 import java.io.IOException;
17 import java.io.InputStream;
18 import org.antlr.v4.runtime.CharStreams;
19 import org.antlr.v4.runtime.CommonTokenStream;
20 import org.antlr.v4.runtime.ParserRuleContext;
21 import org.antlr.v4.runtime.tree.ErrorNode;
22 import org.antlr.v4.runtime.tree.ParseTreeListener;
23 import org.antlr.v4.runtime.tree.ParseTreeWalker;
24 import org.antlr.v4.runtime.tree.TerminalNode;
25 import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementLexer;
26 import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser;
27 import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.StatementContext;
28 import org.opendaylight.yangtools.yang.common.YangVersion;
29 import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
30 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
31 import org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource;
32 import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
33 import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinition;
34 import org.opendaylight.yangtools.yang.parser.spi.source.StatementStreamSource;
35 import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter;
38 * This class represents implementation of StatementStreamSource in order to emit YANG statements using supplied
41 * @author Robert Varga
44 public final class YangStatementStreamSource implements StatementStreamSource {
45 private static final ParseTreeListener MAKE_IMMUTABLE_LISTENER = new ParseTreeListener() {
47 public void enterEveryRule(final ParserRuleContext ctx) {
52 public void exitEveryRule(final ParserRuleContext ctx) {
53 ctx.children = ctx.children == null ? ImmutableList.of() : ImmutableList.copyOf(ctx.children);
57 public void visitTerminal(final TerminalNode node) {
62 public void visitErrorNode(final ErrorNode node) {
67 private final SourceIdentifier identifier;
68 private final StatementContext context;
69 private final String sourceName;
71 private YangStatementStreamSource(final SourceIdentifier identifier, final StatementContext context,
72 final String sourceName) {
73 this.identifier = Preconditions.checkNotNull(identifier);
74 this.context = Preconditions.checkNotNull(context);
75 this.sourceName = sourceName;
79 * Create a {@link YangStatementStreamSource} for a {@link YangTextSchemaSource}.
81 * @param source YangTextSchemaSource, must not be null
82 * @return A new {@link YangStatementStreamSource}
83 * @throws IOException When we fail to read the source
84 * @throws YangSyntaxErrorException If the source fails basic parsing
86 public static YangStatementStreamSource create(final YangTextSchemaSource source) throws IOException,
87 YangSyntaxErrorException {
88 final StatementContext context;
89 try (InputStream stream = source.openStream()) {
90 context = parseYangSource(source.getIdentifier(), stream);
93 return new YangStatementStreamSource(source.getIdentifier(), context, source.getSymbolicName().orElse(null));
97 * Create a {@link YangStatementStreamSource} for a {@link ASTSchemaSource}.
99 * @param source YangTextSchemaSource, must not be null
100 * @return A new {@link YangStatementStreamSource}
102 public static YangStatementStreamSource create(final ASTSchemaSource source) {
103 final ParserRuleContext ast = source.getAST();
104 checkArgument(ast instanceof StatementContext,
105 "Unsupported context class %s for source %s", ast.getClass(), source.getIdentifier());
106 return create(source.getIdentifier(), (StatementContext) ast, source.getSymbolicName().orElse(null));
109 public static YangStatementStreamSource create(final SourceIdentifier identifier, final StatementContext context,
110 final String symbolicName) {
111 return new YangStatementStreamSource(identifier, context, symbolicName);
115 public void writePreLinkage(final StatementWriter writer, final QNameToStatementDefinition stmtDef) {
116 new StatementContextVisitor.Loose(sourceName, writer, stmtDef).visit(context);
120 public void writeLinkage(final StatementWriter writer, final QNameToStatementDefinition stmtDef,
121 final PrefixToModule preLinkagePrefixes) {
122 writeLinkage(writer, stmtDef, preLinkagePrefixes, YangVersion.VERSION_1);
126 public void writeLinkage(final StatementWriter writer, final QNameToStatementDefinition stmtDef,
127 final PrefixToModule preLinkagePrefixes, final YangVersion yangVersion) {
128 new StatementContextVisitor.Loose(sourceName, writer, stmtDef, preLinkagePrefixes, yangVersion).visit(context);
132 public void writeLinkageAndStatementDefinitions(final StatementWriter writer,
133 final QNameToStatementDefinition stmtDef, final PrefixToModule prefixes) {
134 writeLinkageAndStatementDefinitions(writer, stmtDef, prefixes, YangVersion.VERSION_1);
138 public void writeLinkageAndStatementDefinitions(final StatementWriter writer,
139 final QNameToStatementDefinition stmtDef, final PrefixToModule prefixes, final YangVersion yangVersion) {
140 new StatementContextVisitor.Loose(sourceName, writer, stmtDef, prefixes, yangVersion).visit(context);
144 public void writeFull(final StatementWriter writer, final QNameToStatementDefinition stmtDef,
145 final PrefixToModule prefixes) {
146 writeFull(writer, stmtDef, prefixes, YangVersion.VERSION_1);
150 public void writeFull(final StatementWriter writer, final QNameToStatementDefinition stmtDef,
151 final PrefixToModule prefixes, final YangVersion yangVersion) {
152 new StatementContextVisitor.Strict(sourceName, writer, stmtDef, prefixes, yangVersion).visit(context);
156 public SourceIdentifier getIdentifier() {
160 public ParserRuleContext getYangAST() {
164 private static StatementContext parseYangSource(final SourceIdentifier source, final InputStream stream)
165 throws IOException, YangSyntaxErrorException {
166 final YangStatementLexer lexer = new YangStatementLexer(CharStreams.fromStream(stream));
167 final CommonTokenStream tokens = new CommonTokenStream(lexer);
168 final YangStatementParser parser = new YangStatementParser(tokens);
169 //disconnect from console error output
170 parser.removeErrorListeners();
172 final YangErrorListener errorListener = new YangErrorListener(source);
173 parser.addErrorListener(errorListener);
175 final StatementContext result = parser.statement();
176 errorListener.validate();
178 // Walk the resulting tree and replace each children with an immutable list, lowering memory requirements
179 // and making sure the resulting tree will not get accidentally modified. An alternative would be to use
180 // org.antlr.v4.runtime.Parser.TrimToSizeListener, but that does not make the tree immutable.
181 ParseTreeWalker.DEFAULT.walk(MAKE_IMMUTABLE_LISTENER, result);
187 public String toString() {
188 return MoreObjects.toStringHelper(this).add("identifier", getIdentifier()).toString();