Class FormSession

java.lang.Object
com.axelor.meta.headless.FormSession

public final class FormSession extends Object
A form on a record, run on the server: steps change the record and its lines and run the chains the form declares for them, each in the context of the record or line it acts on, as the web client runs it.

A step is made of moves, each at most one chain or one question — Set: the value, then its onChange; Click: the prompt, then the onClick; Add: the defaults and the line's onNew, then the seed; Save: onSave, the save, onLoad. The session records the move before running it, so a run suspended at a question resumes after it.

A line is open from the first step that touches it until the session commits it — before a step touches another node, before a save, or on Commit. Committing a changed line runs its collection's onChange in the parent's context, as the browser does when the user leaves an edited row. Commits are moves of the step that caused them.

Not thread-safe; a session is used by one caller at a time. Keep state() to carry a suspended session across requests.

  • Method Details

    • spec

      public FormSpec spec()
    • added

      public List<Long> added()
      The cid of each line the Add steps created, in the order they ran; not the lines the form's own actions bring, though those take cids too.
    • record

      public Map<String,Object> record()
      The record and its lines as the session holds them now, saved or not.
    • stored

      public Map<String,Object> stored()
      The record and its lines as the database last gave them: as the session loaded them, or as read back after its last save. What record() holds beyond them is not saved.
    • afterSave

      public Map<String,Object> afterSave()
      The record and its lines as the session's last save left them: read back, then with what the onLoad after the save set, which leaves a browser's form changed too though nothing is left to save. As loaded before any save. What record() holds beyond them was changed since.
    • context

      public Map<String,Object> context(String node)
      The context a chain run at a node would carry now, as the client builds it: the node's record, shaped as sent, with the form's keys at the root and _parent for a line. For evaluating an expression as the form's own actions would see it.
      Parameters:
      node - the node's path; blank for the root
      Throws:
      IllegalArgumentException - when the path names no node
    • seededContext

      public Map<String,Object> seededContext()
      The root's context as a run finds the record once it is open, without running anything: the record with the target's seed merged in, as the first run merges it after the open hook. For reading a guard before any of the form runs; the session is left as it was.
    • isSuspended

      public boolean isSuspended()
      Whether the session is stopped at an open question.
    • run

      public FormResult run(List<FormStep> steps, ActionInteraction interaction)
      Runs steps, in order, until they are done or the run stops.

      Steps are checked against the spec first (FormSpec.check(com.axelor.meta.headless.FormStep)); the first problem refuses the run before anything runs. A path is resolved when its step runs. On the session's first run, the open hook runs first — onNew for a new record, onLoad for a saved one — then the target's seed is written.

      Parameters:
      steps - the steps
      interaction - answers where the browser would ask the user
      Throws:
      IllegalStateException - when the session is suspended
    • resume

      public FormResult resume(Decision answer, ActionInteraction interaction)
      Answers the open question and carries on where the run stopped, with the record as it was held when it stopped.
      Parameters:
      answer - Decision.CONTINUE or Decision.CANCEL
      interaction - answers later questions
      Throws:
      IllegalStateException - when the session is not suspended
    • state

      public FormState state()
      Everything needed to carry on later: see HeadlessForms.restore(com.axelor.meta.headless.FormState).