X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;f=yang%2Fyang-parser-impl%2Fsrc%2Fmain%2Fjava%2Forg%2Fopendaylight%2Fyangtools%2Fyang%2Fparser%2Fimpl%2FYangStatementParserListenerImpl.java;h=c20c2d1e179de4ea6ebe41caefa5ac1037e35ccb;hb=7afe82dabbbc39b0ecf52772f5b9a4eaf4c8dacd;hp=5da991b527a05b561303f73571a63dc1152c393c;hpb=ea32c2c6fac2ebe9d0e30c9c4e5279c5ef0d2314;p=yangtools.git diff --git a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YangStatementParserListenerImpl.java b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YangStatementParserListenerImpl.java index 5da991b527..c20c2d1e17 100644 --- a/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YangStatementParserListenerImpl.java +++ b/yang/yang-parser-impl/src/main/java/org/opendaylight/yangtools/yang/parser/impl/YangStatementParserListenerImpl.java @@ -7,9 +7,10 @@ */ package org.opendaylight.yangtools.yang.parser.impl; -import com.google.common.base.Preconditions; import com.google.common.base.Verify; +import java.util.ArrayDeque; import java.util.ArrayList; +import java.util.Deque; import java.util.List; import javax.annotation.concurrent.Immutable; import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.ArgumentContext; @@ -17,8 +18,9 @@ import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.KeywordCo import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParser.StatementContext; import org.opendaylight.yangtools.antlrv4.code.gen.YangStatementParserBaseListener; import org.opendaylight.yangtools.yang.common.QName; +import org.opendaylight.yangtools.yang.common.QNameModule; import org.opendaylight.yangtools.yang.common.YangConstants; -import org.opendaylight.yangtools.yang.model.api.Rfc6020Mapping; +import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition; import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase; import org.opendaylight.yangtools.yang.parser.spi.source.DeclarationInTextSource; import org.opendaylight.yangtools.yang.parser.spi.source.PrefixToModule; @@ -26,16 +28,20 @@ import org.opendaylight.yangtools.yang.parser.spi.source.QNameToStatementDefinit import org.opendaylight.yangtools.yang.parser.spi.source.SourceException; import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference; import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter; -import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.TypeUtils; import org.opendaylight.yangtools.yang.parser.stmt.rfc6020.Utils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; @Immutable public class YangStatementParserListenerImpl extends YangStatementParserBaseListener { - private static final Logger LOG = LoggerFactory.getLogger(YangStatementParserListenerImpl.class); + private static final class Counter { + private int value = 0; + + int getAndIncrement() { + return value++; + } + } private final List toBeSkipped = new ArrayList<>(); + private final Deque counters = new ArrayDeque<>(); private final String sourceName; private QNameToStatementDefinition stmtDef; private PrefixToModule prefixes; @@ -48,47 +54,41 @@ public class YangStatementParserListenerImpl extends YangStatementParserBaseList public void setAttributes(final StatementWriter writer, final QNameToStatementDefinition stmtDef) { this.writer = writer; this.stmtDef = stmtDef; + initCounters(); } - public void setAttributes(final StatementWriter writer, final QNameToStatementDefinition stmtDef, final PrefixToModule prefixes) { + public void setAttributes(final StatementWriter writer, final QNameToStatementDefinition stmtDef, + final PrefixToModule prefixes) { this.writer = writer; this.stmtDef = stmtDef; this.prefixes = prefixes; + initCounters(); + } + + private void initCounters() { + counters.clear(); + counters.push(new Counter()); } @Override public void enterStatement(final StatementContext ctx) { final StatementSourceReference ref = DeclarationInTextSource.atPosition(sourceName, ctx - .getStart().getLine(), ctx.getStart().getCharPositionInLine()); - final KeywordContext keywordCtx = Verify.verifyNotNull(ctx.getChild(KeywordContext.class, 0)); - final ArgumentContext argumentCtx = ctx.getChild(ArgumentContext.class, 0); - final String keywordTxt = keywordCtx.getText(); - - final QName identifier = QName.create(YangConstants.RFC6020_YIN_MODULE, keywordTxt); - final QName validStatementDefinition = Utils.getValidStatementDefinition(prefixes, stmtDef, identifier); - if (stmtDef != null && validStatementDefinition != null && toBeSkipped.isEmpty()) { - final String argument = argumentCtx != null ? Utils.stringFromStringContext(argumentCtx) : null; - // FIXME: Refactor/clean up this special case - if (identifier.equals(Rfc6020Mapping.TYPE.getStatementName())) { - Preconditions.checkArgument(argument != null); - if (TypeUtils.isYangTypeBodyStmtString(argument)) { - writer.startStatement(QName.create(YangConstants.RFC6020_YIN_MODULE, argument), ref); - } else { - writer.startStatement(QName.create(YangConstants.RFC6020_YIN_MODULE, Rfc6020Mapping - .TYPE.getStatementName().getLocalName()), ref); - } - writer.argumentValue(argument, ref); - } else { - writer.startStatement(validStatementDefinition, ref); - if (argument != null) { - writer.argumentValue(argument, ref); - } - } - } else { - Preconditions.checkArgument(writer.getPhase() != ModelProcessingPhase.FULL_DECLARATION, - "%s is not a YANG statement or use of extension. Source: %s", identifier.getLocalName(), ref); + .getStart().getLine(), ctx.getStart().getCharPositionInLine()); + final String keywordTxt = Verify.verifyNotNull(ctx.getChild(KeywordContext.class, 0)).getText(); + final QName validStatementDefinition = getValidStatementDefinition(prefixes, stmtDef, keywordTxt); + + final int childId = counters.peek().getAndIncrement(); + counters.push(new Counter()); + if (stmtDef == null || validStatementDefinition == null || !toBeSkipped.isEmpty()) { + SourceException.throwIf(writer.getPhase() == ModelProcessingPhase.FULL_DECLARATION, ref, + "%s is not a YANG statement or use of extension.", keywordTxt); toBeSkipped.add(keywordTxt); + return; } + + final ArgumentContext argumentCtx = ctx.getChild(ArgumentContext.class, 0); + final String argument = argumentCtx != null ? Utils.stringFromStringContext(argumentCtx) : null; + writer.startStatement(childId, validStatementDefinition, argument, ref); } @Override @@ -96,19 +96,62 @@ public class YangStatementParserListenerImpl extends YangStatementParserBaseList final StatementSourceReference ref = DeclarationInTextSource.atPosition( sourceName, ctx.getStart().getLine(), ctx.getStart().getCharPositionInLine()); - try { - KeywordContext keyword = ctx.getChild(KeywordContext.class, 0); - String statementName = keyword.getText(); - QName identifier = QName.create(YangConstants.RFC6020_YIN_MODULE, statementName); - if (stmtDef != null && Utils.getValidStatementDefinition(prefixes, stmtDef, identifier) != null - && toBeSkipped.isEmpty()) { - writer.endStatement(ref); - } - - // No-op if the statement is not on the list - toBeSkipped.remove(statementName); - } catch (SourceException e) { - LOG.warn(e.getMessage(), e); + KeywordContext keyword = ctx.getChild(KeywordContext.class, 0); + String statementName = keyword.getText(); + if (stmtDef != null && getValidStatementDefinition(prefixes, stmtDef, statementName) != null + && toBeSkipped.isEmpty()) { + writer.endStatement(ref); } + + // No-op if the statement is not on the list + toBeSkipped.remove(statementName); + counters.pop(); + } + + /** + * Based on identifier read from source and collections of relevant prefixes and statement definitions mappings + * provided for actual phase, method resolves and returns valid QName for declared statement to be written. + * This applies to any declared statement, including unknown statements. + * + * @param prefixes collection of all relevant prefix mappings supplied for actual parsing phase + * @param stmtDef collection of all relevant statement definition mappings provided for actual parsing phase + * @param keywordText statement keyword text to parse from source + * @return valid QName for declared statement to be written, or null + */ + private static QName getValidStatementDefinition(final PrefixToModule prefixes, + final QNameToStatementDefinition stmtDef, final String keywordText) { + final int firstColon = keywordText.indexOf(':'); + if (firstColon == -1) { + final StatementDefinition statementDefinition = stmtDef.get( + new QName(YangConstants.RFC6020_YIN_NAMESPACE, keywordText)); + return statementDefinition != null ? statementDefinition.getStatementName() : null; + } + + final int secondColon = keywordText.indexOf(':', firstColon + 1); + if (secondColon != -1) { + // Malformed string + return null; + } + if (prefixes == null) { + // No prefixes to look up from + return null; + } + + final String prefix = keywordText.substring(0, firstColon); + final QNameModule qNameModule = prefixes.get(prefix); + if (qNameModule == null) { + // Failed to look the namespace + return null; + } + + final String localName = keywordText.substring(firstColon + 1); + final StatementDefinition foundStmtDef; + if (prefixes.isPreLinkageMap()) { + foundStmtDef = stmtDef.getByNamespaceAndLocalName(qNameModule.getNamespace(), localName); + } else { + foundStmtDef = stmtDef.get(QName.create(qNameModule, localName)); + } + + return foundStmtDef != null ? foundStmtDef.getStatementName() : null; } }