Rework undeclared statement definition 55/98955/16
authorRobert Varga <robert.varga@pantheon.tech>
Mon, 13 Dec 2021 01:29:52 +0000 (02:29 +0100)
committerRobert Varga <robert.varga@pantheon.tech>
Wed, 15 Dec 2021 12:20:33 +0000 (13:20 +0100)
Statements which are created without a corresponding declaration should
not have a DeclaredStatement footprint. Unfortunately our
createEffective() expect a DeclaredStatement to be present.

This patch adds another, explicit, avenue to create an
EffectiveStatement without having its DeclaredStatement (and
rawArgument).

We then use this facility to provide our usual
Undeclared*EffectiveStatements.

JIRA: YANGTOOLS-1372
Change-Id: I6fb5874d720cbf3a139890824c33fddde7196946
Signed-off-by: Robert Varga <robert.varga@pantheon.tech>
35 files changed:
model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/EffectiveStatements.java
model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/ImplicitStatements.java [deleted file]
model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/UndeclaredStatements.java [new file with mode: 0644]
model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/impl/decl/EmptyCaseStatement.java
model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/impl/decl/EmptyInputStatement.java
model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/impl/decl/EmptyOutputStatement.java
model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/impl/decl/EmptyUndeclaredCaseStatement.java [deleted file]
model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/impl/decl/EmptyUndeclaredInputStatement.java [deleted file]
model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/impl/decl/EmptyUndeclaredOutputStatement.java [deleted file]
model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/impl/decl/RegularCaseStatement.java
model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/impl/decl/RegularInputStatement.java
model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/impl/decl/RegularOutputStatement.java
model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/impl/decl/RegularUndeclaredCaseStatement.java [deleted file]
model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/impl/decl/RegularUndeclaredInputStatement.java [deleted file]
model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/impl/decl/RegularUndeclaredOutputStatement.java [deleted file]
parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/AbstractResumedStatement.java
parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/ForwardingUndeclaredCurrent.java [new file with mode: 0644]
parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/InferredStatementContext.java
parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/OriginalStmtCtx.java [new file with mode: 0644]
parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/ReactorStmtCtx.java
parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/ReplicaStatementContext.java
parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementContextBase.java
parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/StatementMap.java
parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/SubstatementContext.java
parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/UndeclaredStmtCtx.java [new file with mode: 0644]
parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/meta/AbstractImplicitStatementSupport.java
parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/meta/AbstractOperationContainerStatementSupport.java
parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/meta/ActionStatementSupport.java
parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/meta/CaseStatementSupport.java
parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/meta/InputStatementSupport.java
parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/meta/OutputStatementSupport.java
parser/yang-parser-rfc7950/src/main/java/org/opendaylight/yangtools/yang/parser/rfc7950/stmt/meta/RpcStatementSupport.java
parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/EffectiveStmtCtx.java
parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/StmtContext.java
parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/UndeclaredStatementFactory.java [new file with mode: 0644]

index b18c7c591a61f25732215689606bc2ca3bc4df47..0aac30f91b4c5b90debe6052bb0a1e754e16ebe7 100644 (file)
@@ -279,7 +279,7 @@ import org.opendaylight.yangtools.yang.model.ri.stmt.impl.eff.UndeclaredOutputEf
 import org.opendaylight.yangtools.yang.model.spi.meta.SubstatementIndexingException;
 
 /**
- * Static entry point to instantiating {@link EffectiveStatement} covered in the {@code RFC7950} metamodel.
+ * Static entry point to instantiating declared {@link EffectiveStatement} covered in the {@code RFC7950} metamodel.
  */
 @Beta
 @NonNullByDefault
@@ -376,11 +376,6 @@ public final class EffectiveStatements {
         }
     }
 
-    public static CaseEffectiveStatement createCase(final QName argument, final int flags,
-            final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
-        return new UndeclaredCaseEffectiveStatement(substatements, argument, flags);
-    }
-
     public static CaseEffectiveStatement createCase(final CaseStatement declared, final QName argument,
             final int flags, final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
         return new DeclaredCaseEffectiveStatement(declared, substatements, argument, flags);
@@ -550,12 +545,6 @@ public final class EffectiveStatements {
         }
     }
 
-    public static InputEffectiveStatement createInput(final QName argument, final int flags,
-            final ImmutableList<? extends EffectiveStatement<?, ?>> substatements)
-            throws SubstatementIndexingException {
-        return new UndeclaredInputEffectiveStatement(substatements, argument, flags);
-    }
-
     public static InputEffectiveStatement createInput(final InputStatement declared, final QName argument,
             final int flags, final ImmutableList<? extends EffectiveStatement<?, ?>> substatements)
                 throws SubstatementIndexingException {
@@ -711,12 +700,6 @@ public final class EffectiveStatements {
         }
     }
 
