Defer mutatesEffectiveCtxPath() hookOnto()
[yangtools.git] / yang / yang-parser-reactor / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / reactor / ModifierImpl.java
index 7327e988af32d362801e90586d423ecb8fa8200a..3a9eafa9b74dac598a77640ec004a8c3596267cb 100644 (file)
@@ -16,8 +16,10 @@ import static org.opendaylight.yangtools.yang.parser.spi.meta.ModelProcessingPha
 
 import com.google.common.base.MoreObjects;
 import com.google.common.base.MoreObjects.ToStringHelper;
+import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Set;
 import java.util.function.Function;
 import org.eclipse.jdt.annotation.NonNull;
@@ -39,13 +41,13 @@ import org.slf4j.LoggerFactory;
 final class ModifierImpl implements ModelActionBuilder {
     private static final Logger LOG = LoggerFactory.getLogger(ModifierImpl.class);
 
-    private final InferenceContext ctx = new InferenceContext() { };
-
     private final Set<AbstractPrerequisite<?>> unsatisfied = new HashSet<>(1);
     private final Set<AbstractPrerequisite<?>> mutations = new HashSet<>(1);
+    private final InferenceContext ctx = new InferenceContext() { };
 
+    private List<Runnable> bootstraps;
     private InferenceAction action;
-    private boolean actionApplied = false;
+    private boolean actionApplied;
 
     private <D> AbstractPrerequisite<D> addReq(final AbstractPrerequisite<D> prereq) {
         LOG.trace("Modifier {} adding prerequisite {}", this, prereq);
@@ -86,12 +88,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 +143,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;
@@ -253,7 +252,10 @@ final class ModifierImpl implements ModelActionBuilder {
         addReq(ret);
         addMutation(ret);
 
-        ret.hookOnto(context, namespace);
+        if (bootstraps == null) {
+            bootstraps = new ArrayList<>(1);
+        }
+        bootstraps.add(() -> ret.hookOnto(context, namespace));
         return ret;
     }
 
@@ -262,6 +264,10 @@ final class ModifierImpl implements ModelActionBuilder {
     public void apply(final InferenceAction action) {
         checkState(this.action == null, "Action already defined to %s", this.action);
         this.action = requireNonNull(action);
+        if (bootstraps != null) {
+            bootstraps.forEach(Runnable::run);
+            bootstraps = null;
+        }
     }
 
     private abstract class AbstractPrerequisite<T> implements Prerequisite<T> {
@@ -320,7 +326,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();
         }
     }
 
@@ -349,7 +355,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
@@ -426,7 +432,9 @@ final class ModifierImpl implements ModelActionBuilder {
 
             if (!it.hasNext()) {
                 // Last step: we are done
-                resolvePrereq((C) value);
+                if (resolvePrereq((C) value)) {
+                    tryApply();
+                }
                 return;
             }