Cleanup unrecognized statement wrapping 35/95835/1
authorRobert Varga <robert.varga@pantheon.tech>
Mon, 19 Apr 2021 17:03:19 +0000 (19:03 +0200)
committerRobert Varga <robert.varga@pantheon.tech>
Mon, 19 Apr 2021 17:08:38 +0000 (19:08 +0200)
reactor/rfc7950 interaction around inner statements is a bit hacky
in that we end up performing two unrelated semantic checks before
dispatching.

As it turns out, though, this only a special case of a more widely
applicable pattern, where the parent statement chooses to wrap its
children in a different semantic support.

Separating this out makes the intent clear, as it ends up being an
extension trait to StatementSupport on the side of yang-parser-reactor
and has a well-understood anchor in UnrecognizedStatementSupport.

Change-Id: I3b64f58239e22affccc02921efd8cd70b411d7c1
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SourceSpecificContext.java
yang/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementDefinitionContext.java
yang/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/extension/UnrecognizedStatementSupport.java
yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/OverrideChildStatementSupport.java [new file with mode: 0644]
yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StatementSupport.java

index c32bab41ab78b8451b7812a3c2b865e38933ebba..79d8e3af5422567f96e75d80d82375a95b86ebcb 100644 (file)
@@ -7,7 +7,6 @@
  */
 package org.opendaylight.yangtools.yang.parser.stmt.reactor;
 
-import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
 import static com.google.common.base.Verify.verify;
 import static com.google.common.base.Verify.verifyNotNull;
@@ -29,7 +28,6 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.common.QNameModule;
 import org.opendaylight.yangtools.yang.common.XMLNamespace;
 import org.opendaylight.yangtools.yang.common.YangVersion;
-import org.opendaylight.yangtools.yang.model.api.stmt.UnrecognizedStatement;
 import org.opendaylight.yangtools.yang.model.repo.api.SourceIdentifier;
 import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelActionBuilder;
@@ -112,14 +110,8 @@ final class SourceSpecificContext implements NamespaceStorageNode, NamespaceBeha
                     globalContext.putModelDefinedStatementDefinition(name, def);
                 }
             }
-        } else if (current != null && current.producesDeclared(UnrecognizedStatement.class)) {
-            /*
-             * This code wraps statements encountered inside an extension so
-             * they do not get confused with regular statements.
-             */
-            def = checkNotNull(current.definition().getAsUnknownStatementDefinition(def),
-                    "Unable to create unknown statement definition of yang statement %s in unknown statement %s", def,
-                    current);
+        } else if (current != null) {
+            def = current.definition().overrideDefinition(def);
         }
 
         if (InferenceException.throwIfNull(def, ref, "Statement %s does not have type mapping defined.", name)
index 07c63f53e9950efa6374e89cf15b658b48e277d0..32103a339c3e310709681f3d3a3a20f145730bac 100644 (file)
@@ -22,6 +22,7 @@ import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ImplicitParentAwareStatementSupport;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
+import org.opendaylight.yangtools.yang.parser.spi.meta.OverrideChildStatementSupport;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ParserNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementFactory;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
@@ -125,24 +126,30 @@ final class StatementDefinitionContext<A, D extends DeclaredStatement<A>, E exte
         return support.hasArgumentSpecificSupports();
     }
 