-    public static OutputEffectiveStatement createOutput(final QName argument, final int flags,
-            final ImmutableList<? extends EffectiveStatement<?, ?>> substatements)
-            throws SubstatementIndexingException {
-        return new UndeclaredOutputEffectiveStatement(substatements, argument, flags);
-    }
-
     public static OutputEffectiveStatement createOutput(final OutputStatement declared, final QName argument,
             final int flags, final ImmutableList<? extends EffectiveStatement<?, ?>> substatements)
                 throws SubstatementIndexingException {
diff --git a/model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/ImplicitStatements.java b/model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/ImplicitStatements.java
deleted file mode 100644 (file)
index 3fc444c..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (c) 2020 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.model.ri.stmt;
-
-import com.google.common.annotations.Beta;
-import com.google.common.collect.ImmutableList;
-import org.eclipse.jdt.annotation.NonNullByDefault;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.CaseStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.InputStatement;
-import org.opendaylight.yangtools.yang.model.api.stmt.OutputStatement;
-import org.opendaylight.yangtools.yang.model.ri.stmt.impl.decl.EmptyUndeclaredCaseStatement;
-import org.opendaylight.yangtools.yang.model.ri.stmt.impl.decl.EmptyUndeclaredInputStatement;
-import org.opendaylight.yangtools.yang.model.ri.stmt.impl.decl.EmptyUndeclaredOutputStatement;
-import org.opendaylight.yangtools.yang.model.ri.stmt.impl.decl.RegularUndeclaredCaseStatement;
-import org.opendaylight.yangtools.yang.model.ri.stmt.impl.decl.RegularUndeclaredInputStatement;
-import org.opendaylight.yangtools.yang.model.ri.stmt.impl.decl.RegularUndeclaredOutputStatement;
-
-/**
- * Static entry point to instantiating {@link DeclaredStatements} covered in the {@code RFC7950} metamodel which are
- * not really declared, but rather implicit.
- */
-@Beta
-@NonNullByDefault
-public final class ImplicitStatements {
-    private ImplicitStatements() {
-        // Hidden on purpose
-    }
-
-    public static CaseStatement createCase(final QName argument,
-            final ImmutableList<? extends DeclaredStatement<?>> substatements) {
-        return substatements.isEmpty() ? new EmptyUndeclaredCaseStatement(argument)
-            : new RegularUndeclaredCaseStatement(argument, substatements);
-    }
-
-    public static InputStatement createInput(final QName argument,
-            final ImmutableList<? extends DeclaredStatement<?>> substatements) {
-        return substatements.isEmpty() ? new EmptyUndeclaredInputStatement(argument)
-            : new RegularUndeclaredInputStatement(argument, substatements);
-    }
-
-    public static OutputStatement createOutput(final QName argument,
-            final ImmutableList<? extends DeclaredStatement<?>> substatements) {
-        return substatements.isEmpty() ? new EmptyUndeclaredOutputStatement(argument)
-            : new RegularUndeclaredOutputStatement(argument, substatements);
-    }
-}
diff --git a/model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/UndeclaredStatements.java b/model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/UndeclaredStatements.java
new file mode 100644 (file)
index 0000000..71ce1f9
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * 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.model.ri.stmt;
+
+import com.google.common.annotations.Beta;
+import com.google.common.collect.ImmutableList;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.CaseEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.InputEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.api.stmt.OutputEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.ri.stmt.impl.eff.UndeclaredCaseEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.ri.stmt.impl.eff.UndeclaredInputEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.ri.stmt.impl.eff.UndeclaredOutputEffectiveStatement;
+import org.opendaylight.yangtools.yang.model.spi.meta.SubstatementIndexingException;
+
+/**
+ * Static entry point to instantiating undeclared {@link EffectiveStatement} covered in the {@code RFC7950} metamodel.
+ */
+@Beta
+@NonNullByDefault
+public final class UndeclaredStatements {
+    private UndeclaredStatements() {
+        // Hidden on purpose
+    }
+
+    public static CaseEffectiveStatement createCase(final QName argument, final int flags,
+            final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
+        return new UndeclaredCaseEffectiveStatement(substatements, argument, flags);
+    }
+
+    public static InputEffectiveStatement createInput(final QName argument, final int flags,
+            final ImmutableList<? extends EffectiveStatement<?, ?>> substatements)
+            throws SubstatementIndexingException {
+        return new UndeclaredInputEffectiveStatement(substatements, argument, flags);
+    }
+
+    public static OutputEffectiveStatement createOutput(final QName argument, final int flags,
+            final ImmutableList<? extends EffectiveStatement<?, ?>> substatements)
+            throws SubstatementIndexingException {
+        return new UndeclaredOutputEffectiveStatement(substatements, argument, flags);
+    }
+}
index aef8b96b917daa9741dda1a1ef4422066c66e170..ab2501da8a78aa1550e91c25f27eabc7c3a9cebb 100644 (file)
@@ -11,7 +11,7 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.stmt.CaseStatement;
 import org.opendaylight.yangtools.yang.model.spi.meta.AbstractDeclaredStatement.WithQNameArgument;
 
-public class EmptyCaseStatement extends WithQNameArgument implements CaseStatement {
+public final class EmptyCaseStatement extends WithQNameArgument implements CaseStatement {
     public EmptyCaseStatement(final QName argument) {
         super(argument);
     }
index f4e084236032f1a2be60fd043fc8c4378805c621..85374ec7ec060fe5ed8d2458a72640095f4f18a7 100644 (file)
@@ -11,7 +11,7 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.stmt.InputStatement;
 import org.opendaylight.yangtools.yang.model.spi.meta.AbstractDeclaredStatement.WithQNameArgument;
 
-public class EmptyInputStatement extends WithQNameArgument implements InputStatement {
+public final class EmptyInputStatement extends WithQNameArgument implements InputStatement {
     public EmptyInputStatement(final QName argument) {
         super(argument);
     }
index 4e96f027a613e430296e4893d1aba254d21860d9..e3e8f7bd715b9aa62c1e23c9cc3590dfbbba04c6 100644 (file)
@@ -11,7 +11,7 @@ import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.stmt.OutputStatement;
 import org.opendaylight.yangtools.yang.model.spi.meta.AbstractDeclaredStatement.WithQNameArgument;
 
-public class EmptyOutputStatement extends WithQNameArgument implements OutputStatement {
+public final class EmptyOutputStatement extends WithQNameArgument implements OutputStatement {
     public EmptyOutputStatement(final QName argument) {
         super(argument);
     }
diff --git a/model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/impl/decl/EmptyUndeclaredCaseStatement.java b/model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/impl/decl/EmptyUndeclaredCaseStatement.java
deleted file mode 100644 (file)
index 72933cd..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2020 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.model.ri.stmt.impl.decl;
-
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.meta.StatementOrigin;
-
-public final class EmptyUndeclaredCaseStatement extends EmptyCaseStatement {
-    public EmptyUndeclaredCaseStatement(final QName argument) {
-        super(argument);
-    }
-
-    @Override
-    public StatementOrigin statementOrigin() {
-        return StatementOrigin.CONTEXT;
-    }
-}
diff --git a/model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/impl/decl/EmptyUndeclaredInputStatement.java b/model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/impl/decl/EmptyUndeclaredInputStatement.java
deleted file mode 100644 (file)
index 5c91f96..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2020 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.model.ri.stmt.impl.decl;
-
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.meta.StatementOrigin;
-
-public final class EmptyUndeclaredInputStatement extends EmptyInputStatement {
-    public EmptyUndeclaredInputStatement(final QName argument) {
-        super(argument);
-    }
-
-    @Override
-    public StatementOrigin statementOrigin() {
-        return StatementOrigin.CONTEXT;
-    }
-}
diff --git a/model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/impl/decl/EmptyUndeclaredOutputStatement.java b/model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/impl/decl/EmptyUndeclaredOutputStatement.java
deleted file mode 100644 (file)
index e599a3f..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
- * Copyright (c) 2020 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.model.ri.stmt.impl.decl;
-
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.meta.StatementOrigin;
-
-public final class EmptyUndeclaredOutputStatement extends EmptyOutputStatement {
-    public EmptyUndeclaredOutputStatement(final QName argument) {
-        super(argument);
-    }
-
-    @Override
-    public StatementOrigin statementOrigin() {
-        return StatementOrigin.CONTEXT;
-    }
-}
index 3eb69eb5acd859370d19f37dce0702d57a60ad1a..5137b20361a3ecca40a9429f8c0148e6359a84ac 100644 (file)
@@ -13,7 +13,7 @@ import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.CaseStatement;
 import org.opendaylight.yangtools.yang.model.spi.meta.AbstractDeclaredStatement.WithQNameArgument.WithSubstatements;
 
-public class RegularCaseStatement extends WithSubstatements implements CaseStatement {
+public final class RegularCaseStatement extends WithSubstatements implements CaseStatement {
     public RegularCaseStatement(final QName argument,
             final ImmutableList<? extends DeclaredStatement<?>> substatements) {
         super(argument, substatements);
index 62a884aaf4ae4fcb6f20818276597eabae9fd9db..f47a1947fc1661cd4ff8f1c9f70a4bf853584e50 100644 (file)
@@ -13,7 +13,7 @@ import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.InputStatement;
 import org.opendaylight.yangtools.yang.model.spi.meta.AbstractDeclaredStatement.WithQNameArgument.WithSubstatements;
 
-public class RegularInputStatement extends WithSubstatements implements InputStatement {
+public final class RegularInputStatement extends WithSubstatements implements InputStatement {
     public RegularInputStatement(final QName argument,
             final ImmutableList<? extends DeclaredStatement<?>> substatements) {
         super(argument, substatements);
index 86ea4c2c48c98c98bb2b733f34cd7b34c6802556..d4993db3214dce8ebc71112af757bedb160cf7eb 100644 (file)
@@ -13,7 +13,7 @@ import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.OutputStatement;
 import org.opendaylight.yangtools.yang.model.spi.meta.AbstractDeclaredStatement.WithQNameArgument.WithSubstatements;
 
-public class RegularOutputStatement extends WithSubstatements implements OutputStatement {
+public final class RegularOutputStatement extends WithSubstatements implements OutputStatement {
     public RegularOutputStatement(final QName argument,
             final ImmutableList<? extends DeclaredStatement<?>> substatements) {
         super(argument, substatements);
diff --git a/model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/impl/decl/RegularUndeclaredCaseStatement.java b/model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/impl/decl/RegularUndeclaredCaseStatement.java
deleted file mode 100644 (file)
index 60122b6..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2020 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.model.ri.stmt.impl.decl;
-
-import com.google.common.collect.ImmutableList;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
-import org.opendaylight.yangtools.yang.model.api.meta.StatementOrigin;
-
-public final class RegularUndeclaredCaseStatement extends RegularCaseStatement {
-    public RegularUndeclaredCaseStatement(final QName argument,
-            final ImmutableList<? extends DeclaredStatement<?>> substatements) {
-        super(argument, substatements);
-    }
-
-    @Override
-    public StatementOrigin statementOrigin() {
-        return StatementOrigin.CONTEXT;
-    }
-}
diff --git a/model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/impl/decl/RegularUndeclaredInputStatement.java b/model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/impl/decl/RegularUndeclaredInputStatement.java
deleted file mode 100644 (file)
index a8ad0d1..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2020 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.model.ri.stmt.impl.decl;
-
-import com.google.common.collect.ImmutableList;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
-import org.opendaylight.yangtools.yang.model.api.meta.StatementOrigin;
-
-public final class RegularUndeclaredInputStatement extends RegularInputStatement {
-    public RegularUndeclaredInputStatement(final QName argument,
-            final ImmutableList<? extends DeclaredStatement<?>> substatements) {
-        super(argument, substatements);
-    }
-
-    @Override
-    public StatementOrigin statementOrigin() {
-        return StatementOrigin.CONTEXT;
-    }
-}
diff --git a/model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/impl/decl/RegularUndeclaredOutputStatement.java b/model/yang-model-ri/src/main/java/org/opendaylight/yangtools/yang/model/ri/stmt/impl/decl/RegularUndeclaredOutputStatement.java
deleted file mode 100644 (file)
index 765f3d3..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (c) 2020 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.model.ri.stmt.impl.decl;
-
-import com.google.common.collect.ImmutableList;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
-import org.opendaylight.yangtools.yang.model.api.meta.StatementOrigin;
-
-public final class RegularUndeclaredOutputStatement extends RegularOutputStatement {
-    public RegularUndeclaredOutputStatement(final QName argument,
-            final ImmutableList<? extends DeclaredStatement<?>> substatements) {
-        super(argument, substatements);
-    }
-
-    @Override
-    public StatementOrigin statementOrigin() {
-        return StatementOrigin.CONTEXT;
-    }
-}
index 50fbbcd23cff059c9e8c4764836003fb4986a98c..12d879e2c71ed37a631874a52e15bfd538b59cd5 100644 (file)
@@ -10,29 +10,20 @@ package org.opendaylight.yangtools.yang.parser.stmt.reactor;
 import static com.google.common.base.Preconditions.checkState;
 import static com.google.common.base.Verify.verify;
 import static com.google.common.base.Verify.verifyNotNull;
-import static java.util.Objects.requireNonNull;
 
-import com.google.common.collect.ImmutableList;
 import java.util.Collection;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Optional;
 import java.util.stream.Stream;
 import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.jdt.annotation.Nullable;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
-import org.opendaylight.yangtools.yang.model.api.meta.StatementOrigin;
-import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
 import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementFactory;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
-import org.opendaylight.yangtools.yang.parser.spi.source.ImplicitSubstatement;
 import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
 import org.opendaylight.yangtools.yang.parser.spi.source.StatementWriter.ResumedStatement;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * Intermediate subclass of StatementContextBase facing the parser stream via implementation of ResumedStatement. This
@@ -43,20 +34,15 @@ import org.slf4j.LoggerFactory;
  * @param <E> Effective Statement representation
  */
 abstract class AbstractResumedStatement<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>>
-        extends StatementContextBase<A, D, E> implements ResumedStatement {
-    private static final Logger LOG = LoggerFactory.getLogger(AbstractResumedStatement.class);
-
-    private final @NonNull StatementSourceReference statementDeclSource;
+        extends OriginalStmtCtx<A, D, E> implements ResumedStatement {
     private final String rawArgument;
 
-    private List<ReactorStmtCtx<?, ?, ?>> effective = ImmutableList.of();
     private StatementMap substatements = StatementMap.empty();
     private @Nullable D declaredInstance;
 
     // Copy constructor
     AbstractResumedStatement(final AbstractResumedStatement<A, D, E> original) {
         super(original);
-        this.statementDeclSource = original.statementDeclSource;
         this.rawArgument = original.rawArgument;
         this.substatements = original.substatements;
         this.declaredInstance = original.declaredInstance;
@@ -64,67 +50,18 @@ abstract class AbstractResumedStatement<A, D extends DeclaredStatement<A>, E ext
 
     AbstractResumedStatement(final StatementDefinitionContext<A, D, E> def, final StatementSourceReference ref,
             final String rawArgument) {
-        super(def);
-        this.statementDeclSource = requireNonNull(ref);
+        super(def, ref);
         this.rawArgument = def.support().internArgument(rawArgument);
     }
 
-    AbstractResumedStatement(final StatementDefinitionContext<A, D, E> def, final StatementSourceReference ref,
-            final String rawArgument, final CopyType copyType) {
-        super(def, copyType);
-        this.statementDeclSource = requireNonNull(ref);
-        this.rawArgument = rawArgument;
-    }
-
-    @Override
-    public final Optional<StmtContext<A, D, E>> getOriginalCtx() {
-        return Optional.empty();
-    }
-
-    @Override
-    public final Optional<StmtContext<A, D, E>> getPreviousCopyCtx() {
-        return Optional.empty();
-    }
-
-    @Override
-    public final StatementSourceReference sourceReference() {
-        return statementDeclSource;
-    }
-
     @Override
     public final String rawArgument() {
         return rawArgument;
     }
 
     @Override
-    public final Collection<? extends StatementContextBase<?, ?, ?>> mutableDeclaredSubstatements() {
-        return substatements;
-    }
-
-    @Override
-    public final Collection<? extends Mutable<?, ?, ?>> mutableEffectiveSubstatements() {
-        return mutableEffectiveSubstatements(effective);
-    }
-
-    @Override
-    public final void removeStatementFromEffectiveSubstatements(final StatementDefinition statementDef) {
-        effective = removeStatementFromEffectiveSubstatements(effective, statementDef);
-    }
-
-    @Override
-    public final void removeStatementFromEffectiveSubstatements(final StatementDefinition statementDef,
-            final String statementArg) {
-        effective = removeStatementFromEffectiveSubstatements(effective, statementDef, statementArg);
-    }
-
-    @Override
-    public final void addEffectiveSubstatement(final Mutable<?, ?, ?> substatement) {
-        effective = addEffectiveSubstatement(effective, substatement);
-    }
-
-    @Override
-    final void addEffectiveSubstatementsImpl(final Collection<? extends Mutable<?, ?, ?>> statements) {
-        effective = addEffectiveSubstatementsImpl(effective, statements);
+    public Collection<? extends StatementContextBase<?, ?, ?>> mutableDeclaredSubstatements() {
+        return verifyNotNull(substatements);
     }
 
     @Override
@@ -140,18 +77,13 @@ abstract class AbstractResumedStatement<A, D extends DeclaredStatement<A>, E ext
         return declaredInstance = definition().getFactory().createDeclared(this, substatementsAsDeclared());
     }
 
+    @SuppressWarnings({ "rawtypes", "unchecked" })
     private @NonNull Stream<DeclaredStatement<?>> substatementsAsDeclared() {
-        var stream = substatements.stream();
+        final Stream<AbstractResumedStatement<?, ?, ?>> stream;
         if (getImplicitDeclaredFlag()) {
-            stream = stream.map(stmt -> {
-                var ret = stmt;
-                while (ret.origin() == StatementOrigin.CONTEXT) {
-                    final var stmts = ret.substatements;
-                    verify(stmts.size() == 1, "Unexpected substatements %s", stmts);
-                    ret = verifyNotNull(stmts.get(0));
-                }
-                return ret;
-            });
+            stream = substatements.stream().map(AbstractResumedStatement::unmaskUndeclared);
+        } else {
+            stream = (Stream) substatements.stream();
         }
 
         return stream.map(AbstractResumedStatement::declared);
@@ -164,7 +96,7 @@ abstract class AbstractResumedStatement<A, D extends DeclaredStatement<A>, E ext
 
     @Override
     public final StatementSourceReference getSourceReference() {
-        return statementDeclSource;
+        return sourceReference();
     }
 
     @Override
@@ -172,6 +104,31 @@ abstract class AbstractResumedStatement<A, D extends DeclaredStatement<A>, E ext
         return fullyDefined();
     }
 
+    @Override
+    final E createEffective(final StatementFactory<A, D, E> factory) {
+        return createEffective(factory, this);
+    }
+
+    // Creates EffectiveStatement through full materialization and assumes declared statement presence
+    private @NonNull E createEffective(final StatementFactory<A, D, E> factory,
+            final StatementContextBase<A, D, E> ctx) {
+        // Statement reference count infrastructure makes an assumption that effective statement is only built after
+        // the declared statement is already done. Statements tracked by this class always have a declared view, and
+        // we need to ensure that is built before we touch effective substatements.
+        //
+        // Once the effective substatement stream has been exhausted, reference counting will triggers a sweep, hence
+        // the substatements may be gone by the time the factory attempts to acquire the declared statement.
+        declared();
+
+        return factory.createEffective(ctx, ctx.streamDeclared(), ctx.streamEffective());
+    }
+
+    @Override
+    final E createInferredEffective(final StatementFactory<A, D, E> factory,
+            final InferredStatementContext<A, D, E> ctx) {
+        return createEffective(factory, ctx);
+    }
+
     /**
      * Create a new substatement at the specified offset.
      *
@@ -193,38 +150,37 @@ abstract class AbstractResumedStatement<A, D extends DeclaredStatement<A>, E ext
         checkState(inProgressPhase != ModelProcessingPhase.EFFECTIVE_MODEL,
                 "Declared statement cannot be added in effective phase at: %s", sourceReference());
 
+        final SubstatementContext<X, Y, Z> ret;
         final var implicitParent = definition().getImplicitParentFor(this, def.getPublicView());
         if (implicitParent.isPresent()) {
-            return createImplicitParent(offset, implicitParent.orElseThrow(), ref, argument)
-                .createSubstatement(0, def, ref, argument);
+            setImplicitDeclaredFlag();
+            final var parent = createUndeclared(offset, implicitParent.orElseThrow(), ref, argument);
+            ret = new SubstatementContext<>(parent, def, ref, argument);
+            parent.addEffectiveSubstatement(ret);
+        } else {
+            ret = new SubstatementContext<>(this, def, ref, argument);
+            substatements = substatements.put(offset, ret);
         }
 
-        final AbstractResumedStatement<X, Y, Z> ret = new SubstatementContext<>(this, def, ref, argument);
-        substatements = substatements.put(offset, ret);
         def.onStatementAdded(ret);
         return ret;
     }
 
-    @Override
-    final AbstractResumedStatement<A, D, E> unmodifiedEffectiveSource() {
-        // This statement is comes from the source
-        return this;
-    }
-
-    @Override
-    final boolean hasEmptySubstatements() {
-        return substatements.size() == 0 && effective.isEmpty();
-    }
-
-    @Override
-    final boolean noSensitiveSubstatements() {
-        return hasEmptySubstatements()
-            || noSensitiveSubstatements(substatements) && noSensitiveSubstatements(effective);
-    }
-
-    @Override
-    final Iterator<ReactorStmtCtx<?, ?, ?>> effectiveChildrenToComplete() {
-        return effective.iterator();
+    private <X, Y extends DeclaredStatement<X>, Z extends EffectiveStatement<X, Y>>
+            UndeclaredStmtCtx<X, Y, Z> createUndeclared(final int offset, final StatementSupport<X, Y, Z> support,
+                final StatementSourceReference ref, final String argument) {
+        final UndeclaredStmtCtx<X, Y, Z> ret;
+        final var implicitParent = definition().getImplicitParentFor(this, support.getPublicView());
+        if (implicitParent.isPresent()) {
+            final var parent = createUndeclared(offset, implicitParent.orElseThrow(), ref, argument);
+            ret = new UndeclaredStmtCtx<>(parent, support, argument);
+            parent.addEffectiveSubstatement(ret);
+        } else {
+            ret = new UndeclaredStmtCtx<>(this, support, argument);
+            substatements = substatements.put(offset, ret);
+        }
+        support.onStatementAdded(ret);
+        return ret;
     }
 
     @Override
@@ -233,31 +189,8 @@ abstract class AbstractResumedStatement<A, D extends DeclaredStatement<A>, E ext
     }
 
     @Override
-    final Stream<? extends @NonNull StmtContext<?, ?, ?>> streamEffective() {
-        return effective.stream().filter(StmtContext::isSupportedToBuildEffective);
-    }
-
-    @Override
-    final void markNoParentRef() {
-        markNoParentRef(substatements);
-        markNoParentRef(effective);
-    }
-
-    @Override
-    final int sweepSubstatements() {
-        // First we need to sweep all statements, which may trigger sweeps all across the place, for example:
-        // - 'effective' member sweeping a 'substatements' member
-        // - 'substatements' member sweeping a 'substatements' member which came before it during iteration
-        // We then iterate once again, counting what remains unswept
-        sweep(substatements);
-        sweep(effective);
-        final int count = countUnswept(substatements) + countUnswept(effective);
-        if (count != 0) {
-            LOG.debug("{} children left to sweep from {}", count, this);
-        }
+    final void dropDeclaredSubstatements() {
         substatements = null;
-        effective = null;
-        return count;
     }
 
     /**
@@ -268,13 +201,17 @@ abstract class AbstractResumedStatement<A, D extends DeclaredStatement<A>, E ext
      * @return Substatement, or null if substatement does not exist.
      */
     final @Nullable AbstractResumedStatement<?, ?, ?> enterSubstatement(final int offset) {
-        var ret = substatements.get(offset);
-        if (ret != null) {
-            while (ret.origin() == StatementOrigin.CONTEXT) {
-                ret = verifyNotNull(ret.substatements.get(0));
-            }
+        var stmt = substatements.get(offset);
+        return stmt == null ? null : unmaskUndeclared(stmt);
+    }
+
+    private static @NonNull AbstractResumedStatement<?, ?, ?> unmaskUndeclared(final ReactorStmtCtx<?, ?, ?> stmt) {
+        var ret = stmt;
+        while (!(ret instanceof AbstractResumedStatement)) {
+            verify(ret instanceof UndeclaredStmtCtx, "Unexpectred statement %s", ret);
+            ret = ((UndeclaredStmtCtx<?, ?, ?>) ret).getResumedSubstatement();
         }
-        return ret;
+        return (AbstractResumedStatement<?, ?, ?>) ret;
     }
 
     /**
@@ -292,25 +229,26 @@ abstract class AbstractResumedStatement<A, D extends DeclaredStatement<A>, E ext
 
         var ret = verifyParent(parent);
         // Unwind all undeclared statements
-        while (ret.origin() == StatementOrigin.CONTEXT) {
+        while (!(ret instanceof AbstractResumedStatement)) {
             ret.finishDeclaration(phase);
             ret = verifyParent(ret.getParentContext());
         }
-        return ret;
+        return (AbstractResumedStatement<?, ?, ?>) ret;
     }
 
-    // FIXME: AbstractResumedStatement should only ever have AbstractResumedStatement parents, which would remove the
-    //        need for this method. In ordered to do that we need to untangle SubstatementContext's users and do not
-    //        allow it being reparent()ed.
-    private static AbstractResumedStatement<?, ?, ?> verifyParent(final StatementContextBase<?, ?, ?> parent) {
-        verify(parent instanceof AbstractResumedStatement, "Unexpected parent context %s", parent);
-        return (AbstractResumedStatement<?, ?, ?>) parent;
+    // FIXME: AbstractResumedStatement should only ever have OriginalStmtCtx parents, which would remove the need for
+    //        this method. In ordered to do that we need to untangle SubstatementContext's users and do not allow it
+    //        being reparent()ed.
+    private static OriginalStmtCtx<?, ?, ?> verifyParent(final StatementContextBase<?, ?, ?> parent) {
+        verify(parent instanceof OriginalStmtCtx, "Unexpected parent context %s", parent);
+        return (OriginalStmtCtx<?, ?, ?>) parent;
     }
 
     final void resizeSubstatements(final int expectedSize) {
         substatements = substatements.ensureCapacity(expectedSize);
     }
 
+    @Override
     final void declarationFinished(final ModelProcessingPhase phase) {
         finishChildrenDeclaration(phase);
         finishDeclaration(phase);
@@ -320,20 +258,4 @@ abstract class AbstractResumedStatement<A, D extends DeclaredStatement<A>, E ext
         checkState(isFullyDefined());
         substatements.forEach(stmt -> stmt.declarationFinished(phase));
     }
-
-    /**
-     * Ends declared section of current node for the specified phase.
-     *
-     * @param phase processing phase that ended
-     */
-    private void finishDeclaration(final ModelProcessingPhase phase) {
-        definition().onDeclarationFinished(this, phase);
-    }
-
-    private AbstractResumedStatement<?, ?, ?> createImplicitParent(final int offset,
-            final StatementSupport<?, ?, ?> implicitParent, final StatementSourceReference ref, final String argument) {
-        setImplicitDeclaredFlag();
-        return createSubstatement(offset, new StatementDefinitionContext<>(implicitParent),
-            ImplicitSubstatement.of(ref), argument);
-    }
 }
diff --git a/parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/ForwardingUndeclaredCurrent.java b/parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/ForwardingUndeclaredCurrent.java
new file mode 100644 (file)
index 0000000..84ffdd2
--- /dev/null
@@ -0,0 +1,128 @@
+/*
+ * 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.stmt.reactor;
+
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.collect.ForwardingObject;
+import java.util.Map;
+import java.util.Optional;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.QNameModule;
+import org.opendaylight.yangtools.yang.common.YangVersion;
+import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
+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.CopyHistory;
+import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.UndeclaredCurrent;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ParserNamespace;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
+
+final class ForwardingUndeclaredCurrent<A, D extends DeclaredStatement<A>> extends ForwardingObject
+        implements UndeclaredCurrent<A, D> {
+    private final Current<A, D> delegate;
+
+    ForwardingUndeclaredCurrent(final Current<A, D> delegate) {
+        this.delegate = requireNonNull(delegate);
+    }
+
+    @Override
+    public @NonNull QName moduleName() {
+        return delegate.moduleName();
+    }
+
+    @Override
+    @Deprecated(forRemoval = true)
+    public EffectiveStatement<?, ?> original() {
+        return delegate.original();
+    }
+
+    @Override
+    public QName argumentAsTypeQName() {
+        return delegate.argumentAsTypeQName();
+    }
+
+    @Override
+    @Deprecated
+    public <E extends EffectiveStatement<A, D>> StmtContext<A, D, E> caerbannog() {
+        return delegate.caerbannog();
+    }
+
+    @Override
+    public EffectiveConfig effectiveConfig() {
+        return delegate.effectiveConfig();
+    }
+
+    @Override
+    public QNameModule effectiveNamespace() {
+        return delegate.effectiveNamespace();
+    }
+
+    @Override
+    public Parent effectiveParent() {
+        return delegate.effectiveParent();
+    }
+
+    @Override
+    public StatementDefinition publicDefinition() {
+        return delegate.publicDefinition();
+    }
+
+    @Override
+    public StatementSourceReference sourceReference() {
+        return delegate.sourceReference();
+    }
+
+    @Override
+    public CopyHistory history() {
+        return delegate.history();
+    }
+
+    @Override
+    public <K, V, N extends ParserNamespace<K, V>> Map<K, V> namespace(final Class<@NonNull N> nsType) {
+        return delegate.namespace(nsType);
+    }
+
+    @Override
+    public <K, V, T extends K, N extends ParserNamespace<K, V>> V namespaceItem(final Class<@NonNull N> nsType,
+            final T key) {
+        return delegate.namespaceItem(nsType, key);
+    }
+
+    @Override
+    public <K, V, N extends ParserNamespace<K, V>> Map<K, V> localNamespacePortion(final Class<@NonNull N> nsType) {
+        return delegate.localNamespacePortion(nsType);
+    }
+
+    @Override
+    public A argument() {
+        return delegate.argument();
+    }
+
+    @Override
+    public YangVersion yangVersion() {
+        return delegate.yangVersion();
+    }
+
+    @Override
+    public <X, Z extends EffectiveStatement<X, ?>> Optional<X> findSubstatementArgument(final Class<Z> type) {
+        return delegate.findSubstatementArgument(type);
+    }
+
+    @Override
+    public boolean hasSubstatement(final Class<? extends EffectiveStatement<?, ?>> type) {
+        return delegate.hasSubstatement(type);
+    }
+
+    @Override
+    protected Current<A, D> delegate() {
+        return delegate;
+    }
+}
index c1e4386f21201b34afafaf575ddb5e035e9bffd7..2d724e85689264feb14372dd9d6bf0bcbf762cd0 100644 (file)
@@ -211,10 +211,15 @@ final class InferredStatementContext<A, D extends DeclaredStatement<A>, E extend
         // If we have not materialized we do not have a difference in effective substatements, hence we can forward
         // towards the source of the statement.
         accessSubstatements();
-        return substatements == null ? tryToReusePrototype(factory) : super.createEffective(factory);
+        return substatements == null ? tryToReusePrototype(factory) : createInferredEffective(factory, this);
     }
 
-    private @NonNull E tryToReusePrototype(final StatementFactory<A, D, E> factory) {
+    @Override
+    E createInferredEffective(final StatementFactory<A, D, E> factory, final InferredStatementContext<A, D, E> ctx) {
+        return prototype.createInferredEffective(factory, ctx);
+    }
+
+    private @NonNull E tryToReusePrototype(final @NonNull StatementFactory<A, D, E> factory) {
         final E origEffective = prototype.buildEffective();
         final Collection<? extends @NonNull EffectiveStatement<?, ?>> origSubstatements =
             origEffective.effectiveSubstatements();
@@ -276,7 +281,8 @@ final class InferredStatementContext<A, D extends DeclaredStatement<A>, E extend
         return internAlongCopyAxis(factory, factory.createEffective(this, declared.stream(), effective.stream()));
     }
 
-    private @NonNull E tryToReuseSubstatements(final StatementFactory<A, D, E> factory, final @NonNull E original) {
+    private @NonNull E tryToReuseSubstatements(final @NonNull StatementFactory<A, D, E> factory,
+            final @NonNull E original) {
         if (allSubstatementsContextIndependent()) {
             LOG.debug("Reusing substatements of: {}", prototype);
             substatements = noRefs() ? REUSED_SUBSTATEMENTS : reusePrototypeReplicas();
@@ -286,7 +292,7 @@ final class InferredStatementContext<A, D extends DeclaredStatement<A>, E extend
 
         // Fall back to full instantiation, which populates our substatements. Then check if we should be reusing
         // the substatement list, as this operation turned out to not affect them.
-        final E effective = super.createEffective(factory);
+        final E effective = createInferredEffective(factory, this);
         // Since we have forced instantiation to deal with this case, we also need to reset the 'modified' flag
         setUnmodified();
 
diff --git a/parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/OriginalStmtCtx.java b/parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/OriginalStmtCtx.java
new file mode 100644 (file)
index 0000000..c4c7d95
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * 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.stmt.reactor;
+
+import static com.google.common.base.Verify.verify;
+import static com.google.common.base.Verify.verifyNotNull;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.collect.ImmutableList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Stream;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
+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.CopyType;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPhase;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+abstract class OriginalStmtCtx<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>>
+        extends StatementContextBase<A, D, E> {
+    private static final Logger LOG = LoggerFactory.getLogger(OriginalStmtCtx.class);
+
+    private final @NonNull StatementSourceReference ref;
+
+    private List<ReactorStmtCtx<?, ?, ?>> effective = ImmutableList.of();
+
+    OriginalStmtCtx(final OriginalStmtCtx<A, D, E> original) {
+        super(original);
+        this.ref = original.ref;
+    }
+
+    OriginalStmtCtx(final StatementDefinitionContext<A, D, E> def, final StatementSourceReference ref) {
+        super(def);
+        this.ref = requireNonNull(ref);
+    }
+
+    OriginalStmtCtx(final StatementDefinitionContext<A, D, E> def, final StatementSourceReference ref,
+            final CopyType copyType) {
+        super(def, copyType);
+        this.ref = requireNonNull(ref);
+    }
+
+    @Override
+    public final StatementSourceReference sourceReference() {
+        return ref;
+    }
+
+    @Override
+    public final Optional<StmtContext<A, D, E>> getOriginalCtx() {
+        return Optional.empty();
+    }
+
+    @Override
+    public final Optional<StmtContext<A, D, E>> getPreviousCopyCtx() {
+        return Optional.empty();
+    }
+
+    @Override
+    public final Collection<? extends Mutable<?, ?, ?>> mutableEffectiveSubstatements() {
+        return mutableEffectiveSubstatements(effective);
+    }
+
+    @Override
+    public final void removeStatementFromEffectiveSubstatements(final StatementDefinition statementDef) {
+        effective = removeStatementFromEffectiveSubstatements(effective, statementDef);
+    }
+
+    @Override
+    public final void removeStatementFromEffectiveSubstatements(final StatementDefinition statementDef,
+            final String statementArg) {
+        effective = removeStatementFromEffectiveSubstatements(effective, statementDef, statementArg);
+    }
+
+    @Override
+    public final void addEffectiveSubstatement(final Mutable<?, ?, ?> substatement) {
+        effective = addEffectiveSubstatement(effective, substatement);
+    }
+
+    @Override
+    final void addEffectiveSubstatementsImpl(final Collection<? extends Mutable<?, ?, ?>> statements) {
+        effective = addEffectiveSubstatementsImpl(effective, statements);
+    }
+
+    @Override
+    final Iterator<ReactorStmtCtx<?, ?, ?>> effectiveChildrenToComplete() {
+        return effective.iterator();
+    }
+
+    @Override
+    final Stream<? extends @NonNull StmtContext<?, ?, ?>> streamEffective() {
+        return effective.stream().filter(StmtContext::isSupportedToBuildEffective);
+    }
+
+    @Override
+    final OriginalStmtCtx<A, D, E> unmodifiedEffectiveSource() {
+        // This statement is comes from the source
+        return this;
+    }
+
+    @Override
+    final boolean hasEmptySubstatements() {
+        return effective.isEmpty() && mutableDeclaredSubstatements().isEmpty();
+    }
+
+    @Override
+    final boolean noSensitiveSubstatements() {
+        return hasEmptySubstatements()
+            || noSensitiveSubstatements(effective) && noSensitiveSubstatements(mutableDeclaredSubstatements());
+    }
+
+    @Override
+    final void markNoParentRef() {
+        markNoParentRef(mutableDeclaredSubstatements());
+        markNoParentRef(effective);
+    }
+
+    @Override
+    final int sweepSubstatements() {
+        // First we need to sweep all statements, which may trigger sweeps all across the place, for example:
+        // - 'effective' member sweeping a 'substatements' member
+        // - 'substatements' member sweeping a 'substatements' member which came before it during iteration
+        // We then iterate once again, counting what remains unswept
+        final var declared = mutableDeclaredSubstatements();
+
+        sweep(declared);
+        sweep(effective);
+        final int count = countUnswept(declared) + countUnswept(effective);
+        if (count != 0) {
+            LOG.debug("{} children left to sweep from {}", count, this);
+        }
+        effective = null;
+        dropDeclaredSubstatements();
+        return count;
+    }
+
+    abstract void dropDeclaredSubstatements();
+
+    void declarationFinished(final ModelProcessingPhase phase) {
+        finishDeclaration(phase);
+    }
+
+    /**
+     * Ends declared section of current node for the specified phase.
+     *
+     * @param phase processing phase that ended
+     */
+    final void finishDeclaration(final ModelProcessingPhase phase) {
+        definition().onDeclarationFinished(this, phase);
+    }
+
+    final OriginalStmtCtx<?, ?, ?> getResumedSubstatement() {
+        final var local = verifyNotNull(effective);
+        verify(!local.isEmpty(), "Unexpected empty statements");
+        final var ret = local.get(0);
+        verify(ret instanceof OriginalStmtCtx, "Unexpected statement %s", ret);
+        return (OriginalStmtCtx<?, ?, ?>) ret;
+    }
+}
index 4fd73c7b94619a8e93f91241222f4774313d2e44..aab4fae60f0551e223ba7b7a82e57d156262769b 100644 (file)
@@ -298,8 +298,7 @@ abstract class ReactorStmtCtx<A, D extends DeclaredStatement<A>, E extends Effec
     }
 
     protected ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
-        return toStringHelper.add("definition", definition()).add("rawArgument", rawArgument())
-            .add("refCount", refString());
+        return toStringHelper.add("definition", definition()).add("argument", argument()).add("refCount", refString());
     }
 
     private String refString() {
@@ -389,12 +388,6 @@ abstract class ReactorStmtCtx<A, D extends DeclaredStatement<A>, E extends Effec
     }
 
     private @NonNull E loadEffective() {
-        // Creating an effective statement does not strictly require a declared instance -- there are statements like
-        // 'input', which are implicitly defined.
-        // Our implementation design makes an invariant assumption that buildDeclared() has been called by the time
-        // we attempt to create effective statement:
-        declared();
-
         final E ret = createEffective();
         effectiveInstance = ret;
         // we have called createEffective(), substatements are no longer guarded by us. Let's see if we can clear up
index 2f81c12c323094ee9033cafa57d547bac579020f..d70191206084de8604a1e16bc5c385ae91707470 100644 (file)
@@ -180,7 +180,7 @@ final class ReplicaStatementContext<A, D extends DeclaredStatement<A>, E extends
 
     @Override
     public <X, Y extends DeclaredStatement<X>, Z extends EffectiveStatement<X, Y>>
-            Mutable<X, Y, Z> addEffectiveSubstatement(final StatementSupport<X, Y, Z> support, final X arg) {
+            Mutable<X, Y, Z> addUndeclaredSubstatement(final StatementSupport<X, Y, Z> support, final X arg) {
         throw new UnsupportedOperationException();
     }
 
index c5cf622953e22153c194eeba442e43985a3a50ac..f5f85c37c412a94cd80f795e8546c8a84e5548c4 100644 (file)
@@ -49,7 +49,7 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.StatementNamespace;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport.CopyPolicy;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
-import org.opendaylight.yangtools.yang.parser.spi.source.ImplicitSubstatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.UndeclaredStatementFactory;
 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
 import org.opendaylight.yangtools.yang.parser.stmt.reactor.NamespaceBehaviourWithListeners.KeyedValueAddedListener;
 import org.opendaylight.yangtools.yang.parser.stmt.reactor.NamespaceBehaviourWithListeners.PredicateValueAddedListener;
@@ -321,11 +321,11 @@ abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E extends
 
     @Override
     public final <X, Y extends DeclaredStatement<X>, Z extends EffectiveStatement<X, Y>>
-            Mutable<X, Y, Z> addEffectiveSubstatement(final StatementSupport<X, Y, Z> support, final X arg) {
-        // FIXME: YANGTOOLS-652: This does not need to be a SubstatementContext, in can be a specialized
-        //                       StatementContextBase subclass.
-        final Mutable<X, Y, Z> ret = new SubstatementContext<>(this, new StatementDefinitionContext<>(support),
-                ImplicitSubstatement.of(sourceReference()), arg);
+            Mutable<X, Y, Z> addUndeclaredSubstatement(final StatementSupport<X, Y, Z> support, final X arg) {
+        requireNonNull(support);
+        checkArgument(support instanceof UndeclaredStatementFactory, "Unsupported statement support %s", support);
+
+        final var ret = new UndeclaredStmtCtx<>(this, support, arg);
         support.onStatementAdded(ret);
         addEffectiveSubstatement(ret);
         return ret;
@@ -421,15 +421,20 @@ abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E extends
         return result;
     }
 
-    @NonNull E createEffective(final StatementFactory<A, D, E> factory) {
-        return createEffective(factory, this);
-    }
+    abstract @NonNull E createEffective(@NonNull StatementFactory<A, D, E> factory);
 
-    // Creates EffectiveStatement through full materialization
-    static <A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>> @NonNull E createEffective(
-            final StatementFactory<A, D, E> factory, final StatementContextBase<A, D, E> ctx) {
-        return factory.createEffective(ctx, ctx.streamDeclared(), ctx.streamEffective());
-    }
+    /**
+     * Routing of the request to build an effective statement from {@link InferredStatementContext} towards the original
+     * definition site. This is needed to pick the correct instantiation method: for declared statements we will
+     * eventually land in {@link AbstractResumedStatement}, for underclared statements that will be
+     * {@link UndeclaredStmtCtx}.
+     *
+     * @param factory Statement factory
+     * @param ctx Inferred statement context, i.e. where the effective statement is instantiated
+     * @return Built effective stateue
+     */
+    abstract @NonNull E createInferredEffective(@NonNull StatementFactory<A, D, E> factory,
+        @NonNull InferredStatementContext<A, D, E> ctx);
 
     /**
      * Return a stream of declared statements which can be built into an {@link EffectiveStatement}, as per
@@ -795,9 +800,7 @@ abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E extends
         final InferredStatementContext<X, Y, Z> copy;
 
         if (implicitParent.isPresent()) {
-            final StatementDefinitionContext<?, ?, ?> def = new StatementDefinitionContext<>(implicitParent.get());
-            result = new SubstatementContext(this, def, original.sourceReference(), original.rawArgument(),
-                original.argument(), type);
+            result = new UndeclaredStmtCtx(this, implicitParent.orElseThrow(), original, type);
 
             final CopyType childCopyType;
             switch (type) {
@@ -846,16 +849,11 @@ abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E extends
             return original;
         }
 
-        final StatementDefinitionContext<?, ?, ?> def = new StatementDefinitionContext<>(optImplicit.orElseThrow());
-        final CopyType type = original.history().getLastOperation();
-
         checkArgument(original instanceof StatementContextBase, "Unsupported original %s", original);
         final var origBase = (StatementContextBase<?, ?, ?>)original;
 
-        @SuppressWarnings({ "rawtypes", "unchecked"})
-        final SubstatementContext<?, ?, ?> result = new SubstatementContext(origBase.getParentContext(), def,
-            original.sourceReference(), original.rawArgument(), original.argument(), type);
-
+        @SuppressWarnings({ "rawtypes", "unchecked" })
+        final UndeclaredStmtCtx<?, ?, ?> result = new UndeclaredStmtCtx(origBase, optImplicit.orElseThrow());
         result.addEffectiveSubstatement(origBase.reparent(result));
         result.setCompletedPhase(original.getCompletedPhase());
         return result;
index 6441ded70dd9e5e5f6f79803f13abfec348845f7..fc099716a4c53d90f8e61778328b2cff0c0a9648 100644 (file)
@@ -32,15 +32,15 @@ import org.eclipse.jdt.annotation.Nullable;
  *
  * @author Robert Varga
  */
-abstract class StatementMap extends AbstractCollection<AbstractResumedStatement<?, ?, ?>> {
+abstract class StatementMap extends AbstractCollection<OriginalStmtCtx<?, ?, ?>> {
     private static final class Empty extends StatementMap {
-        private static final Iterator<AbstractResumedStatement<?, ?, ?>> EMPTY_ITERATOR;
+        private static final Iterator<OriginalStmtCtx<?, ?, ?>> EMPTY_ITERATOR;
 
         static {
             // This may look weird, but we really want to return two Iterator implementations from StatementMap, so that
             // users have to deal with bimorphic invocation. Note that we want to invoke hasNext() here, as we want to
             // initialize state to AbstractIterator.endOfData().
-            final Iterator<AbstractResumedStatement<?, ?, ?>> it = new Regular(0).iterator();
+            final Iterator<OriginalStmtCtx<?, ?, ?>> it = new Regular(0).iterator();
             verify(!it.hasNext());
             EMPTY_ITERATOR = it;
         }
@@ -51,7 +51,7 @@ abstract class StatementMap extends AbstractCollection<AbstractResumedStatement<
         }
 
         @Override
-        StatementMap put(final int index, final AbstractResumedStatement<?, ?, ?> obj) {
+        StatementMap put(final int index, final OriginalStmtCtx<?, ?, ?> obj) {
             return index == 0 ? new Singleton(obj) : new Regular(index, obj);
         }
 
@@ -66,48 +66,48 @@ abstract class StatementMap extends AbstractCollection<AbstractResumedStatement<
         }
 
         @Override
-        public void forEach(final Consumer<? super AbstractResumedStatement<?, ?, ?>> action) {
+        public void forEach(final Consumer<? super OriginalStmtCtx<?, ?, ?>> action) {
             // No-op
         }
 
         @Override
-        public Iterator<AbstractResumedStatement<?, ?, ?>> iterator() {
+        public Iterator<OriginalStmtCtx<?, ?, ?>> iterator() {
             return EMPTY_ITERATOR;
         }
     }
 
     private static final class Regular extends StatementMap {
-        private AbstractResumedStatement<?, ?, ?>[] elements;
+        private OriginalStmtCtx<?, ?, ?>[] elements;
         private int size;
 
         Regular(final int expectedLimit) {
-            elements = new AbstractResumedStatement<?, ?, ?>[expectedLimit];
+            elements = new OriginalStmtCtx<?, ?, ?>[expectedLimit];
         }
 
-        Regular(final int index, final AbstractResumedStatement<?, ?, ?> object) {
+        Regular(final int index, final OriginalStmtCtx<?, ?, ?> object) {
             this(index + 1, index, object);
         }
 
-        Regular(final AbstractResumedStatement<?, ?, ?> object0, final int index,
-                final AbstractResumedStatement<?, ?, ?> object) {
+        Regular(final OriginalStmtCtx<?, ?, ?> object0, final int index,
+                final OriginalStmtCtx<?, ?, ?> object) {
             this(index + 1, 0, object0);
             elements[index] = requireNonNull(object);
             size = 2;
         }
 
-        Regular(final int expectedLimit, final int index, final AbstractResumedStatement<?, ?, ?> object) {
+        Regular(final int expectedLimit, final int index, final OriginalStmtCtx<?, ?, ?> object) {
             this(expectedLimit);
             elements[index] = requireNonNull(object);
             size = 1;
         }
 
         @Override
-        AbstractResumedStatement<?, ?, ?> get(final int index) {
+        OriginalStmtCtx<?, ?, ?> get(final int index) {
             return index >= elements.length ? null : elements[index];
         }
 
         @Override
-        StatementMap put(final int index, final AbstractResumedStatement<?, ?, ?> obj) {
+        StatementMap put(final int index, final OriginalStmtCtx<?, ?, ?> obj) {
             if (index < elements.length) {
                 checkArgument(elements[index] == null);
             } else {
@@ -134,11 +134,11 @@ abstract class StatementMap extends AbstractCollection<AbstractResumedStatement<
         }
 
         @Override
-        public Iterator<AbstractResumedStatement<?, ?, ?>> iterator() {
+        public Iterator<OriginalStmtCtx<?, ?, ?>> iterator() {
             return new Iter(this);
         }
 
-        private static final class Iter extends AbstractIterator<AbstractResumedStatement<?, ?, ?>> {
+        private static final class Iter extends AbstractIterator<OriginalStmtCtx<?, ?, ?>> {
             private int nextOffset = 0;
             private Regular map;
 
@@ -147,9 +147,9 @@ abstract class StatementMap extends AbstractCollection<AbstractResumedStatement<
             }
 
             @Override
-            protected AbstractResumedStatement<?, ?, ?> computeNext() {
+            protected OriginalStmtCtx<?, ?, ?> computeNext() {
                 while (nextOffset < map.elements.length) {
-                    final AbstractResumedStatement<?, ?, ?> ret = map.elements[nextOffset++];
+                    final OriginalStmtCtx<?, ?, ?> ret = map.elements[nextOffset++];
                     if (ret != null) {
                         return ret;
                     }
@@ -162,19 +162,19 @@ abstract class StatementMap extends AbstractCollection<AbstractResumedStatement<
     }
 
     private static final class Singleton extends StatementMap {
-        private final AbstractResumedStatement<?, ?, ?> object;
+        private final OriginalStmtCtx<?, ?, ?> object;
 
-        Singleton(final AbstractResumedStatement<?, ?, ?> object) {
+        Singleton(final OriginalStmtCtx<?, ?, ?> object) {
             this.object = requireNonNull(object);
         }
 
         @Override
-        AbstractResumedStatement<?, ?, ?> get(final int index) {
+        OriginalStmtCtx<?, ?, ?> get(final int index) {
             return index == 0 ? object : null;
         }
 
         @Override
-        StatementMap put(final int index, final AbstractResumedStatement<?, ?, ?> obj) {
+        StatementMap put(final int index, final OriginalStmtCtx<?, ?, ?> obj) {
             checkArgument(index != 0);
             return new Regular(object, index, obj);
         }
@@ -190,7 +190,7 @@ abstract class StatementMap extends AbstractCollection<AbstractResumedStatement<
         }
 
         @Override
-        public Iterator<AbstractResumedStatement<?, ?, ?>> iterator() {
+        public Iterator<OriginalStmtCtx<?, ?, ?>> iterator() {
             return Iterators.singletonIterator(object);
         }
     }
@@ -212,7 +212,7 @@ abstract class StatementMap extends AbstractCollection<AbstractResumedStatement<
      * @param index Element index, must be non-negative
      * @return Requested element or null if there is no element at that index
      */
-    abstract @Nullable AbstractResumedStatement<?, ?, ?> get(int index);
+    abstract @Nullable OriginalStmtCtx<?, ?, ?> get(int index);
 
     /**
      * Add a statement at specified index.
@@ -222,7 +222,7 @@ abstract class StatementMap extends AbstractCollection<AbstractResumedStatement<
      * @return New statement map
      * @throws IllegalArgumentException if the index is already occupied
      */
-    abstract @NonNull StatementMap put(int index, @NonNull AbstractResumedStatement<?, ?, ?> obj);
+    abstract @NonNull StatementMap put(int index, @NonNull OriginalStmtCtx<?, ?, ?> obj);
 
     /**
      * Ensure storage space for at least {@code explectedLimit} substatements.
index ca287ad0a1ab5024f55531130c72e8c8cca8f7e6..15044126b7fc5588223524f19fc6a009ec751562 100644 (file)
@@ -11,7 +11,6 @@ import static java.util.Objects.requireNonNull;
 
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
-import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
 import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.StorageNodeType;
 import org.opendaylight.yangtools.yang.parser.spi.source.StatementSourceReference;
 
@@ -23,33 +22,17 @@ final class SubstatementContext<A, D extends DeclaredStatement<A>, E extends Eff
     private SubstatementContext(final SubstatementContext<A, D, E> original,
             final StatementContextBase<?, ?, ?> parent) {
         super(original);
-        this.parent = requireNonNull(parent, "Parent must not be null");
+        this.parent = requireNonNull(parent);
         this.argument = original.argument;
     }
 
-    SubstatementContext(final StatementContextBase<?, ?, ?> parent, final StatementDefinitionContext<A, D, E> def,
+    SubstatementContext(final OriginalStmtCtx<?, ?, ?> parent, final StatementDefinitionContext<A, D, E> def,
             final StatementSourceReference ref, final String rawArgument) {
         super(def, ref, rawArgument);
-        this.parent = requireNonNull(parent, "Parent must not be null");
+        this.parent = requireNonNull(parent);
         this.argument = def.parseArgumentValue(this, rawArgument());
     }
 
-    SubstatementContext(final StatementContextBase<?, ?, ?> parent, final StatementDefinitionContext<A, D, E> def,
-            final StatementSourceReference ref, final A argument) {
-        super(def, ref, null);
-        this.parent = requireNonNull(parent, "Parent must not be null");
-        this.argument = argument != null ? argument : def.parseArgumentValue(this, null);
-    }
-
-    // FIXME: YANGTOOLS-784: this constructor is only called in contexts where a different implementation
-    //                       would be more appropriate
-    SubstatementContext(final StatementContextBase<?, ?, ?> parent, final StatementDefinitionContext<A, D, E> def,
-            final StatementSourceReference ref, final String rawArgument, final A argument, final CopyType copyType) {
-        super(def, ref, rawArgument, copyType);
-        this.parent = requireNonNull(parent, "Parent must not be null");
-        this.argument = argument;
-    }
-
     @Override
     SubstatementContext<A, D, E> reparent(final StatementContextBase<?, ?, ?> newParent) {
         return new SubstatementContext<>(this, newParent);
diff --git a/parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/UndeclaredStmtCtx.java b/parser/yang-parser-reactor/src/main/java/org/opendaylight/yangtools/yang/parser/stmt/reactor/UndeclaredStmtCtx.java
new file mode 100644 (file)
index 0000000..75b3aef
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+ * 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.stmt.reactor;
+
+import static com.google.common.base.Verify.verify;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.collect.ImmutableList;
+import java.util.Collection;
+import java.util.stream.Stream;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.Nullable;
+import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.CopyType;
+import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.UndeclaredCurrent;
+import org.opendaylight.yangtools.yang.parser.spi.meta.NamespaceBehaviour.StorageNodeType;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementFactory;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StatementSupport;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
+import org.opendaylight.yangtools.yang.parser.spi.meta.UndeclaredStatementFactory;
+import org.opendaylight.yangtools.yang.parser.spi.source.ImplicitSubstatement;
+
+/**
+/**
+ * Core reactor statement implementation of {@link Mutable}.
+ *
+ * @param <A> Argument type
+ * @param <D> Declared Statement representation
+ * @param <E> Effective Statement representation
+ */
+final class UndeclaredStmtCtx<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>>
+        extends OriginalStmtCtx<A, D, E> implements UndeclaredCurrent<A, D> {
+    private final StatementContextBase<?, ?, ?> parent;
+    private final A argument;
+
+    private UndeclaredStmtCtx(final UndeclaredStmtCtx<A, D, E> original, final StatementContextBase<?, ?, ?> parent) {
+        super(original);
+        this.parent = requireNonNull(parent);
+        this.argument = original.argument;
+    }
+
+    UndeclaredStmtCtx(final StatementContextBase<?, ?, ?> parent, final StatementSupport<A, D, E> support,
+            final @Nullable A argument) {
+        super(new StatementDefinitionContext<>(support), ImplicitSubstatement.of(parent.sourceReference()));
+        this.parent = requireNonNull(parent);
+        this.argument = argument != null ? argument : definition().parseArgumentValue(this, null);
+    }
+
+    // Exposed for StatementContextBase.wrapWithImplicit()
+    UndeclaredStmtCtx(final StatementContextBase<?, ?, ?> original, final StatementSupport<A, D, E> support) {
+        super(new StatementDefinitionContext<>(verifySupport(support)), original.sourceReference(),
+            original.getLastOperation());
+        this.parent = original.getParentContext();
+        this.argument = castArgument(original);
+    }
+
+    // Exposed for implicit substatement wrapping in StatementContextBase.childCopyOf()
+    UndeclaredStmtCtx(final StatementContextBase<?, ?, ?> parent, final StatementSupport<A, D, E> support,
+            final StatementContextBase<?, ?, ?> original, final CopyType type) {
+        super(new StatementDefinitionContext<>(verifySupport(support)), original.sourceReference(), type);
+        this.parent = requireNonNull(parent);
+        this.argument = castArgument(original);
+    }
+
+    // Exposed for AbstractResumedStatement
+    UndeclaredStmtCtx(final StatementContextBase<?, ?, ?> parent, final StatementSupport<A, D, E> support,
+            final String rawArgument) {
+        super(new StatementDefinitionContext<>(support), ImplicitSubstatement.of(parent.sourceReference()));
+        this.parent = requireNonNull(parent);
+        this.argument = definition().parseArgumentValue(this, rawArgument);
+    }
+
+    // FIXME: this assumes original's argument type matches this type... which is true for the only case we
+    //        currently care about (implicit case in choice, which is always triggered by a SchemaTree original),
+    //        but this will need re-visiting
+    @SuppressWarnings("unchecked")
+    private static <A> @NonNull A castArgument(final StatementContextBase<?, ?, ?> original) {
+        return (A) original.getArgument();
+    }
+
+    private static <T> T verifySupport(final T support) {
+        verify(support instanceof UndeclaredStatementFactory, "Unexpected statement support %s", support);
+        return support;
+    }
+
+    @Override
+    public Collection<? extends StatementContextBase<?, ?, ?>> mutableDeclaredSubstatements() {
+        return ImmutableList.of();
+    }
+
+    @Override
+    Stream<? extends @NonNull StmtContext<?, ?, ?>> streamDeclared() {
+        return Stream.empty();
+    }
+
+    @Override
+    void dropDeclaredSubstatements() {
+        // No-op
+    }
+
+    @Override
+    UndeclaredStmtCtx<A, D, E> reparent(final StatementContextBase<?, ?, ?> newParent) {
+        return new UndeclaredStmtCtx<>(this, newParent);
+    }
+
+    @Override
+    E createEffective(final StatementFactory<A, D, E> factory) {
+        return createEffective(factory, this, streamEffective());
+    }
+
+    @SuppressWarnings("unchecked")
+    private static <A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>> @NonNull E createEffective(
+            final @NonNull StatementFactory<A, D, E> factory, final @NonNull UndeclaredCurrent<A, D> ctx,
+            final @NonNull Stream<? extends StmtContext<?, ?, ?>> substatements) {
+        verify(factory instanceof UndeclaredStatementFactory, "Unexpected factory %s", factory);
+        return ((UndeclaredStatementFactory<A, D, E>) factory).createUndeclaredEffective(ctx, substatements);
+    }
+
+    @Override
+    E createInferredEffective(final StatementFactory<A, D, E> factory, final InferredStatementContext<A, D, E> ctx) {
+        return createEffective(factory, new ForwardingUndeclaredCurrent<>(ctx), ctx.streamEffective());
+    }
+
+    /*
+     * KEEP THINGS ORGANIZED!
+     *
+     * below methods exist in the same form in InferredStatementContext. If any adjustment is made here, make sure it is
+     * properly updated there.
+     */
+    @Override
+    public A argument() {
+        return argument;
+    }
+
+    @Override
+    public StatementContextBase<?, ?, ?> getParentContext() {
+        return parent;
+    }
+
+    @Override
+    public StorageNodeType getStorageNodeType() {
+        return StorageNodeType.STATEMENT_LOCAL;
+    }
+
+    @Override
+    public StatementContextBase<?, ?, ?> getParentNamespaceStorage() {
+        return parent;
+    }
+
+    @Override
+    public RootStatementContext<?, ?, ?> getRoot() {
+        return parent.getRoot();
+    }
+
+    @Override
+    public EffectiveConfig effectiveConfig() {
+        return effectiveConfig(parent);
+    }
+
+    @Override
+    protected boolean isIgnoringIfFeatures() {
+        return isIgnoringIfFeatures(parent);
+    }
+
+    @Override
+    protected boolean isIgnoringConfig() {
+        return isIgnoringConfig(parent);
+    }
+
+    @Override
+    protected boolean isParentSupportedByFeatures() {
+        return parent.isSupportedByFeatures();
+    }
+}
index 7d834e1153040ddb91542fb4f9088dfd7b71a84a..45bc4aad896e8cb8ff209d0f0bb60f2d5ebc441e 100644 (file)
@@ -10,17 +10,20 @@ package org.opendaylight.yangtools.yang.parser.rfc7950.stmt.meta;
 import static java.util.Objects.requireNonNull;
 
 import com.google.common.collect.ImmutableList;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 import org.eclipse.jdt.annotation.NonNull;
 import org.opendaylight.yangtools.yang.common.QName;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.StatementDefinition;
-import org.opendaylight.yangtools.yang.model.api.meta.StatementOrigin;
 import org.opendaylight.yangtools.yang.model.api.stmt.SchemaTreeEffectiveStatement;
 import org.opendaylight.yangtools.yang.parser.api.YangParserConfiguration;
 import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractSchemaTreeStatementSupport;
-import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current;
+import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.UndeclaredCurrent;
+import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
 import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator;
+import org.opendaylight.yangtools.yang.parser.spi.meta.UndeclaredStatementFactory;
 
 /**
  * A massively-misnamed superclass for statements which are both schema tree participants and can be created as implicit
@@ -30,46 +33,22 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator;
  * @param <E> Effective Statement representation
  */
 abstract class AbstractImplicitStatementSupport<D extends DeclaredStatement<QName>,
-        E extends SchemaTreeEffectiveStatement<D>> extends AbstractSchemaTreeStatementSupport<D, E> {
+        E extends SchemaTreeEffectiveStatement<D>> extends AbstractSchemaTreeStatementSupport<D, E>
+        implements UndeclaredStatementFactory<QName, D, E> {
     AbstractImplicitStatementSupport(final StatementDefinition publicDefinition, final StatementPolicy<QName, D> policy,
             final YangParserConfiguration config, final SubstatementValidator validator) {
         super(publicDefinition, policy, config, requireNonNull(validator));
     }
 
     @Override
-    public final E copyEffective(final Current<QName, D> stmt, final E original) {
-        final StatementOrigin source = stmt.origin();
-        switch (source) {
-            case CONTEXT:
-                return copyUndeclaredEffective(stmt, original);
-            case DECLARATION:
-                return copyDeclaredEffective(stmt, original);
-            default:
-                throw new IllegalStateException("Unhandled statement source " + source);
-        }
+    public final E createUndeclaredEffective(final UndeclaredCurrent<QName, D> stmt,
+            final @NonNull Stream<? extends StmtContext<?, ?, ?>> effectiveSubstatements) {
+        return createUndeclaredEffective(stmt, buildEffectiveSubstatements(stmt,
+            statementsToBuild(stmt, effectiveSubstatements
+                .filter(StmtContext::isSupportedToBuildEffective)
+                .collect(Collectors.toUnmodifiableList()))));
     }
 
-    @Override
-    protected E createEffective(final Current<QName, D> stmt,
-            final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
-        final StatementOrigin origin = stmt.origin();
-        switch (origin) {
-            case CONTEXT:
-                return createUndeclaredEffective(stmt, substatements);
-            case DECLARATION:
-                return createDeclaredEffective(stmt, substatements);
-            default:
-                throw new IllegalStateException("Unhandled statement origin " + origin);
-        }
-    }
-
-    abstract @NonNull E copyDeclaredEffective(@NonNull Current<QName, D> stmt, @NonNull E original);
-
-    abstract @NonNull E copyUndeclaredEffective(@NonNull Current<QName, D> stmt, @NonNull E original);
-
-    abstract @NonNull E createDeclaredEffective(@NonNull Current<QName, D> stmt,
-            @NonNull ImmutableList<? extends EffectiveStatement<?, ?>> substatements);
-
-    abstract @NonNull E createUndeclaredEffective(@NonNull Current<QName, D> stmt,
-            @NonNull ImmutableList<? extends EffectiveStatement<?, ?>> substatements);
+    abstract @NonNull E createUndeclaredEffective(@NonNull UndeclaredCurrent<QName, D> stmt,
+        @NonNull ImmutableList<? extends EffectiveStatement<?, ?>> substatements);
 }
index c3266a9e7064792e0d939e15fd1f1a1765207a54..a5975fa347b3cf26b1f4f691e9ffe3962e75b647 100644 (file)
@@ -26,6 +26,7 @@ import org.opendaylight.yangtools.yang.parser.rfc7950.stmt.EffectiveStmtUtils;
 import org.opendaylight.yangtools.yang.parser.spi.meta.AbstractQNameStatementSupport;
 import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStatementState;
 import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current;
+import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.UndeclaredCurrent;
 import org.opendaylight.yangtools.yang.parser.spi.meta.QNameWithFlagsEffectiveStatementState;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContext;
 import org.opendaylight.yangtools.yang.parser.spi.meta.StmtContextUtils;
@@ -55,46 +56,36 @@ abstract class AbstractOperationContainerStatementSupport<D extends DeclaredStat
     }
 
     @Override
-    final @NonNull E copyDeclaredEffective(final Current<QName, D> stmt, final E original) {
-        return copyDeclaredEffective(
-            EffectiveStmtUtils.historyAndStatusFlags(stmt.history(), original.effectiveSubstatements()), stmt,
-            original);
-    }
-
-    abstract @NonNull E copyDeclaredEffective(int flags, @NonNull Current<QName, D> stmt,
-        @NonNull E original);
-
-    @Override
-    final @NonNull E copyUndeclaredEffective(final Current<QName, D> stmt, final E original) {
-        return copyUndeclaredEffective(
-            EffectiveStmtUtils.historyAndStatusFlags(stmt.history(), original.effectiveSubstatements()), stmt,
-            original);
-    }
-
-    abstract @NonNull E copyUndeclaredEffective(int flags, @NonNull Current<QName, D> stmt, @NonNull E original);
-
-    @Override
-    final @NonNull E createDeclaredEffective(final Current<QName, D> stmt,
+    protected final E createEffective(final Current<QName, D> stmt,
             final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
         try {
-            return createDeclaredEffective(
-                EffectiveStmtUtils.historyAndStatusFlags(stmt.history(), substatements), stmt, substatements);
+            return createEffective(EffectiveStmtUtils.historyAndStatusFlags(stmt.history(), substatements), stmt,
+                substatements);
         } catch (SubstatementIndexingException e) {
             throw new SourceException(e.getMessage(), stmt, e);
         }
     }
 
-    abstract @NonNull E createDeclaredEffective(int flags, @NonNull Current<QName, D> stmt,
+    abstract @NonNull E createEffective(int flags, @NonNull Current<QName, D> stmt,
             @NonNull ImmutableList<? extends EffectiveStatement<?, ?>> substatements);
 
     @Override
-    final E createUndeclaredEffective(final Current<QName, D> stmt,
+    public final @NonNull E copyEffective(final Current<QName, D> stmt, final E original) {
+        return copyEffective(
+            EffectiveStmtUtils.historyAndStatusFlags(stmt.history(), original.effectiveSubstatements()), stmt,
+            original);
+    }
+
+    abstract @NonNull E copyEffective(int flags, @NonNull Current<QName, D> stmt, @NonNull E original);
+
+    @Override
+    final E createUndeclaredEffective(final UndeclaredCurrent<QName, D> stmt,
             final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
         return createUndeclaredEffective(EffectiveStmtUtils.historyAndStatusFlags(stmt.history(), substatements), stmt,
             substatements);
     }
 
-    abstract @NonNull E createUndeclaredEffective(int flags, @NonNull Current<QName, D> stmt,
+    abstract @NonNull E createUndeclaredEffective(int flags, @NonNull UndeclaredCurrent<QName, D> stmt,
             @NonNull ImmutableList<? extends EffectiveStatement<?, ?>> substatements);
 
     @Override
index 14f3f38c15208f56a53f0de72c51f275b304d182..1d2d5c15e81ffeea36a641e099af1928c087521e 100644 (file)
@@ -132,7 +132,7 @@ public final class ActionStatementSupport extends
 
     private static void appendImplicitSubstatement(final Mutable<QName, ActionStatement, ActionEffectiveStatement> stmt,
             final QName substatementName) {
-        stmt.addEffectiveSubstatement(
+        stmt.addUndeclaredSubstatement(
             verifyNotNull(stmt.getFromNamespace(StatementSupportNamespace.class, substatementName)), null);
     }
 }
index 4496a38b0e77d96500b2f4eba2cd448a0c3e574c..c623e5a14209aa39433db8151796b424f2ab40f2 100644 (file)
@@ -24,14 +24,13 @@ import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclarationReference;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.meta.StatementOrigin;
 import org.opendaylight.yangtools.yang.model.api.stmt.CaseEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.CaseStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.StatusEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.ri.stmt.DeclaredStatementDecorators;
 import org.opendaylight.yangtools.yang.model.ri.stmt.DeclaredStatements;
 import org.opendaylight.yangtools.yang.model.ri.stmt.EffectiveStatements;
-import org.opendaylight.yangtools.yang.model.ri.stmt.ImplicitStatements;
+import org.opendaylight.yangtools.yang.model.ri.stmt.UndeclaredStatements;
 import org.opendaylight.yangtools.yang.model.spi.meta.EffectiveStatementMixins.EffectiveStatementWithFlags.FlagsBuilder;
 import org.opendaylight.yangtools.yang.model.spi.meta.SubstatementIndexingException;
 import org.opendaylight.yangtools.yang.parser.api.YangParserConfiguration;
@@ -39,6 +38,7 @@ import org.opendaylight.yangtools.yang.parser.spi.meta.BoundStmtCtx;
 import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStatementState;
 import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current;
 import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Parent.EffectiveConfig;
+import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.UndeclaredCurrent;
 import org.opendaylight.yangtools.yang.parser.spi.meta.QNameWithFlagsEffectiveStatementState;
 import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator;
 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
@@ -91,15 +91,7 @@ public final class CaseStatementSupport
     @Override
     protected CaseStatement createDeclared(final BoundStmtCtx<QName> ctx,
             final ImmutableList<DeclaredStatement<?>> substatements) {
-        final StatementOrigin origin = ctx.origin();
-        switch (origin) {
-            case CONTEXT:
-                return ImplicitStatements.createCase(ctx.getArgument(), substatements);
-            case DECLARATION:
-                return DeclaredStatements.createCase(ctx.getArgument(), substatements);
-            default:
-                throw new IllegalStateException("Unhandled statement origin " + origin);
-        }
+        return DeclaredStatements.createCase(ctx.getArgument(), substatements);
     }
 
     @Override
@@ -108,21 +100,7 @@ public final class CaseStatementSupport
     }
 
     @Override
-    protected CaseEffectiveStatement copyDeclaredEffective(final Current<QName, CaseStatement> stmt,
-            final CaseEffectiveStatement original) {
-        return EffectiveStatements.copyCase(original, stmt.getArgument(),
-            computeFlags(stmt, original.effectiveSubstatements()));
-    }
-
-    @Override
-    protected CaseEffectiveStatement copyUndeclaredEffective(final Current<QName, CaseStatement> stmt,
-            final CaseEffectiveStatement original) {
-        return EffectiveStatements.copyCase(original, stmt.getArgument(),
-            computeFlags(stmt, original.effectiveSubstatements()));
-    }
-
-    @Override
-    protected CaseEffectiveStatement createDeclaredEffective(final Current<QName, CaseStatement> stmt,
+    protected CaseEffectiveStatement createEffective(final Current<QName, CaseStatement> stmt,
             final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
         try {
             return EffectiveStatements.createCase(stmt.declared(), stmt.getArgument(),
@@ -133,10 +111,18 @@ public final class CaseStatementSupport
     }
 
     @Override
-    protected CaseEffectiveStatement createUndeclaredEffective(final Current<QName, CaseStatement> stmt,
+    public CaseEffectiveStatement copyEffective(final Current<QName, CaseStatement> stmt,
+            final CaseEffectiveStatement original) {
+        return EffectiveStatements.copyCase(original, stmt.getArgument(),
+            computeFlags(stmt, original.effectiveSubstatements()));
+    }
+
+    @Override
+    protected CaseEffectiveStatement createUndeclaredEffective(final UndeclaredCurrent<QName, CaseStatement> stmt,
             final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
         try {
-            return EffectiveStatements.createCase(stmt.getArgument(), computeFlags(stmt, substatements), substatements);
+            return UndeclaredStatements.createCase(stmt.getArgument(), computeFlags(stmt, substatements),
+                substatements);
         } catch (SubstatementIndexingException e) {
             throw new SourceException(e.getMessage(), stmt, e);
         }
index ba6512a9d1ccc71d5bee1fe68140851cb16bcb1f..75d9413c3f262ae8d83647a4d7bb0e1df29fc018 100644 (file)
@@ -16,17 +16,17 @@ import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclarationReference;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.meta.StatementOrigin;
 import org.opendaylight.yangtools.yang.model.api.stmt.InputEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.InputStatement;
 import org.opendaylight.yangtools.yang.model.ri.stmt.DeclaredStatementDecorators;
 import org.opendaylight.yangtools.yang.model.ri.stmt.DeclaredStatements;
 import org.opendaylight.yangtools.yang.model.ri.stmt.EffectiveStatements;
-import org.opendaylight.yangtools.yang.model.ri.stmt.ImplicitStatements;
+import org.opendaylight.yangtools.yang.model.ri.stmt.UndeclaredStatements;
 import org.opendaylight.yangtools.yang.model.spi.meta.SubstatementIndexingException;
 import org.opendaylight.yangtools.yang.parser.api.YangParserConfiguration;
 import org.opendaylight.yangtools.yang.parser.spi.meta.BoundStmtCtx;
 import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current;
+import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.UndeclaredCurrent;
 import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator;
 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
 
@@ -73,15 +73,7 @@ public final class InputStatementSupport
     @Override
     protected InputStatement createDeclared(final BoundStmtCtx<QName> ctx,
             final ImmutableList<DeclaredStatement<?>> substatements) {
-        final StatementOrigin origin = ctx.origin();
-        switch (origin) {
-            case CONTEXT:
-                return ImplicitStatements.createInput(ctx.getArgument(), substatements);
-            case DECLARATION:
-                return DeclaredStatements.createInput(ctx.getArgument(), substatements);
-            default:
-                throw new IllegalStateException("Unhandled statement origin " + origin);
-        }
+        return DeclaredStatements.createInput(ctx.getArgument(), substatements);
     }
 
     @Override
@@ -91,19 +83,13 @@ public final class InputStatementSupport
     }
 
     @Override
-    InputEffectiveStatement copyDeclaredEffective(final int flags, final Current<QName, InputStatement> stmt,
-            final InputEffectiveStatement original) {
-        return EffectiveStatements.copyInput(original, stmt.getArgument(), flags);
-    }
-
-    @Override
-    InputEffectiveStatement copyUndeclaredEffective(final int flags, final Current<QName, InputStatement> stmt,
+    InputEffectiveStatement copyEffective(final int flags, final Current<QName, InputStatement> stmt,
             final InputEffectiveStatement original) {
         return EffectiveStatements.copyInput(original, stmt.getArgument(), flags);
     }
 
     @Override
-    InputEffectiveStatement createDeclaredEffective(final int flags, final Current<QName, InputStatement> stmt,
+    InputEffectiveStatement createEffective(final int flags, final Current<QName, InputStatement> stmt,
             final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
         try {
             return EffectiveStatements.createInput(stmt.declared(), stmt.getArgument(), flags, substatements);
@@ -113,10 +99,11 @@ public final class InputStatementSupport
     }
 
     @Override
-    InputEffectiveStatement createUndeclaredEffective(final int flags, final Current<QName, InputStatement> stmt,
+    InputEffectiveStatement createUndeclaredEffective(final int flags,
+            final UndeclaredCurrent<QName, InputStatement> stmt,
             final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
         try {
-            return EffectiveStatements.createInput(stmt.getArgument(), flags, substatements);
+            return UndeclaredStatements.createInput(stmt.getArgument(), flags, substatements);
         } catch (SubstatementIndexingException e) {
             throw new SourceException(e.getMessage(), stmt, e);
         }
index 36294fedd0fd313814fd35c83dba27a973e23a42..72eec151e783ed13c3b49389e127c38d1878ba5c 100644 (file)
@@ -16,17 +16,17 @@ import org.opendaylight.yangtools.yang.model.api.YangStmtMapping;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclarationReference;
 import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
 import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
-import org.opendaylight.yangtools.yang.model.api.meta.StatementOrigin;
 import org.opendaylight.yangtools.yang.model.api.stmt.OutputEffectiveStatement;
 import org.opendaylight.yangtools.yang.model.api.stmt.OutputStatement;
 import org.opendaylight.yangtools.yang.model.ri.stmt.DeclaredStatementDecorators;
 import org.opendaylight.yangtools.yang.model.ri.stmt.DeclaredStatements;
 import org.opendaylight.yangtools.yang.model.ri.stmt.EffectiveStatements;
-import org.opendaylight.yangtools.yang.model.ri.stmt.ImplicitStatements;
+import org.opendaylight.yangtools.yang.model.ri.stmt.UndeclaredStatements;
 import org.opendaylight.yangtools.yang.model.spi.meta.SubstatementIndexingException;
 import org.opendaylight.yangtools.yang.parser.api.YangParserConfiguration;
 import org.opendaylight.yangtools.yang.parser.spi.meta.BoundStmtCtx;
 import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current;
+import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.UndeclaredCurrent;
 import org.opendaylight.yangtools.yang.parser.spi.meta.SubstatementValidator;
 import org.opendaylight.yangtools.yang.parser.spi.source.SourceException;
 
@@ -73,15 +73,7 @@ public final class OutputStatementSupport
     @Override
     protected OutputStatement createDeclared(final BoundStmtCtx<QName> ctx,
             final ImmutableList<DeclaredStatement<?>> substatements) {
-        final StatementOrigin origin = ctx.origin();
-        switch (origin) {
-            case CONTEXT:
-                return ImplicitStatements.createOutput(ctx.getArgument(), substatements);
-            case DECLARATION:
-                return DeclaredStatements.createOutput(ctx.getArgument(), substatements);
-            default:
-                throw new IllegalStateException("Unhandled statement origin " + origin);
-        }
+        return DeclaredStatements.createOutput(ctx.getArgument(), substatements);
     }
 
     @Override
@@ -91,19 +83,13 @@ public final class OutputStatementSupport
     }
 
     @Override
-    OutputEffectiveStatement copyDeclaredEffective(final int flags, final Current<QName, OutputStatement> stmt,
-            final OutputEffectiveStatement original) {
-        return EffectiveStatements.copyOutput(original, stmt.getArgument(), flags);
-    }
-
-    @Override
-    OutputEffectiveStatement copyUndeclaredEffective(final int flags, final Current<QName, OutputStatement> stmt,
+    OutputEffectiveStatement copyEffective(final int flags, final Current<QName, OutputStatement> stmt,
             final OutputEffectiveStatement original) {
         return EffectiveStatements.copyOutput(original, stmt.getArgument(), flags);
     }
 
     @Override
-    OutputEffectiveStatement createDeclaredEffective(final int flags, final Current<QName, OutputStatement> stmt,
+    OutputEffectiveStatement createEffective(final int flags, final Current<QName, OutputStatement> stmt,
             final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
         try {
             return EffectiveStatements.createOutput(stmt.declared(), stmt.getArgument(), flags, substatements);
@@ -113,10 +99,11 @@ public final class OutputStatementSupport
     }
 
     @Override
-    OutputEffectiveStatement createUndeclaredEffective(final int flags, final Current<QName, OutputStatement> stmt,
+    OutputEffectiveStatement createUndeclaredEffective(final int flags,
+            final UndeclaredCurrent<QName, OutputStatement> stmt,
             final ImmutableList<? extends EffectiveStatement<?, ?>> substatements) {
         try {
-            return EffectiveStatements.createOutput(stmt.getArgument(), flags, substatements);
+            return UndeclaredStatements.createOutput(stmt.getArgument(), flags, substatements);
         } catch (SubstatementIndexingException e) {
             throw new SourceException(e.getMessage(), stmt, e);
         }
index 66009ec426e0cce9519ffdd884b69ca14a01e2b5..b696325e4d94a207d066c3db597a46719c3baae5 100644 (file)
@@ -100,7 +100,7 @@ public final class RpcStatementSupport extends AbstractSchemaTreeStatementSuppor
 
     private static void appendImplicitSubstatement(final Mutable<QName, RpcStatement, RpcEffectiveStatement> stmt,
             final QName substatementName) {
-        stmt.addEffectiveSubstatement(
+        stmt.addUndeclaredSubstatement(
             verifyNotNull(stmt.getFromNamespace(StatementSupportNamespace.class, substatementName)), null);
     }
 }
index 2140b7dceb78c33e22bfa00e71ab4eb2fcc85c82..c98c9fa14dd90bb960238c34e6f0c0c0f98b5881 100644 (file)
@@ -126,4 +126,25 @@ public interface EffectiveStmtCtx extends CommonStmtCtx, StmtContextCompat, Immu
         @Deprecated
         <E extends EffectiveStatement<A, D>> @NonNull StmtContext<A, D, E> caerbannog();
     }
+
+    /**
+     * A restricted version of {@link Current}, which does not expose the raw argument or the declared statement.
+     *
+     * @param <A> Argument type
+     * @param <D> Class representing declared version of this statement
+     */
+    @Beta
+    interface UndeclaredCurrent<A, D extends DeclaredStatement<A>> extends Current<A, D> {
+        @Deprecated
+        @Override
+        default String rawArgument() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Deprecated
+        @Override
+        default D declared() {
+            throw new UnsupportedOperationException();
+        }
+    }
 }
index 96d26f7c0ce9847f826d33660e9a9b185ca5dd59..d689406428da860d365b5fa0a4bbd829d3e784b4 100644 (file)
@@ -354,17 +354,12 @@ public interface StmtContext<A, D extends DeclaredStatement<A>, E extends Effect
          */
         void addRequiredSource(SourceIdentifier dependency);
 
-        // YANG example: RPC/action statements always have 'input' and 'output' defined
-        @Beta
-        <X, Y extends DeclaredStatement<X>, Z extends EffectiveStatement<X, Y>>
-            @NonNull Mutable<X, Y, Z> addEffectiveSubstatement(StatementSupport<X, Y, Z> support, @Nullable X arg);
-
         /**
          * Adds an effective statement to collection of substatements.
          *
          * @param substatement substatement
          * @throws IllegalStateException if added in declared phase
-         * @throws NullPointerException if statement parameter is null
+         * @throws NullPointerException if {@code substatement} is null
          */
         void addEffectiveSubstatement(Mutable<?, ?, ?> substatement);
 
@@ -377,6 +372,23 @@ public interface StmtContext<A, D extends DeclaredStatement<A>, E extends Effect
          */
         void addEffectiveSubstatements(Collection<? extends Mutable<?, ?, ?>> statements);
 
+        /**
+         * Adds a purely-effective statement to collection of substatements. The statement will report a {@code null}
+         * {@link EffectiveStatement#getDeclared()} object. A typical example of statements which require this mechanics
+         * are {@code rpc} and {@code action} statements, which always have {@code input} and {@code output}
+         * substatements, even if those are not declared in YANG text.
+         *
+         * @param support Statement support of the statement being created
+         * @param arg Effective argument. If specified as {@code null}, statement support will be consulted for the
+         *            empty argument.
+         * @throws IllegalArgumentException if {@code support} does not implement {@link UndeclaredStatementFactory}
+         * @throws IllegalStateException if added in declared phase
+         * @throws NullPointerException if {@code support} is null
+         */
+        @Beta
+        <X, Y extends DeclaredStatement<X>, Z extends EffectiveStatement<X, Y>>
+            @NonNull Mutable<X, Y, Z> addUndeclaredSubstatement(StatementSupport<X, Y, Z> support, @Nullable X arg);
+
         @Beta
         void removeStatementFromEffectiveSubstatements(StatementDefinition statementDef);
 
diff --git a/parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/UndeclaredStatementFactory.java b/parser/yang-parser-spi/src/main/java/org/opendaylight/yangtools/yang/parser/spi/meta/UndeclaredStatementFactory.java
new file mode 100644 (file)
index 0000000..f80b2f9
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * 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 java.util.stream.Stream;
+import org.eclipse.jdt.annotation.NonNull;
+import org.opendaylight.yangtools.yang.model.api.meta.DeclaredStatement;
+import org.opendaylight.yangtools.yang.model.api.meta.EffectiveStatement;
+import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.Current;
+import org.opendaylight.yangtools.yang.parser.spi.meta.EffectiveStmtCtx.UndeclaredCurrent;
+
+/**
+ * An entity capable of creating undeclared {@link EffectiveStatement} instances for a particular type. Unlike
+ * {@link StatementFactory}, effective statements created through this interface are expected to return a {@code null}
+ * from {@link EffectiveStatement#getDeclared()}.
+ *
+ * @param <A> Argument type
+ * @param <D> Declared Statement representation
+ * @param <E> Effective Statement representation
+ */
+@Beta
+public interface UndeclaredStatementFactory<A, D extends DeclaredStatement<A>, E extends EffectiveStatement<A, D>> {
+    /**
+     * Create a {@link EffectiveStatement} for specified context. Implementations of this method must not access
+     * {@link Current#declared()} or {@link Current#rawArgument()}.
+     *
+     * @param stmt Effective capture of this statement's significant state
+     * @param effectiveSubstatements effectively-visible substatements
+     * @return An effective statement instance
+     */
+    @NonNull E createUndeclaredEffective(@NonNull UndeclaredCurrent<A, D> stmt,
+        @NonNull Stream<? extends StmtContext<?, ?, ?>> effectiveSubstatements);
+}