Fire AbstractPrerequisite listeners as soon as they resolve
[yangtools.git] / yang / yang-parser-reactor / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / reactor / ModifierImpl.java
index 664ad74a546256600329707f0bf833c148892ae3..5edde2ffd80a3b391b6c6d86331cce5b11fb27a7 100644 (file)
@@ -86,12 +86,6 @@ final class ModifierImpl implements ModelActionBuilder {
         action = null;
     }
 
-    private void applyAction() {
-        checkState(!actionApplied);
-        action.apply(ctx);
-        actionApplied = true;
-    }
-
     private <K, C extends StmtContext<?, ?, ?>, N extends StatementNamespace<K, ?, ?>> @NonNull AbstractPrerequisite<C>
             requiresCtxImpl(final StmtContext<?, ?, ?> context, final Class<N> namespace, final K key,
                     final ModelProcessingPhase phase)  {
@@ -147,7 +141,10 @@ final class ModifierImpl implements ModelActionBuilder {
         checkState(action != null, "Action was not defined yet.");
 
         if (removeSatisfied()) {
-            applyAction();
+            if (!actionApplied) {
+                action.apply(ctx);
+                actionApplied = true;
+            }
             return true;
         }
         return false;
@@ -169,15 +166,15 @@ final class ModifierImpl implements ModelActionBuilder {
 
     @Override
     public <K, N extends StatementNamespace<K, ?, ?>> Prerequisite<StmtContext<?, ?, ?>> requiresCtx(
-            final StmtContext<?, ?, ?> context, final Class<N> namespace, final K key,
+            final StmtContext<?, ?, ?> context, final Class<@NonNull N> namespace, final K key,
             final ModelProcessingPhase phase) {
         return requiresCtxImpl(context, namespace, key, phase);
     }
 
     @Override
     public <K, N extends StatementNamespace<K, ?, ?>> Prerequisite<StmtContext<?, ?, ?>> requiresCtx(
-            final StmtContext<?, ?, ?> context, final Class<N> namespace, final NamespaceKeyCriterion<K> criterion,
-            final ModelProcessingPhase phase) {
+            final StmtContext<?, ?, ?> context, final Class<@NonNull N> namespace,
+            final NamespaceKeyCriterion<K> criterion, final ModelProcessingPhase phase) {
         return requiresCtxImpl(context, namespace, criterion, phase);
     }
 
@@ -188,6 +185,7 @@ final class ModifierImpl implements ModelActionBuilder {
     }
 
     @Override
+    @Deprecated
     public <K, D extends DeclaredStatement<?>, N extends StatementNamespace<K, ? extends D, ?>> Prerequisite<D>
             requiresDeclared(final StmtContext<?, ?, ?> context, final Class<N> namespace, final K key) {
         final AbstractPrerequisite<StmtContext<?, D, ?>> rawContext = requiresCtxImpl(context, namespace, key,
@@ -196,6 +194,7 @@ final class ModifierImpl implements ModelActionBuilder {
     }
 
     @Override
+    @Deprecated
     public <K, D extends DeclaredStatement<?>, N extends StatementNamespace<K, ? extends D, ?>>
             AbstractPrerequisite<StmtContext<?, D, ?>> requiresDeclaredCtx(final StmtContext<?, ?, ?> context,
                     final Class<N> namespace, final K key) {
@@ -203,12 +202,14 @@ final class ModifierImpl implements ModelActionBuilder {
     }
 
     @Override
+    @Deprecated
     public <E extends EffectiveStatement<?, ?>> Prerequisite<E> requiresEffective(
             final StmtContext<?, ?, ? extends E> stmt) {
         return requiresCtxImpl(stmt, EFFECTIVE_MODEL).transform(StmtContext::buildEffective);
     }
 
     @Override
+    @Deprecated
     public <K, E extends EffectiveStatement<?, ?>, N extends StatementNamespace<K, ?, ? extends E>> Prerequisite<E>
             requiresEffective(final StmtContext<?, ?, ?> context, final Class<N> namespace, final K key) {
         final AbstractPrerequisite<StmtContext<?, ?, E>> rawContext = requiresCtxImpl(context, namespace, key,
@@ -217,6 +218,7 @@ final class ModifierImpl implements ModelActionBuilder {
     }
 
     @Override
+    @Deprecated
     public <K, E extends EffectiveStatement<?, ?>, N extends StatementNamespace<K, ?, ? extends E>>
             AbstractPrerequisite<StmtContext<?, ?, E>> requiresEffectiveCtx(final StmtContext<?, ?, ?> context,
                     final Class<N> namespace, final K key) {
@@ -224,6 +226,7 @@ final class ModifierImpl implements ModelActionBuilder {
     }
 
     @Override
+    @Deprecated
     public <N extends IdentifierNamespace<?, ?>> Prerequisite<Mutable<?, ?, ?>> mutatesNs(
             final Mutable<?, ?, ?> context, final Class<N> namespace) {
         return addMutation(new NamespaceMutation<>(contextImpl(context), namespace));
@@ -314,7 +317,7 @@ final class ModifierImpl implements ModelActionBuilder {
         @Override
         public boolean phaseFinished(final StatementContextBase<?, ?, ?> context,
                 final ModelProcessingPhase finishedPhase) {
-            return resolvePrereq((C) context);
+            return resolvePrereq((C) context) || tryApply();
         }
     }
 
@@ -343,7 +346,7 @@ final class ModifierImpl implements ModelActionBuilder {
         @Override
         public boolean phaseFinished(final StatementContextBase<?, ?, ?> context,
                 final ModelProcessingPhase finishedPhase) {
-            return resolvePrereq((C) context);
+            return resolvePrereq((C) context) || tryApply();
         }
 
         @Override
@@ -376,6 +379,11 @@ final class ModifierImpl implements ModelActionBuilder {
         }
     }
 
+    /**
+     * This similar to {@link PhaseModificationInNamespace}, but allows recursive descent until it finds the real
+     * target. The mechanics is driven as a sequence of prerequisites along a path: first we hook onto namespace to
+     * give us the first step. When it does, we hook onto the first item to provide us the second step and so on.
+     */
     private final class PhaseModificationInNamespacePath<C extends Mutable<?, ?, ?>, K,
             N extends IdentifierNamespace<K, ? extends StmtContext<?, ?, ?>>> extends AbstractPrerequisite<C>
             implements OnNamespaceItemAdded, ContextMutation {
@@ -407,15 +415,29 @@ final class ModifierImpl implements ModelActionBuilder {
                 return;
             }
 
+            // Hook onto target: we either have a modification of the target itself or one of its children.
+            target.addMutation(modPhase, this);
+            // We have completed the context -> target step, hence we are no longer directly blocking context from
+            // making forward progress.
+            context.removeMutation(modPhase, this);
+
             if (!it.hasNext()) {
-                target.addMutation(modPhase, this);
-                resolvePrereq((C) value);
+                // Last step: we are done
+                if (resolvePrereq((C) value)) {
+                    tryApply();
+                }
                 return;
             }
 
+            // Make sure target's storage notifies us when the next step becomes available.
             hookOnto(target, namespace, it.next());
         }
 
+        @Override
+        ToStringHelper addToStringAttributes(final ToStringHelper toStringHelper) {
+            return super.addToStringAttributes(toStringHelper).add("phase", modPhase).add("keys", keys);
+        }
+
         void hookOnto(final StmtContext<?, ?, ?> context, final Class<?> namespace) {
             checkArgument(it.hasNext(), "Namespace %s keys may not be empty", namespace);
             hookOnto(contextImpl(context), namespace, it.next());