Do not instantiate QNameModules needlessly
[yangtools.git] / yang / yang-parser-impl / src / main / java / org / opendaylight / yangtools / yang / parser / impl / 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.impl;
9
10 import java.util.ArrayList;
11 import java.util.List;
12 import javax.annotation.concurrent.Immutable;
13 import org.antlr.v4.runtime.tree.ParseTree;
14 import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser;
15 import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParserBaseListener;
16 import org.opendaylight.yangtools.yang.common.QName;
17 import org.opendaylight.yangtools.yang.common.YangConstants;
18 import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping;
19 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
20 import org.opendaylight.yangtools.yang.parser.spi.source.DeclarationInTextSource;
21 import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule;
22 import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinition;
23 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
24 import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
25 import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter;
26 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.TypeUtils;
27 import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.Utils;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
30
31 @Immutable
32 public class YangStatementParserListenerImpl extends YangStatementParserBaseListener {
33
34     private StatementWriter writer;
35     private final String sourceName;
36     private QNameToStatementDefinition stmtDef;
37     private PrefixToModule prefixes;
38     private final List<String> toBeSkipped = new ArrayList<>();
39     private boolean isType = false;
40     private static final Logger LOG = LoggerFactory.getLogger(YangStatementParserListenerImpl.class);
41
42     public YangStatementParserListenerImpl(final String sourceName) {
43         this.sourceName = sourceName;
44     }
45
46     public void setAttributes(final StatementWriter writer, final QNameToStatementDefinition stmtDef) {
47         this.writer = writer;
48         this.stmtDef = stmtDef;
49     }
50
51     public void setAttributes(final StatementWriter writer, final QNameToStatementDefinition stmtDef, final PrefixToModule prefixes) {
52         this.writer = writer;
53         this.stmtDef = stmtDef;
54         this.prefixes = prefixes;
55     }
56
57     @Override
58     public void enterStatement(final YangStatementParser.StatementContext ctx) {
59         final StatementSourceReference ref = DeclarationInTextSource.atPosition(sourceName, ctx.getText(), ctx
60                 .getStart().getLine(), ctx.getStart().getCharPositionInLine());
61         boolean action = true;
62         QName identifier;
63         for (int i = 0; i < ctx.getChildCount(); i++) {
64             ParseTree child = ctx.getChild(i);
65             if (child instanceof YangStatementParser.KeywordContext) {
66                 try {
67                     identifier = QName.create(YangConstants.RFC6020_YIN_MODULE,
68                             ((YangStatementParser.KeywordContext) child).children.get(0).getText());
69                     if (stmtDef != null && Utils.isValidStatementDefinition(prefixes, stmtDef, identifier) && toBeSkipped.isEmpty()) {
70                         if (identifier.equals(Rfc6020Mapping.TYPE.getStatementName())) {
71                             isType = true;
72                         } else {
73                             writer.startStatement(identifier, ref);
74                         }
75                     } else {
76                         if (writer.getPhase().equals(ModelProcessingPhase.FULL_DECLARATION)) {
77                             throw new IllegalArgumentException(identifier.getLocalName() + " is not a YANG statement " +
78                                     "or use of extension. Source: " + ref);
79                         } else {
80                             action = false;
81                             toBeSkipped.add(((YangStatementParser.KeywordContext) child).children.get(0).getText());
82                         }
83                     }
84                 } catch (SourceException e) {
85                     LOG.warn(e.getMessage(), e);
86                 }
87             } else if (child instanceof YangStatementParser.ArgumentContext) {
88                 try {
89                     final String argument = Utils.stringFromStringContext((YangStatementParser.ArgumentContext) child);
90                     if (isType) {
91                             if (TypeUtils.isYangTypeBodyStmtString(argument)) {
92                                 writer.startStatement(QName.create(YangConstants.RFC6020_YIN_MODULE, argument), ref);
93                             } else {
94                                 writer.startStatement(QName.create(YangConstants.RFC6020_YIN_MODULE, Rfc6020Mapping
95                                         .TYPE.getStatementName().getLocalName()), ref);
96                             }
97                         writer.argumentValue(argument, ref);
98                         isType = false;
99                     } else if (action) {
100                         writer.argumentValue(Utils.stringFromStringContext((YangStatementParser.ArgumentContext) child), ref);
101                     } else {
102                         action = true;
103                     }
104                 } catch (SourceException e) {
105                     LOG.warn(e.getMessage(), e);
106                 }
107             }
108
109         }
110     }
111
112     @Override
113     public void exitStatement(final YangStatementParser.StatementContext ctx) {
114         final StatementSourceReference ref = DeclarationInTextSource.atPosition(sourceName, ctx.getText(), ctx.getStart().getLine(), ctx
115                 .getStart().getCharPositionInLine());
116         for (int i = 0; i < ctx.getChildCount(); i++) {
117             ParseTree child = ctx.getChild(i);
118             if (child instanceof YangStatementParser.KeywordContext) {
119                 try {
120                     String statementName = ((YangStatementParser.KeywordContext) child).children.get(0).getText();
121                     QName identifier = QName.create(YangConstants.RFC6020_YIN_MODULE, statementName);
122                     if (stmtDef != null && Utils.isValidStatementDefinition(prefixes, stmtDef, identifier) && toBeSkipped.isEmpty()) {
123                         writer.endStatement(ref);
124                     }
125
126                     if (toBeSkipped.contains(statementName)) {
127                         toBeSkipped.remove(statementName);
128                     }
129                 } catch (SourceException e) {
130                     LOG.warn(e.getMessage(), e);
131                 }
132             }
133         }
134     }
135 }