/**
   * Restore an XFormsContainingDocument from XFormsState only.
   *
   * <p>Used by XFormsStateManager.
   *
   * @param xformsState XFormsState containing static and dynamic state
   * @param disableUpdates whether to disable updates (for recreating initial document upon browser
   *     back)
   */
  public XFormsContainingDocument(XFormsState xformsState, boolean disableUpdates) {
    super();

    // 1. Restore the static state
    {
      final scala.Option<String> staticStateDigest = xformsState.staticStateDigest();

      if (staticStateDigest.isDefined()) {
        final XFormsStaticState cachedState =
            XFormsStaticStateCache.instance().getDocument(staticStateDigest.get());
        if (cachedState != null) {
          // Found static state in cache
          indentedLogger().logDebug("", "found static state by digest in cache");
          this.staticState = cachedState;
        } else {
          // Not found static state in cache, create static state from input
          indentedLogger().logDebug("", "did not find static state by digest in cache");
          indentedLogger().startHandleOperation("initialization", "restoring static state");
          this.staticState =
              XFormsStaticStateImpl.restore(staticStateDigest, xformsState.staticState());
          indentedLogger().endHandleOperation();

          // Store in cache
          XFormsStaticStateCache.instance().storeDocument(this.staticState);
        }

        assert this.staticState.isServerStateHandling();
      } else {
        // Not digest provided, create static state from input
        indentedLogger().logDebug("", "did not find static state by digest in cache");
        this.staticState =
            XFormsStaticStateImpl.restore(staticStateDigest, xformsState.staticState());

        assert this.staticState.isClientStateHandling();
      }

      this.staticOps = new StaticStateGlobalOps(staticState.topLevelPart());
      this.xpathDependencies = Version.instance().createUIDependencies(this);

      this.supportUpdates = !disableUpdates && !isNoUpdates();
    }

    // 2. Restore the dynamic state
    indentedLogger().startHandleOperation("initialization", "restoring containing document");
    try {
      restoreDynamicState(xformsState.dynamicState());
    } catch (Exception e) {
      throw OrbeonLocationException.wrapException(
          e, new ExtendedLocationData(null, "re-initializing XForms containing document"));
    }
    indentedLogger().endHandleOperation();
  }
  /**
   * Create an XFormsContainingDocument from an XFormsStaticState object.
   *
   * <p>Used by XFormsToXHTML.
   *
   * @param staticState static state object
   * @param uriResolver URIResolver for loading instances during initialization (and possibly more,
   *     such as schemas and "GET" submissions upon initialization)
   * @param response optional response for handling replace="all" during initialization
   */
  public XFormsContainingDocument(
      XFormsStaticState staticState,
      XFormsURIResolver uriResolver,
      ExternalContext.Response response) {
    super();

    // Create UUID for this document instance
    this.uuid = SecureUtils.randomHexId();

    // Initialize request information
    {
      initializeRequestInformation();
      initializePathMatchers();
    }

    indentedLogger()
        .startHandleOperation(
            "initialization",
            "creating new ContainingDocument (static state object provided).",
            "uuid",
            this.uuid);
    {
      // Remember static state
      this.staticState = staticState;
      this.staticOps = new StaticStateGlobalOps(staticState.topLevelPart());

      // NOTE: template is not stored right away, as it depends on the evaluation of the noscript
      // property.

      this.xpathDependencies = Version.instance().createUIDependencies(this);

      // Whether we support updates
      // NOTE: Reading the property requires the static state set above
      this.supportUpdates = !isNoUpdates();

      // Remember parameters used during initialization
      this.uriResolver = uriResolver;
      this.response = response;
      this.initializing = true;

      // Initialize the containing document
      try {
        initialize();
      } catch (Exception e) {
        throw OrbeonLocationException.wrapException(
            e, new ExtendedLocationData(null, "initializing XForms containing document"));
      }
    }
    indentedLogger().endHandleOperation();
  }