Cache substatement context-independence summary
[yangtools.git] / yang / yang-parser-reactor / src / main / java / org / opendaylight / yangtools / yang / parser / stmt / reactor / StatementContextBase.java
index 7ccad2490fb9955d9840aee4106436af6e0349b3..19837d22874d475ceeeb1c4bc704847778e619b6 100644 (file)
@@ -423,6 +423,9 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
      */
     private void onPhaseCompleted(final ModelProcessingPhase phase) {
         completedPhase = phase;
+        if (phase == ModelProcessingPhase.EFFECTIVE_MODEL) {
+            summarizeSubstatementPolicy();
+        }
 
         final Collection<OnPhaseFinished> listeners = phaseListeners.get(phase);
         if (!listeners.isEmpty()) {
@@ -430,6 +433,52 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
         }
     }
 
+    private void summarizeSubstatementPolicy() {
+        if (noSensitiveSubstatements()) {
+            setAllSubstatementsContextIndependent();
+        }
+    }
+
+    /**
+     * Determine whether any substatements are context-sensitive as determined by {@link StatementSupport#copyPolicy()}.
+     * Only {@link CopyPolicy#CONTEXT_INDEPENDENT} and {@link CopyPolicy#IGNORE} are context-insensitive. Note that
+     * statements which are not {@link StmtContext#isSupportedToBuildEffective()} are all considered
+     * context-insensitive.
+     *
+     * <p>
+     * Implementations are expected to call {@link #noSensitiveSubstatements()} to actually traverse substatement sets.
+     *
+     * @return True if no substatements require context-sensitive handling
+     */
+    abstract boolean noSensitiveSubstatements();
+
+    /**
+     * Determine whether any of the provided substatements are context-sensitive for purposes of implementing
+     * {@link #noSensitiveSubstatements()}.
+     *
+     * @param substatements Substatements to check
+     * @return True if no substatements require context-sensitive handling
+     */
+    static boolean noSensitiveSubstatements(final Collection<? extends ReactorStmtCtx<?, ?, ?>> substatements) {
+        for (ReactorStmtCtx<?, ?, ?> stmt : substatements) {
+            if (stmt.isSupportedToBuildEffective()) {
+                if (!stmt.allSubstatementsContextIndependent()) {
+                    // This is a recursive property
+                    return false;
+                }
+
+                switch (stmt.definition().support().copyPolicy()) {
+                    case CONTEXT_INDEPENDENT:
+                    case IGNORE:
+                        break;
+                    default:
+                        return false;
+                }
+            }
+        }
+        return true;
+    }
+
     private void runPhaseListeners(final ModelProcessingPhase phase, final Collection<OnPhaseFinished> listeners) {
         final Iterator<OnPhaseFinished> listener = listeners.iterator();
         while (listener.hasNext()) {
@@ -643,17 +692,6 @@ public abstract class StatementContextBase<A, D extends DeclaredStatement<A>, E
             && allSubstatementsContextIndependent();
     }
 
-    // FIXME: YANGTOOLS-1195: we really want to compute (and cache) the summary for substatements.
-    //
-    // For now we just check if there are any substatements, but we really want to ask:
-    //
-    //   Are all substatements (recursively) CONTEXT_INDEPENDENT as well?
-    //
-    // Which is something we want to compute once and store. This needs to be implemented.
-    private boolean allSubstatementsContextIndependent() {
-        return hasEmptySubstatements();
-    }
-
     @Override
     public final Mutable<?, ?, ?> childCopyOf(final StmtContext<?, ?, ?> stmt, final CopyType type,
             final QNameModule targetModule) {