Deprecate PrefixToModule.isPreLinkageMap()
[yangtools.git] / yang / yang-parser-rfc7950 / src / main / java / org / opendaylight / yangtools / yang / parser / rfc7950 / repo / StatementContextVisitor.java
1 /*
2  * Copyright (c) 2018 Pantheon Technologies, s.r.o. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.yangtools.yang.parser.rfc7950.repo;
9
10 import static com.google.common.base.Verify.verifyNotNull;
11 import static java.util.Objects.requireNonNull;
12
13 import org.antlr.v4.runtime.tree.ParseTree;
14 import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.ArgumentContext;
15 import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.KeywordContext;
16 import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.StatementContext;
17 import org.opendaylight.yangtools.yang.common.QName;
18 import org.opendaylight.yangtools.yang.common.QNameModule;
19 import org.opendaylight.yangtools.yang.common.YangConstants;
20 import org.opendaylight.yangtools.yang.common.YangVersion;
21 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
22 import org.opendaylight.yangtools.yang.parser.spi.source.DeclarationInTextSource;
23 import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
24 import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinition;
25 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
26 import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
27 import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter;
28
29 class StatementContextVisitor {
30     private final QNameToStatementDefinition stmtDef;
31     private final StatementWriter writer;
32     private final YangVersion yangVersion;
33     private final PrefixToModule prefixes;
34     private final String sourceName;
35
36     StatementContextVisitor(final String sourceName, final StatementWriter writer,
37             final QNameToStatementDefinition stmtDef, final PrefixToModule prefixes, final YangVersion yangVersion) {
38         this.writer = requireNonNull(writer);
39         this.stmtDef = requireNonNull(stmtDef);
40         this.yangVersion = requireNonNull(yangVersion);
41         this.sourceName = sourceName;
42         this.prefixes = prefixes;
43     }
44
45     void visit(final StatementContext context) {
46         processStatement(0, context);
47     }
48
49     /**
50      * Based on identifier read from source and collections of relevant prefixes and statement definitions mappings
51      * provided for actual phase, method resolves and returns valid QName for declared statement to be written.
52      * This applies to any declared statement, including unknown statements.
53      *
54      * @param prefixes collection of all relevant prefix mappings supplied for actual parsing phase
55      * @param stmtDef collection of all relevant statement definition mappings provided for actual parsing phase
56      * @param keywordText statement keyword text to parse from source
57      * @param ref Source reference
58      * @return valid QName for declared statement to be written, or null
59      */
60     QName getValidStatementDefinition(final String keywordText, final StatementSourceReference ref) {
61         final int firstColon = keywordText.indexOf(':');
62         if (firstColon == -1) {
63             final StatementDefinition def = stmtDef.get(QName.create(YangConstants.RFC6020_YIN_NAMESPACE, keywordText));
64             return def != null ? def.getStatementName() : null;
65         }
66
67         SourceException.throwIf(firstColon == keywordText.length() - 1
68                 || keywordText.indexOf(':', firstColon + 1) != -1, ref, "Malformed statement '%s'", keywordText);
69
70         if (prefixes == null) {
71             // No prefixes to look up from
72             return null;
73         }
74
75         final String prefix = keywordText.substring(0, firstColon);
76         final QNameModule qNameModule = prefixes.get(prefix);
77         if (qNameModule == null) {
78             // Failed to look the namespace
79             return null;
80         }
81
82         final String localName = keywordText.substring(firstColon + 1);
83         final StatementDefinition foundStmtDef = resolveStatement(qNameModule, localName);
84         return foundStmtDef != null ? foundStmtDef.getStatementName() : null;
85     }
86
87     StatementDefinition resolveStatement(final QNameModule module, final String localName) {
88         return stmtDef.get(QName.create(module, localName));
89     }
90
91     private void processStatement(final int myOffset, final StatementContext ctx) {
92         final String keywordTxt = verifyNotNull(ctx.getChild(KeywordContext.class, 0)).getText();
93         final StatementSourceReference ref = DeclarationInTextSource.atPosition(sourceName, ctx.getStart().getLine(),
94             ctx.getStart().getCharPositionInLine());
95         final QName def = getValidStatementDefinition(keywordTxt, ref);
96         if (def == null) {
97             return;
98         }
99
100         final ArgumentContext argumentCtx = ctx.getChild(ArgumentContext.class, 0);
101         final String argument = argumentCtx == null ? null
102                 : ArgumentContextUtils.stringFromStringContext(argumentCtx, yangVersion, ref);
103         writer.startStatement(myOffset, def, argument, ref);
104
105         if (ctx.children != null) {
106             int childOffset = 0;
107             for (ParseTree s : ctx.children) {
108                 if (s instanceof StatementContext) {
109                     processStatement(childOffset++, (StatementContext) s);
110                 }
111             }
112         }
113
114         writer.endStatement(ref);
115     }
116 }