com.formkiq.core.webflow.FlowManager.java Source code

Java tutorial

Introduction

Here is the source code for com.formkiq.core.webflow.FlowManager.java

Source

/*
 * Copyright (C) 2017 FormKiQ Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.formkiq.core.webflow;

import static com.formkiq.core.util.CollectionUtil.last;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.tuple.Pair;
import org.springframework.util.StringUtils;

import com.formkiq.core.form.tokenizer.TokenType;
import com.formkiq.core.form.tokenizer.TokenizerService;
import com.formkiq.core.form.tokenizer.TokenizerServiceImpl;
import com.formkiq.core.form.tokenizer.TokenizerToken;

/**
 * Class to Manage {@link WebFlow}s.
 *
 */
public final class FlowManager {

    /** Flow Execution Parameter. */
    public static final String PARAMETER_EXECUTION = "execution";

    /** Session Variable for the max Web flow ID. */
    public static final String WEBFLOW_SESSION_ID = "FK_WEBFLOW_ID";

    /**
     * Finish Flow.
     * @param request {@link HttpServletRequest}
     */
    public static void finish(final HttpServletRequest request) {

        WebFlow flow = getCurrentWebFlow(request);
        request.getSession().removeAttribute(getExecutionSessionKey(flow.getSessionKey()).getLeft());
    }

    /**
     * Gets the current {@link WebFlow} or create a new one.
     * @param request {@link HttpServletRequest}
     * @return {@link WebFlow}
     */
    public static WebFlow get(final HttpServletRequest request) {
        return getCurrentWebFlow(request);
    }

    /**
     * Finds the current {@link WebFlow} if one exists.
     * @param req {@link HttpServletRequest}
     * @return {@link WebFlow}
     */
    private static WebFlow getCurrentWebFlow(final HttpServletRequest req) {

        Pair<String, Integer> webflowkey = getExecutionSessionKey(req.getParameter(PARAMETER_EXECUTION));
        String sessionKey = webflowkey.getLeft();

        if (StringUtils.hasText(sessionKey)) {
            Object obj = req.getSession().getAttribute(sessionKey);
            if (obj instanceof WebFlow) {
                WebFlow wf = (WebFlow) obj;
                return wf;
            }
        }

        throw new FlowNotFoundException();
    }

    /**
     * Get Event Id.
     * @param request {@link HttpServletRequest}
     * @return int
     */
    public static int getEventId(final HttpServletRequest request) {
        Pair<String, Integer> webflowkey = getExecutionSessionKey(request.getParameter(PARAMETER_EXECUTION));
        Integer eventId = webflowkey.getRight();
        return eventId != null ? eventId.intValue() : 1;
    }

    /**
     * Gets the SessionKey from the Execution Parameter.
     * @param webflowkey {@link String}
     * @return {@link Pair}
     */
    public static Pair<String, Integer> getExecutionSessionKey(final String webflowkey) {

        String s = null;
        Integer e = null;

        if (StringUtils.hasText(webflowkey)) {
            TokenizerService ts = new TokenizerServiceImpl(webflowkey);
            Optional<TokenizerToken> session = ts.nextToken();
            Optional<TokenizerToken> sessionNo = ts.nextToken();
            Optional<TokenizerToken> event = ts.nextToken();
            Optional<TokenizerToken> eventNo = ts.nextToken();

            boolean tokensPresent = session.isPresent() && sessionNo.isPresent() && event.isPresent()
                    && eventNo.isPresent();

            if (tokensPresent && session.get().getType().equals(TokenType.STRING)
                    && sessionNo.get().getType().equals(TokenType.INTEGER)
                    && event.get().getType().equals(TokenType.STRING)
                    && eventNo.get().getType().equals(TokenType.INTEGER)) {
                s = session.get().getValue() + sessionNo.get().getValue();
                e = Integer.valueOf(eventNo.get().getValue());
            }
        }

        return Pair.of(s, e);
    }

    /**
     * Gets the Next WebFlow Session Id.
     * @param req {@link HttpServletRequest}
     * @return int
     */
    private static int getNextWebFlowSessionId(final HttpServletRequest req) {

        int sessionId = 1;
        HttpSession session = req.getSession();
        Object sessionOb = session.getAttribute(WEBFLOW_SESSION_ID);

        if (sessionOb != null) {
            try {
                sessionId = Integer.parseInt(sessionOb.toString()) + 1;
            } catch (NumberFormatException e) {
                sessionId = 1;
            }
        }

        session.setAttribute(WEBFLOW_SESSION_ID, String.valueOf(sessionId));

        return sessionId;
    }

    /**
     * Start new WebFlow.
     * @param <T> {@link FlowEventProcessor}
     * @param request {@link HttpServletRequest}
     * @param eventProcessor Class
     * @param states {@link List}
     * @return {@link WebFlow}
     */
    public static <T extends FlowEventProcessor> WebFlow start(final HttpServletRequest request,
            final Class<T> eventProcessor, final List<FlowState> states) {

        if (states.isEmpty()) {
            throw new IllegalArgumentException("states is empty");
        }

        List<FlowState> newstates = new ArrayList<>(states);
        if (!FlowStateType.START.equals(newstates.get(0).getType())) {
            newstates.add(0, new FlowState(FlowStateType.START));
        }

        if (!FlowStateType.START.equals(newstates.get(0).getType())) {
            newstates.add(0, new FlowState(FlowStateType.START));
        }

        if (!last(newstates).isEnd()) {
            newstates.add(new FlowState(FlowStateType.END));
        }

        int webflowSessionID = getNextWebFlowSessionId(request);

        WebFlow flow = new WebFlow(webflowSessionID, eventProcessor, newstates);

        request.getSession().setAttribute(getExecutionSessionKey(flow.getSessionKey()).getLeft(), flow);

        return flow;
    }

    /**
     * Transition WebFlow.
     * @param request {@link HttpServletRequest}
     * @param transition {@link FlowTransition}
     * @return {@link WebFlow}
     */
    public static WebFlow transition(final HttpServletRequest request, final FlowTransition transition) {

        WebFlow flow = getCurrentWebFlow(request);
        int eventId = flow.getEventId();

        if (FlowTransition.BACKWARD.equals(transition)) {
            flow.setEventId(Math.max(1, eventId - 1));
        } else if (FlowTransition.FORWARD.equals(transition)) {
            flow.setEventId(Math.max(1, eventId + 1));
        }

        return flow;
    }

    /**
     * private constructor.
     */
    private FlowManager() {
    }
}