org.beangle.struts2.convention.result.DefaultResultBuilder.java Source code

Java tutorial

Introduction

Here is the source code for org.beangle.struts2.convention.result.DefaultResultBuilder.java

Source

/* Copyright c 2005-2012.
 * Licensed under GNU  LESSER General Public License, Version 3.
 * http://www.gnu.org/licenses
 */
package org.beangle.struts2.convention.result;

import static org.beangle.web.util.RequestUtils.getServletPath;

import java.util.LinkedHashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.struts2.ServletActionContext;
import org.apache.struts2.dispatcher.ServletRedirectResult;
import org.beangle.struts2.convention.route.Action;
import org.beangle.struts2.convention.route.ActionBuilder;
import org.beangle.struts2.convention.route.ProfileService;
import org.beangle.struts2.convention.route.ViewMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.Result;
import com.opensymphony.xwork2.XWorkException;
import com.opensymphony.xwork2.config.Configuration;
import com.opensymphony.xwork2.config.entities.ActionConfig;
import com.opensymphony.xwork2.config.entities.PackageConfig;
import com.opensymphony.xwork2.config.entities.ResultConfig;
import com.opensymphony.xwork2.config.entities.ResultTypeConfig;
import com.opensymphony.xwork2.inject.Inject;

/**
 * ??result?<br>
 * 1)chain:/xxx?param1=value1&param2=value2<br>
 * 2)redirectAction:/yyy!method.action?param1=value1&param2=value2<br>
 * 2)redirect:/yyy!methodd?param1=value1&param2=value2<br>
 * 3)path/to/page/page.ftl<br>
 * 
 * @author chaostone
 */
public class DefaultResultBuilder implements ResultBuilder {

    private static final Logger logger = LoggerFactory.getLogger(DefaultResultBuilder.class);

    protected Map<String, ResultTypeConfig> resultTypeConfigs;

    @Inject
    protected ObjectFactory objectFactory;

    @Inject
    protected Configuration configuration;

    @Inject
    protected ViewMapper viewMapper;

    @Inject
    protected ProfileService profileService;

    @Inject
    protected ActionBuilder actionNameBuilder;

    public Result build(String resultCode, ActionConfig actionConfig, ActionContext context) {
        String path = null;
        ResultTypeConfig resultTypeConfig = null;

        logger.debug("result code:{} for actionConfig:{}", resultCode, actionConfig);
        if (null == resultTypeConfigs) {
            PackageConfig pc = configuration.getPackageConfig(actionConfig.getPackageName());
            this.resultTypeConfigs = pc.getAllResultTypeConfigs();
        }
        // prefix
        // TODO jsp,vm,ftl
        if (!StringUtils.contains(resultCode, ':')) {
            String className = context.getActionInvocation().getProxy().getAction().getClass().getName();
            String methodName = context.getActionInvocation().getProxy().getMethod();
            if (StringUtils.isEmpty(resultCode)) {
                resultCode = "index";
            }
            StringBuilder buf = new StringBuilder();
            buf.append(viewMapper.getViewPath(className, methodName, resultCode));
            buf.append('.');
            buf.append(profileService.getProfile(className).getViewExtension());
            path = buf.toString();
            resultTypeConfig = resultTypeConfigs.get("freemarker");
            return buildResult(resultCode, resultTypeConfig, context, buildResultParams(path, resultTypeConfig));
        } else {
            String prefix = StringUtils.substringBefore(resultCode, ":");
            resultTypeConfig = (ResultTypeConfig) resultTypeConfigs.get(prefix);
            if (prefix.startsWith("chain")) {
                Action action = buildAction(StringUtils.substringAfter(resultCode, ":"));
                Map<String, String> params = buildResultParams(path, resultTypeConfig);
                addNamespaceAction(action, params);
                if (StringUtils.isNotEmpty(action.getMethod())) {
                    params.put("method", action.getMethod());
                }
                return buildResult(resultCode, resultTypeConfig, context, params);
            } else if (prefix.startsWith("redirect")) {
                String targetResource = StringUtils.substringAfter(resultCode, ":");
                if (StringUtils.contains(targetResource, ':')) {
                    return new ServletRedirectResult(targetResource);
                }
                Action action = buildAction(targetResource);
                // add special param and ajax tag for redirect
                HttpServletRequest request = ServletActionContext.getRequest();
                String redirectParamStr = request.getParameter("params");
                action.params(redirectParamStr);
                if (redirectParamStr != null && !"null".equals(redirectParamStr)) {
                    action.param("params", redirectParamStr);
                }
                // x-requested-with->XMLHttpRequest
                if (null != request.getHeader("x-requested-with")) {
                    action.param("x-requested-with", "1");
                }
                Map<String, String> params = buildResultParams(path, resultTypeConfig);
                if (null != action.getParams().get("method")) {
                    params.put("method", (String) action.getParams().get("method"));
                    action.getParams().remove("method");
                }
                if (StringUtils.isNotEmpty(action.getMethod())) {
                    params.put("method", action.getMethod());
                }
                addNamespaceAction(action, params);

                ServletRedirectResult result = (ServletRedirectResult) buildResult(resultCode, resultTypeConfig,
                        context, params);
                for (Map.Entry<String, String> param : action.getParams().entrySet()) {
                    String property = param.getKey();
                    result.addParameter(property, param.getValue());
                }
                return result;
            } else {
                return buildResult(resultCode, resultTypeConfig, context,
                        buildResultParams(path, resultTypeConfig));
            }
        }
    }