-    // FIXME: 7.0.0: do we still need this?
-    StatementDefinitionContext<?, ?, ?> getAsUnknownStatementDefinition(
-            final StatementDefinitionContext<?, ?, ?> yangStmtDef) {
+    @NonNull StatementDefinitionContext<?, ?, ?> overrideDefinition(
+            final @NonNull StatementDefinitionContext<?, ?, ?> def) {
+        if (!(support instanceof OverrideChildStatementSupport)) {
+            return def;
+        }
+
         if (unknownStmtDefsOfYangStmts != null) {
-            final StatementDefinitionContext<?, ?, ?> existing = unknownStmtDefsOfYangStmts.get(yangStmtDef);
+            final StatementDefinitionContext<?, ?, ?> existing = unknownStmtDefsOfYangStmts.get(def);
             if (existing != null) {
                 return existing;
             }
         } else {
-            unknownStmtDefsOfYangStmts = new HashMap<>();
+            unknownStmtDefsOfYangStmts = new HashMap<>(4);
         }
 
-        @SuppressWarnings("unchecked")
-        final StatementDefinitionContext<?, ?, ?> ret = support.getUnknownStatementDefinitionOf(
-            yangStmtDef.getPublicView()).map(StatementDefinitionContext::new).orElse(null);
-        if (ret != null) {
-            unknownStmtDefsOfYangStmts.put(yangStmtDef, ret);
+        final StatementSupport<?, ?, ?> override =
+            ((OverrideChildStatementSupport) support).statementDefinitionOverrideOf(def.getPublicView());
+        final StatementDefinitionContext<?, ?, ?> ret;
+        if (override != null) {
+            ret = new StatementDefinitionContext<>(override);
+        } else {
+            ret = def;
         }
+        unknownStmtDefsOfYangStmts.put(def, ret);
         return ret;
     }
 }
index d092c896c1e09746b4f3b3160102a9ba7333c841..f669707ce1dc9bb3af80be4f98d6a4e7a735eb32 100644 (file)
@@ -18,13 +18,14 @@ import org.opendaylight.yangtools.yang.model.api.stmt.UnrecognizedStatement;
 import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractStatementSupport;
 import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current;
 import org.opendaylight.yangtools.yang.parser.spi.meta.InferenceException;
-import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
+import org.opendaylight.yangtools.yang.parser.spi.meta.OverrideChildStatementSupport;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext.Mutable;
 import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator;
 
 final class UnrecognizedStatementSupport
-        extends AbstractStatementSupport<Object, UnrecognizedStatement, UnrecognizedEffectiveStatement> {
+        extends AbstractStatementSupport<Object, UnrecognizedStatement, UnrecognizedEffectiveStatement>
+        implements OverrideChildStatementSupport {
     UnrecognizedStatementSupport(final StatementDefinition publicDefinition) {
         // We have no idea about the statement's semantics, hence there should be noone interested in its semantics.
         // Nevertheless it may be of interest for various hacks to understand there was an extension involved.
@@ -37,20 +38,23 @@ final class UnrecognizedStatementSupport
     }
 
     @Override
-    public Optional<StatementSupport<?, ?, ?>> getUnknownStatementDefinitionOf(
-            final StatementDefinition yangStmtDef) {
+    public UnrecognizedStatementSupport statementDefinitionOverrideOf(final StatementDefinition childDef) {
+        /*
+         * This code wraps statements encountered inside an extension so they do not get confused with regular
+         * statements.
+         */
         final QName baseQName = getStatementName();
-        final QName statementName = QName.create(baseQName, yangStmtDef.getStatementName().getLocalName());
+        final QName statementName = QName.create(baseQName, childDef.getStatementName().getLocalName());
 
         final ModelDefinedStatementDefinition def;
-        final Optional<ArgumentDefinition> optArgDef = yangStmtDef.getArgumentDefinition();
+        final Optional<ArgumentDefinition> optArgDef = childDef.getArgumentDefinition();
         if (optArgDef.isPresent()) {
             final ArgumentDefinition argDef = optArgDef.get();
             def = new ModelDefinedStatementDefinition(statementName, argDef.getArgumentName(), argDef.isYinElement());
         } else {
             def = new ModelDefinedStatementDefinition(statementName);
         }
-        return Optional.of(new UnrecognizedStatementSupport(def));
+        return new UnrecognizedStatementSupport(def);
     }
 
     @Override
diff --git a/yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/OverrideChildStatementSupport.java b/yang/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/OverrideChildStatementSupport.java
new file mode 100644 (file)
index 0000000..8a7618c
--- /dev/null
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2021 PANTHEON.tech, s.r.o. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+package org.opendaylight.yangtools.yang.parser.spi.meta;
+
+import com.google.common.annotations.Beta;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
+
+/**
+ * An additional trait for {@link StatementSupport}, allowing a parent statement to override the support for a child
+ * statement.
+ */
+@Beta
+public interface OverrideChildStatementSupport {
+    /**
+     * Returns unknown statement form of a regular YANG statement supplied as a parameter to the method.
+     *
+     * @param childDef statement definition of a regular YANG statement
+     * @return Optional of unknown statement form of a regular YANG statement, or {@code null} if it should not be
+     *         overridden.
+     */
+    @Nullable StatementSupport<?, ?, ?> statementDefinitionOverrideOf(@NonNull StatementDefinition childDef);
+}
index 464d9e5128f5cee44ff2d583c0a944f117f6a0dc..6ea8fe59a273471778859c7ca9be9a69cc017159 100644 (file)
@@ -408,18 +408,6 @@ public abstract class StatementSupport<A, D extends DeclaredStatement<A>, E exte
         return rawArgument;
     }
 
-    /**
-     * Returns unknown statement form of a regular YANG statement supplied as a parameter to the method. Default
-     * implementation does nothing.
-     *
-     * @param yangStmtDef statement definition of a regular YANG statement
-     * @return Optional of unknown statement form of a regular YANG statement or empty() if it is not supported by this
-     *         statement support
-     */
-    public Optional<StatementSupport<?, ?, ?>> getUnknownStatementDefinitionOf(final StatementDefinition yangStmtDef) {
-        return Optional.empty();
-    }
-
     /**
      * Returns true if this statement support and all its substatements ignore if-feature statements (e.g. yang-data
      * extension defined in <a href="https://tools.ietf.org/html/rfc8040#section-8">RFC 8040</a>). Default