Class LlmDataLoader.RunScope

java.lang.Object
io.jmix.reports.libintegration.LlmDataLoader.RunScope
Enclosing class:
LlmDataLoader

protected static class LlmDataLoader.RunScope extends Object
What one report run has already done, so that loading a band once per parent row does not repeat it: the queries already read for it and the warnings already written for it.

A run is recognised by the band data its hierarchy is rooted at. Reaching a different root means another run has started on this thread, and everything remembered for the previous one is dropped — which is also what keeps the scope from outliving the run on a pooled thread.

  • Field Details

    • rootBand

      protected WeakReference<@Nullable BandData> rootBand
    • storedQueries

      protected Map<String,Optional<LlmDataQuery>> storedQueries
    • storeNames

      protected Map<String,String> storeNames
    • inParameters

      protected Map<String,Set<String>> inParameters
    • rowLevelJpql

      protected Map<String,String> rowLevelJpql
    • entityReadChecked

      protected Set<String> entityReadChecked
    • queryChecked

      protected Set<String> queryChecked
    • warnings

      protected Map<ReportQuery,Set<String>> warnings
      Held weakly, as the root band is and for the same reason: a data set belongs to a report, whose bands, parameters and templates — the content of a template included — would otherwise stay reachable from a pooled thread until another run replaces the scope.
  • Constructor Details

    • RunScope

      protected RunScope()
  • Method Details

    • rootedAt

      protected void rootedAt(@Nullable BandData rootBand)
    • storedQuery

      protected @Nullable LlmDataQuery storedQuery(String document, Supplier<@Nullable LlmDataQuery> read)
      Returns what a stored document reads as, reading each document once. A band under a parent is loaded once per parent row, and the document does not change while the run reads it, so parsing it again per row is work the run does not need. A document that reads as nothing is remembered as such.
    • storeName

      protected String storeName(String jpql, Supplier<String> resolve)
      Returns the store a query text runs in, working it out once per text: telling the store means parsing the query, and a band under a parent is loaded once per parent row.
    • parametersMatchedWithIn

      protected Set<String> parametersMatchedWithIn(String jpql, Supplier<Set<String>> read)
      Returns the parameters a query text matches with IN, reading each text once: telling them apart means scanning the query, which no row of a parent band changes.
    • rowLevelJpql

      protected String rowLevelJpql(String jpql, Supplier<String> weave)
      Returns the text to execute for a stored query text, weaving the row-level policies into it once: the policies of a run do not change between the rows of a parent band, and weaving them parses the query.
    • entityReadChecked

      protected void entityReadChecked(String jpql, Runnable check)
      Runs the entity-read check once per query text: the permissions of a run do not change between the rows of a parent band, and the check parses the query to find the entities it reads.
    • queryChecked

      protected void queryChecked(String jpql, Runnable check)
      Runs the barrier once per query text: what makes a text unfit to execute does not change between the rows of a parent band, and establishing it parses and scans the query.
    • checkedOnce

      protected void checkedOnce(Set<String> passed, String jpql, Runnable check)
      Runs a check the first time a query text reaches it, remembering it only once it has passed: a refusal must be raised again for every data set and every parent row that reaches this query, not swallowed because the first attempt already ran.
    • warnOnce

      protected void warnOnce(ReportQuery reportQuery, String reason, Runnable warning)
      Writes a warning the first time this data set runs into it. Remembered per data set rather than per name: a data set name is unique only within its band, so two bands can each hold a dataSet1, and what one of them has already said must not silence the other. The data set is the one the engine is loading, so it stays reachable for as long as the run needs the entry.