    /**
     * ??
     * 
     * @param path
     * @param param
     * @param redirectParamStr
     * @return
     */
    private Action buildAction(String path) {
        Action action = (Action) ActionContext.getContext().getContextMap().get("dispatch_action");
        if (null == action) {
            action = new Action();
            String newPath = path;
            if (path.startsWith("?")) {
                newPath = getServletPath(ServletActionContext.getRequest()) + path;
            }
            action.path(newPath);
        } else {
            if (null != action.getClazz()) {
                Action newAction = actionNameBuilder.build(action.getClazz());
                action.name(newAction.getName()).namespace(newAction.getNamespace());
            }
            if (StringUtils.isBlank(action.getName())) {
                action.path(getServletPath(ServletActionContext.getRequest()));
            }
        }
        return action;
    }

    private void addNamespaceAction(Action action, Map<String, String> params) {
        params.put("namespace", action.getNamespace());
        params.put("actionName", action.getName());
    }

    protected Map<String, String> buildResultParams(String defaultParam, ResultTypeConfig resultTypeConfig) {
        Map<String, String> params = new LinkedHashMap<String, String>();
        if (resultTypeConfig.getParams() != null) {
            params.putAll(resultTypeConfig.getParams());
        }
        params.put(resultTypeConfig.getDefaultResultParam(), defaultParam);
        return params;
    }

    /**
     * 
     * 
     * @param defaultParam
     * @param resultCode
     * @param resultTypeConfig
     * @param context
     * @param extraParams
     * @return
     */
    protected Result buildResult(String resultCode, ResultTypeConfig resultTypeConfig, ActionContext context,
            Map<String, String> params) {
        ResultConfig resultConfig = new ResultConfig.Builder(resultCode, resultTypeConfig.getClassName())
                .addParams(params).build();
        try {
            return objectFactory.buildResult(resultConfig, context.getContextMap());
        } catch (Exception e) {
            throw new XWorkException("Unable to build convention result", e, resultConfig);
        }
    }

    public ObjectFactory getObjectFactory() {
        return objectFactory;
    }

    public void setObjectFactory(ObjectFactory objectFactory) {
        this.objectFactory = objectFactory;
    }

    public Configuration getConfiguration() {
        return configuration;
    }

    public void setConfiguration(Configuration configuration) {
        this.configuration = configuration;
    }

    public void setViewMapper(ViewMapper viewMapper) {
        this.viewMapper = viewMapper;
    }

    public void setProfileService(ProfileService profileService) {
        this.profileService = profileService;
    }

    public void setActionNameBuilder(ActionBuilder actionNameBuilder) {
        this.actionNameBuilder = actionNameBuilder;
    }

}