Class DesignPreflightReport

java.lang.Object
ubic.gemma.model.expression.experiment.DesignPreflightReport
All Implemented Interfaces:
Serializable

public class DesignPreflightReport extends Object implements Serializable
Report returned by POST /datasets/{id}/designPreflight. Predicts what would happen if the accompanying proposed ExperimentalDesignValueObject were PUT to /datasets/{id}/design.

Contract:

  • blockers non-empty ⇒ the corresponding PUT would return 4xx. Caller must fix the payload.
  • blockers empty AND requiresForce() false ⇒ PUT would succeed without ?force=true.
  • blockers empty AND requiresForce() true ⇒ PUT needs ?force=true (admin) to consent to the consequences.
Author:
ogan
See Also:
  • Constructor Details

    • DesignPreflightReport

      public DesignPreflightReport()
  • Method Details

    • requiresForce

      public boolean requiresForce()
      Whether applying this change needs explicit consent (?force=true, admin) rather than proceeding silently. True when the change would delete differential-expression analyses, or would leave a subset defined by factor values that no longer exist.

      Subsets are included deliberately. A cascade-deleted analysis is gone, and gone announces itself — somebody re-runs it. An orphaned subset is still there, still named, still listed, and now anchored on factor values that were deleted out from under it: it reads as valid. A false prompt costs a curator one force=true; a false silence costs a subset that nobody notices is wrong until it produces a wrong answer.

      Consent is per-request, not per-consequence: a caller that forces past an analysis cascade also forces past a stale anchor. Callers should therefore surface differentialExpressionAnalysesToDelete and subsetsWithStaleAnchor separately so the curator sees which they are agreeing to.

    • getBlockers

      public List<DesignPreflightReport.Blocker> getBlockers()
      Hard validation errors. A non-empty list means the PUT would be rejected; fix the payload and re-run.
    • getSummary

      public DesignPreflightReport.Summary getSummary()
    • getFactorsToDelete

      public List<DesignPreflightReport.EntityRef> getFactorsToDelete()
    • getFactorValuesToDelete

      public List<DesignPreflightReport.EntityRef> getFactorValuesToDelete()
    • getFactorsToUpdate

      public List<DesignPreflightReport.EntityRef> getFactorsToUpdate()
      Kept factors whose name, description or category the proposal rewrites.

      Nothing is created or deleted by such an edit, so every counter above it stays at zero and the report used to describe a real change as unchanged. The apply path has always performed these — see isNoOpDesignApply, which consults the same comparison — so the gap was in what the report could say, not in what a PUT would do.

    • getFactorValuesToUpdate

      public List<DesignPreflightReport.EntityRef> getFactorValuesToUpdate()
      Kept factor values the proposal edits in place: a statement re-termed, evidence attached, the baseline flag flipped, a measurement retimed, the deprecated free-text value rewritten.

      cab hit the gap on GSE49354.1 (2026-08-27): re-terming one factor value's subject URI preflighted as {created: 0, updated: 0, deleted: 0, unchanged: 1}, which reads as "nothing to do" for an edit that a PUT would in fact apply.

    • getDifferentialExpressionAnalysesToDelete

      public List<DesignPreflightReport.AnalysisRef> getDifferentialExpressionAnalysesToDelete()
    • getSubsetsWithStaleAnchor

      public List<DesignPreflightReport.SubsetRef> getSubsetsWithStaleAnchor()
      Subsets whose definitional factor-value anchors would be deleted. These are not blockers (subsets carry no FK to FactorValue), but their semantics drift after the change, so they require the same explicit consent as the analysis cascade — see requiresForce().
    • setBlockers

      public void setBlockers(List<DesignPreflightReport.Blocker> blockers)
      Hard validation errors. A non-empty list means the PUT would be rejected; fix the payload and re-run.
    • setSummary

      public void setSummary(DesignPreflightReport.Summary summary)
    • setFactorsToDelete

      public void setFactorsToDelete(List<DesignPreflightReport.EntityRef> factorsToDelete)
    • setFactorValuesToDelete

      public void setFactorValuesToDelete(List<DesignPreflightReport.EntityRef> factorValuesToDelete)
    • setFactorsToUpdate

      public void setFactorsToUpdate(List<DesignPreflightReport.EntityRef> factorsToUpdate)
      Kept factors whose name, description or category the proposal rewrites.

      Nothing is created or deleted by such an edit, so every counter above it stays at zero and the report used to describe a real change as unchanged. The apply path has always performed these — see isNoOpDesignApply, which consults the same comparison — so the gap was in what the report could say, not in what a PUT would do.

    • setFactorValuesToUpdate

      public void setFactorValuesToUpdate(List<DesignPreflightReport.EntityRef> factorValuesToUpdate)
      Kept factor values the proposal edits in place: a statement re-termed, evidence attached, the baseline flag flipped, a measurement retimed, the deprecated free-text value rewritten.

      cab hit the gap on GSE49354.1 (2026-08-27): re-terming one factor value's subject URI preflighted as {created: 0, updated: 0, deleted: 0, unchanged: 1}, which reads as "nothing to do" for an edit that a PUT would in fact apply.

    • setDifferentialExpressionAnalysesToDelete

      public void setDifferentialExpressionAnalysesToDelete(List<DesignPreflightReport.AnalysisRef> differentialExpressionAnalysesToDelete)
    • setSubsetsWithStaleAnchor

      public void setSubsetsWithStaleAnchor(List<DesignPreflightReport.SubsetRef> subsetsWithStaleAnchor)
      Subsets whose definitional factor-value anchors would be deleted. These are not blockers (subsets carry no FK to FactorValue), but their semantics drift after the change, so they require the same explicit consent as the analysis cascade — see requiresForce().