Fix checkstyle issues reported by odlparent-3.0.0's checkstyle
[yangtools.git] / yang / yang-parser-rfc7950 / src / main / java / org / opendaylight / yangtools / yang / parser / rfc7950 / repo / YangStatementParserListenerImpl.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. 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 com.google.common.base.Verify;
11 import java.util.ArrayDeque;
12 import java.util.ArrayList;
13 import java.util.Deque;
14 import java.util.List;
15 import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.ArgumentContext;
16 import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.KeywordContext;
17 import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.StatementContext;
18 import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParserBaseListener;
19 import org.opendaylight.yangtools.yang.common.QName;
20 import org.opendaylight.yangtools.yang.common.QNameModule;
21 import org.opendaylight.yangtools.yang.common.YangConstants;
22 import org.opendaylight.yangtools.yang.common.YangVersion;
23 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
24 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
25 import org.opendaylight.yangtools.yang.parser.spi.source.DeclarationInTextSource;
26 import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
27 import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinition;
28 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
29 import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
30 import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter;
31
32 final class YangStatementParserListenerImpl extends YangStatementParserBaseListener {
33     private static final class Counter {
34         private int value = 0;
35
36         int getAndIncrement() {
37             return value++;
38         }
39     }
40
41     private final List<String> toBeSkipped = new ArrayList<>();
42     private final Deque<Counter> counters = new ArrayDeque<>();
43     private final String sourceName;
44     private QNameToStatementDefinition stmtDef;
45     private PrefixToModule prefixes;
46     private StatementWriter writer;
47     private YangVersion yangVersion;
48
49     YangStatementParserListenerImpl(final String sourceName) {
50         this.sourceName = sourceName;
51     }
52
53     @SuppressWarnings("checkstyle:hiddenField")
54     public void setAttributes(final StatementWriter writer, final QNameToStatementDefinition stmtDef) {
55         this.writer = writer;
56         this.stmtDef = stmtDef;
57         initCounters();
58     }
59
60     @SuppressWarnings("checkstyle:hiddenField")
61     public void setAttributes(final StatementWriter writer, final QNameToStatementDefinition stmtDef,
62             final PrefixToModule prefixes) {
63         this.writer = writer;
64         this.stmtDef = stmtDef;
65         this.prefixes = prefixes;
66         initCounters();
67     }
68
69     @SuppressWarnings("checkstyle:hiddenField")
70     public void setAttributes(final StatementWriter writer, final QNameToStatementDefinition stmtDef,
71             final PrefixToModule prefixes, final YangVersion yangVersion) {
72         this.yangVersion = yangVersion;
73         setAttributes(writer, stmtDef, prefixes);
74     }
75
76     private void initCounters() {
77         counters.clear();
78         counters.push(new Counter());
79     }
80
81     @Override
82     public void enterStatement(final StatementContext ctx) {
83         final StatementSourceReference ref = DeclarationInTextSource.atPosition(sourceName, ctx.getStart().getLine(),
84                 ctx.getStart().getCharPositionInLine());
85         final String keywordTxt = Verify.verifyNotNull(ctx.getChild(KeywordContext.class, 0)).getText();
86         final QName validStatementDefinition = getValidStatementDefinition(prefixes, stmtDef, keywordTxt, ref);
87
88         final int childId = counters.peek().getAndIncrement();
89         counters.push(new Counter());
90         if (stmtDef == null || validStatementDefinition == null || !toBeSkipped.isEmpty()) {
91             SourceException.throwIf(writer.getPhase() == ModelProcessingPhase.FULL_DECLARATION, ref,
92                     "%s is not a YANG statement or use of extension.", keywordTxt);
93             toBeSkipped.add(keywordTxt);
94             return;
95         }
96
97         final ArgumentContext argumentCtx = ctx.getChild(ArgumentContext.class, 0);
98         final String argument = argumentCtx != null
99                 ? ArgumentContextUtils.stringFromStringContext(argumentCtx, yangVersion, ref) : null;
100         writer.startStatement(childId, validStatementDefinition, argument, ref);
101     }
102
103     @Override
104     public void exitStatement(final StatementContext ctx) {
105         final StatementSourceReference ref = DeclarationInTextSource.atPosition(
106             sourceName, ctx.getStart().getLine(), ctx.getStart().getCharPositionInLine());
107
108         final KeywordContext keyword = ctx.getChild(KeywordContext.class, 0);
109         final String statementName = keyword.getText();
110         if (stmtDef != null && getValidStatementDefinition(prefixes, stmtDef, statementName, ref) != null
111                 && toBeSkipped.isEmpty()) {
112             writer.endStatement(ref);
113         }
114
115         // No-op if the statement is not on the list
116         toBeSkipped.remove(statementName);
117         counters.pop();
118     }
119
120     /**
121      * Based on identifier read from source and collections of relevant prefixes and statement definitions mappings
122      * provided for actual phase, method resolves and returns valid QName for declared statement to be written.
123      * This applies to any declared statement, including unknown statements.
124      *
125      * @param prefixes collection of all relevant prefix mappings supplied for actual parsing phase
126      * @param stmtDef collection of all relevant statement definition mappings provided for actual parsing phase
127      * @param keywordText statement keyword text to parse from source
128      * @param ref Source reference
129      * @return valid QName for declared statement to be written, or null
130      */
131     private static QName getValidStatementDefinition(final PrefixToModule prefixes,
132             final QNameToStatementDefinition stmtDef, final String keywordText, final StatementSourceReference ref) {
133         final int firstColon = keywordText.indexOf(':');
134         if (firstColon == -1) {
135             final StatementDefinition statementDefinition = stmtDef.get(
136                 QName.create(YangConstants.RFC6020_YIN_NAMESPACE, keywordText));
137             return statementDefinition != null ? statementDefinition.getStatementName() : null;
138         }
139
140         SourceException.throwIf(firstColon == keywordText.length() - 1
141                 || keywordText.indexOf(':', firstColon + 1) != -1, ref, "Malformed statement '%s'", keywordText);
142
143         if (prefixes == null) {
144             // No prefixes to look up from
145             return null;
146         }
147
148         final String prefix = keywordText.substring(0, firstColon);
149         final QNameModule qNameModule = prefixes.get(prefix);
150         if (qNameModule == null) {
151             // Failed to look the namespace
152             return null;
153         }
154
155         final String localName = keywordText.substring(firstColon + 1);
156         final StatementDefinition foundStmtDef;
157         if (prefixes.isPreLinkageMap()) {
158             foundStmtDef = stmtDef.getByNamespaceAndLocalName(qNameModule.getNamespace(), localName);
159         } else {
160             foundStmtDef = stmtDef.get(QName.create(qNameModule, localName));
161         }
162
163         return foundStmtDef != null ? foundStmtDef.getStatementName() : null;
164     }
165 }