public PageFlowController createPageFlow()

in ti/phase2/jars/core/src/java/org/apache/ti/pageflow/FlowControllerFactory.java [155:309]


    public PageFlowController createPageFlow(Class pageFlowClass)
            throws InstantiationException, IllegalAccessException {
        if (!PageFlowController.class.isAssignableFrom(pageFlowClass)) {
            return null;
        }

        //
        // First check if this is a request for a "long lived" page flow.  If so, try
        // PageFlowUtils.getCurrentPageFlow again, with the longLived flag.
        //
        PageFlowController retVal = null;
        String namespace = InternalUtils.inferNamespaceFromClassName(pageFlowClass.getName());
        ModuleRegistrationHandler mrh = Handlers.get().getModuleRegistrationHandler();
        ModuleConfig mc = mrh.getModuleConfig(namespace);

        if (mc == null) {
            _log.error("Struts module " + namespace + " not found for " + pageFlowClass.getName() + "; cannot create page flow.");

            return null;
        }

        if (mc.isLongLivedFlow()) {
            retVal = PageFlowUtils.getLongLivedPageFlow(namespace);

            if (_log.isDebugEnabled()) {
                if (retVal != null) {
                    _log.debug("Using long lived PageFlowController of type " + pageFlowClass.getName());
                }
            }
        }

        //
        // First, see if this is a nested page flow that's already on the stack.  Unless "renesting" is explicitly
        // enabled, we don't want to allow another instance of this page flow to be nested.  This is a common
        // browser back-button problem:
        //    1) request nested page flow A
        //    2) request nested page flow B
        //    3) press back button, and execute an action on A.
        //
        // This logic does not deal with immediate self-nesting (A->A), which is taken care of in
        // PageFlowController.forwardTo().  Nested page flows can only self-nest by forwarding to the .jpf URI, not
        // indirectly by executing actions on themselves (think about it -- that would be a disaster).
        //
        boolean createdNew = false;
        boolean isNestable = mc.isNestedFlow();
        PageFlowStack pfStack = PageFlowStack.get(false);

        if (isNestable && (pfStack != null)) {
            PageFlowConfig options = ConfigUtil.getConfig().getPageFlowConfig();

            if ((options == null) || !options.isEnableSelfNesting()) {
                int lastIndexOfJpfClass = pfStack.lastIndexOf(pageFlowClass);

                if (lastIndexOfJpfClass != -1) {
                    retVal = pfStack.popUntil(lastIndexOfJpfClass);
                    retVal.persistInSession();

                    return retVal;
                }
            }
        }

        //
        // OK, if it's not an existing long lived page flow, and if this wasn't a nested page flow already on the
        // stack, then create a new instance.
        //
        if (retVal == null) {
            if (_log.isDebugEnabled()) {
                _log.debug("Creating PageFlowController of type " + pageFlowClass.getName());
            }

            retVal = (PageFlowController) getFlowControllerInstance(pageFlowClass);
            createdNew = true;
        }

        //
        // Store the previous PageFlowController on the nesting stack (if this one is nestable),
        // or destroy the nesting stack.
        //
        if (isNestable) {
            //
            // Call create() on the newly-created page flow.
            //
            if (createdNew) {
                retVal.create();
            }

            PageFlowController current = PageFlowUtils.getCurrentPageFlow();

            if (current != null) {
                if (_log.isDebugEnabled()) {
                    _log.debug("Pushing PageFlowController " + current + " onto the nesting stack");
                }

                if (pfStack == null) {
                    pfStack = PageFlowStack.get(true);
                }

                pfStack.push(current);
            }

            retVal.reinitialize();
            retVal.persistInSession();
        } else {
            //
            // Going to a non-nested pageflow.  Blow away the pageflow stack.
            //
            if (pfStack != null) {
                if (_log.isDebugEnabled()) {
                    _log.debug("Destroying the PageFlowController stack.");
                }

                //
                // Start popping page flows until 1) there are none left on the stack, or 2) we find
                // one of the type we're returning.  If (2), we'll use that one (this means that executing
                // an action on a nesting page flow while in a nested one will not destroy the nesting
                // page flow only to create a new instance of it).
                //
                PageFlowController onStackAlready = pfStack.popUntil(retVal.getClass());

                if (onStackAlready != null) {
                    if (_log.isDebugEnabled()) {
                        _log.debug("Found a page flow of type " + retVal.getClass() + " in the stack; " +
                                   "using that instance and stopping destruction of the nesting stack.");
                    }

                    retVal = onStackAlready;
                    retVal.persistInSession();
                } else {
                    //
                    // We're actually using the newly-created page flow, so call create() on it.
                    // Note that we make the call to persistInSession *before* create, so the previous flow's
                    // onDestroy() gets called before the new one's onCreate().
                    //
                    retVal.reinitialize();
                    retVal.persistInSession();
                    retVal.create();
                }
            } else {
                //
                // We're actually using the newly-created page flow, so call create() on it (*after* persisting
                // in the session so the previous page flow's onDestroy() gets called before the new one's
                // onCreate()).
                //
                retVal.reinitialize();
                retVal.persistInSession();

                if (createdNew) {
                    retVal.create();
                }
            }
        }

        return retVal;
    }