public void addServerError(XFormsError.ServerError serverError) {
    final int maxErrors = getShowMaxRecoverableErrors();
    if (maxErrors > 0) {
      if (serverErrors == null) serverErrors = new ArrayList<XFormsError.ServerError>();

      if (serverErrors.size() < maxErrors) serverErrors.add(serverError);
    }
  }
  public void addScriptToRun(
      org.orbeon.oxf.xforms.Script script, XFormsEvent event, XFormsEventObserver eventObserver) {

    if (activeSubmissionFirstPass != null
        && StringUtils.isBlank(activeSubmissionFirstPass.getResolvedXXFormsTarget())) {
      // Scripts occurring after a submission without a target takes place should not run
      // TODO: Should we allow scripts anyway? Don't we allow value changes updates on the client
      // anyway?
      indentedLogger()
          .logWarning(
              "",
              "xxf:script will be ignored because two-pass submission started",
              "script id",
              script.prefixedId());
      return;
    }

    // Warn that scripts won't run in noscript mode (duh)
    if (noscript())
      indentedLogger()
          .logWarning(
              "noscript", "script won't run in noscript mode", "script id", script.prefixedId());

    if (scriptsToRun == null) scriptsToRun = new ArrayList<Script>();
    scriptsToRun.add(new Script(script.clientName(), event, eventObserver));
  }
  /** Add an XForms load to send to the client. */
  public void addLoadToRun(
      String resource, String target, String urlType, boolean isReplace, boolean isShowProgress) {

    if (activeSubmissionFirstPass != null)
      throw new ValidationException(
          "Unable to run a two-pass submission and xf:load within a same action sequence.",
          activeSubmissionFirstPass.getLocationData());

    if (loadsToRun == null) loadsToRun = new ArrayList<Load>();
    loadsToRun.add(new Load(resource, target, urlType, isReplace, isShowProgress));
  }
  /**
   * Schedule an event for delayed execution, following xf:dispatch/@delay semantics.
   *
   * @param eventName name of the event to dispatch
   * @param targetEffectiveId id of the target to dispatch to
   * @param bubbles whether the event bubbles
   * @param cancelable whether the event is cancelable
   * @param delay delay after which to dispatch the event
   * @param isMaxDelay whether the delay indicates a maximum delay
   * @param showProgress whether to show the progress indicator when submitting the event
   * @param progressMessage message to show if the progress indicator is visible
   */
  public void addDelayedEvent(
      String eventName,
      String targetEffectiveId,
      boolean bubbles,
      boolean cancelable,
      int delay,
      boolean isMaxDelay,
      boolean showProgress,
      String progressMessage) {
    if (delayedEvents == null) delayedEvents = new ArrayList<DelayedEvent>();

    delayedEvents.add(
        new DelayedEvent(
            eventName,
            targetEffectiveId,
            bubbles,
            cancelable,
            System.currentTimeMillis() + delay,
            isMaxDelay,
            showProgress,
            progressMessage));
  }
 /** Add an XForms message to send to the client. */
 public void addMessageToRun(String message, String level) {
   if (messagesToRun == null) messagesToRun = new ArrayList<Message>();
   messagesToRun.add(new Message(message, level));
 }