Package org.eweb4j.mvc.config

Source Code of org.eweb4j.mvc.config.ActionAnnotationConfig

package org.eweb4j.mvc.config;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

import javax.ws.rs.DELETE;
import javax.ws.rs.GET;
import javax.ws.rs.HttpMethod;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;

import org.eweb4j.cache.ActionConfigBeanCache;
import org.eweb4j.cache.SingleBeanCache;
import org.eweb4j.config.LogFactory;
import org.eweb4j.config.ScanPackage;
import org.eweb4j.mvc.ActionMethod;
import org.eweb4j.mvc.action.RenderType;
import org.eweb4j.mvc.action.annotation.ActionLevel;
import org.eweb4j.mvc.action.annotation.Controller;
import org.eweb4j.mvc.action.annotation.Result;
import org.eweb4j.mvc.action.annotation.ShowValMess;
import org.eweb4j.mvc.action.annotation.Singleton;
import org.eweb4j.mvc.config.bean.ActionConfigBean;
import org.eweb4j.mvc.config.bean.ResultConfigBean;
import org.eweb4j.mvc.config.bean.ValidatorConfigBean;
import org.eweb4j.mvc.config.creator.ValidatorUtil;
import org.eweb4j.mvc.validator.annotation.Validate;
import org.eweb4j.util.ReflectUtil;
import org.eweb4j.util.StringUtil;

public class ActionAnnotationConfig extends ScanPackage{

 
  public ActionAnnotationConfig() {
    super();
    log = LogFactory.getMVCLogger(getClass());
  }

  /**
   * handle action class
   *
   * @param clsName
   * @throws Exception
   */
  public boolean handleClass(String clsName) {

    //log.debug("handleClass -> " + clsName);
    
    Class<?> cls = null;
    try {
      cls = Class.forName(clsName);

      if (cls == null)
        return false;

      String simpleName = cls.getSimpleName();
      Controller controlAnn = cls.getAnnotation(Controller.class);
      if (controlAnn == null && !simpleName.endsWith("Controller") && !simpleName.endsWith("Action") && !simpleName.endsWith("Control"))
        return false;

      String moduleName = StringUtil.toLowCaseFirst(simpleName.replace("Controller", "").replace("Control", ""));
      if (simpleName.endsWith("Action")) {
        moduleName = "";
      }

      Object obj = null;
      try {
        if (cls.getAnnotation(Singleton.class) != null) {
          obj = SingleBeanCache.get(cls);
          if (obj == null) {
            obj = cls.newInstance();
            SingleBeanCache.add(cls, obj);
          }
        } else
          obj = cls.newInstance();

      } catch (Error er) {
        log.debug("the action class new instance failued -> " + clsName + " | " + er.toString());
        return false;
      } catch (Exception e) {
        log.debug("the action class new instance failued -> " + clsName + " | " + e.toString());
        return false;
      }

      ReflectUtil ru = new ReflectUtil(obj);
      Method[] ms = ru.getMethods();
      if (ms == null)
        return false;

      // 扫描方法的注解信息
      for (Method m : ms) {
        if (m.getModifiers() != 1)
          continue;

        Path path = m.getAnnotation(Path.class);

        if (path == null) {
          String methodName = m.getName();
          Method getter = ru.getGetter(methodName.replace("get", ""));
          Method setter = ru.getSetter(methodName.replace("set", ""));
          // 默认下setter和getter不作为action方法
          if (getter != null || setter != null)
            continue;
        }

        handleActionConfigInfo(ru, cls, m, moduleName);
      }
    } catch (Error e) {
      return false;
    } catch (Exception e) {
      return false;
    }
   
    return true;
  }

  /**
   * 处理Action配置信息
   *
   * @param ru
   * @param controller
   * @param method
   * @param moduleName
   */
  private void handleActionConfigInfo(ReflectUtil ru,
      Class<?> controller, Method method, String moduleName) {

    final ActionConfigBean action = parseUriMappingSuffix(moduleName, method);
    if (action == null)
      return;

    action.setClazz(controller.getName());
    action.setMethod(method.getName());

    /* 解析出验证器错误信息输出类型 */
    action.setShowValErrorType(parseShowValErrType(controller, method));

    /* 解析出Http Method */
    String httpMethod = parseHttpMethodByAnnotation(controller, method);
    if (httpMethod != null)
      action.setHttpMethod(httpMethod);

    /* 解析出最终的uriMapping */
    String uriMapping = parseUriMapping(controller, moduleName, action.getUriMapping());
    if (uriMapping != null)
      action.setUriMapping(uriMapping);

    // 解析@Result注解
    Result resultAnn = method.getAnnotation(Result.class);
    if (resultAnn != null)
      action.getResult().addAll(ResultAnnUtil.readResultAnn(resultAnn));

    /* 解析@ActionLevel */
    int level = parseActionLevel(controller, method);
    action.setLevel(String.valueOf(level));

    /* 解析@Produces */
    List<String> pcbs = parseProduces(method);
    if (pcbs != null)
      action.getProduces().addAll(pcbs);

    /* 解析@Validator和各种验证器 */
    List<ValidatorConfigBean> vals = parseValidators(ru, method);
    if (vals != null)
      action.getValidator().addAll(vals);

    /* 解析最终的actionKey (包括合并http method、正则等) */
    String actionConfigKey = parseFullUriMapping(controller, method, action.getHttpMethod(), action.getUriMapping());
    if (actionConfigKey == null)
      return;

    // 将读取成功的配置信息放入缓存供框架运行期使用
    ActionConfigBeanCache.add(actionConfigKey, action);
    ActionClassCache.add(action.getClazz(), controller);
  }

  /**
   * 解析 URI Mapping 后部分
   *
   * @param moduleName
   * @param m
   * @return
   */
  private ActionConfigBean parseUriMappingSuffix(String moduleName, Method m) {
    ActionConfigBean acb = new ActionConfigBean();

    String methodName = m.getName();
    String fullName = m.toString();
    log.debug("parse action.method --> " + fullName);

    String uriMapping = null;

    Path m_path = m.getAnnotation(Path.class);
    if (m_path != null) {
      uriMapping = StringUtil.parsePropValue(m_path.value());
    } else if (methodName.startsWith(ActionMethod.PREFIX)) {
      uriMapping = methodName.substring(ActionMethod.PREFIX.length());
      // doUriBindParam1AndParam2JoinUriAtPostOrGet
      String at = null;
      int indexOfAt = methodName.indexOf(ActionMethod.AT);
      if (indexOfAt != -1) {
        at = methodName.substring(indexOfAt + ActionMethod.AT.length());
        if (methodName.startsWith(ActionMethod.PREFIX))
          uriMapping = uriMapping.substring(0,uriMapping.indexOf(ActionMethod.AT));

        String[] httpMethods = at.split(ActionMethod.OR);
        StringBuilder sb = new StringBuilder();
        for (String httpMethod : httpMethods) {
          if (sb.length() > 0)
            sb.append("|");

          sb.append(httpMethod.toUpperCase());
        }

        if (sb.length() > 0) {
          acb.setHttpMethod(sb.toString());
        }
      }
      String join = "";
      String bind;
      int indexOfBind = methodName.indexOf(ActionMethod.BIND);
      if (indexOfBind != -1) {
        if (indexOfAt != -1 && indexOfAt > indexOfBind) {
          bind = methodName.substring(indexOfBind + ActionMethod.BIND.length(),indexOfAt);
        } else {
          bind = methodName.substring(indexOfBind + ActionMethod.BIND.length());
        }

        uriMapping = uriMapping.substring(0,uriMapping.indexOf(ActionMethod.BIND));

        int indexOfJoin = bind.indexOf(ActionMethod.JOIN);
        if (indexOfJoin != -1) {
          String[] joins = bind.split(ActionMethod.JOIN);
          if (joins.length > 1) {
            bind = joins[0];
            join = joins[1];
          }
        }

        String[] pathParams = bind.split(ActionMethod.AND);
        StringBuilder pathParamSB = new StringBuilder();
        for (int i = 0; i < pathParams.length; i++) {
          pathParams[i] = StringUtil.toLowCaseFirst(pathParams[i]);
          pathParamSB.append("/{").append(pathParams[i]).append("}");
        }

        if (pathParamSB.length() > 0)
          uriMapping = uriMapping + pathParamSB.toString();

        acb.setPathParams(pathParams);
      }

      uriMapping = StringUtil.toLowCaseFirst(uriMapping);
      uriMapping = StringUtil.hump2ohter(uriMapping, "-");

      if (join.length() > 0) {
        join = StringUtil.toLowCaseFirst(join);
        join = StringUtil.hump2ohter(join, "-");
        uriMapping = uriMapping + "/" + join;
      }

    } else {
      /* 8 个默认方法 */
      ActionConfigBean defaultAcb = parseDefaultActionConfig(methodName, moduleName);
      if (defaultAcb != null) {
        acb.setHttpMethod(defaultAcb.getHttpMethod());
        acb.getResult().addAll(defaultAcb.getResult());

        uriMapping = defaultAcb.getUriMapping();
      } else {

        String info = fullName + " does not starts with '" + ActionMethod.PREFIX + "' so that can not be a valid action uri mapping";
        log.debug(info);
        return null;
      }
    }

    acb.setUriMapping(uriMapping);
    return acb;
  }

  /**
   * 解析默认的Action配置
   *
   * @param methodReqMapVal
   * @param moduleName
   * @return
   */
  private static ActionConfigBean parseDefaultActionConfig(String methodName, String moduleName) {
    String uriMapping = null;
    String httpMethod = null;
    ActionConfigBean acb = new ActionConfigBean();

    if (ActionMethod.INDEX.equals(methodName)) {
      uriMapping = "/";
      httpMethod = HttpMethod.GET;
      ResultConfigBean rcb = new ResultConfigBean();
      rcb.setName("jsp");
      rcb.setLocation(moduleName + "/view/index.jsp");
      acb.getResult().add(rcb);
      ResultConfigBean rcb2 = new ResultConfigBean();
      rcb2.setName("html");
      rcb2.setType(RenderType.FREEMARKER);
      rcb2.setLocation(moduleName + "/view/index.html");
      acb.getResult().add(rcb2);
    } else if (ActionMethod.CREATE.equals(methodName)) {
      uriMapping = "/";
      httpMethod = HttpMethod.POST;

      ResultConfigBean rcb = new ResultConfigBean();
      rcb.setName(ActionMethod.INDEX);
      rcb.setLocation(moduleName);
      rcb.setType(RenderType.ACTION);
      acb.getResult().add(rcb);
    } else if (ActionMethod.UPDATE.equals(methodName)) {
      uriMapping = "/{id}";
      httpMethod = HttpMethod.PUT;
      ResultConfigBean rcb = new ResultConfigBean();
      rcb.setName(ActionMethod.INDEX);
      rcb.setLocation(moduleName);
      rcb.setType(RenderType.ACTION);
      acb.getResult().add(rcb);
    } else if (ActionMethod.SHOW.equals(methodName)) {
      uriMapping = "/{id}";
      httpMethod = HttpMethod.GET;

      ResultConfigBean rcb = new ResultConfigBean();
      rcb.setName("jsp");
      rcb.setLocation(moduleName + "/view/show.jsp");
      acb.getResult().add(rcb);
      ResultConfigBean rcb2 = new ResultConfigBean();
      rcb2.setName("html");
      rcb2.setType(RenderType.FREEMARKER);
      rcb2.setLocation(moduleName + "/view/show.html");
      acb.getResult().add(rcb2);
    } else if (ActionMethod.EDIT.equals(methodName)) {
      uriMapping = "/{id}/edit";
      httpMethod = HttpMethod.GET;
      ResultConfigBean rcb = new ResultConfigBean();
      rcb.setName("jsp");
      rcb.setLocation(moduleName + "/view/edit.jsp");
      acb.getResult().add(rcb);
      ResultConfigBean rcb2 = new ResultConfigBean();
      rcb2.setName("html");
      rcb2.setType(RenderType.FREEMARKER);
      rcb2.setLocation(moduleName + "/view/edit.html");
      acb.getResult().add(rcb2);
    } else if (ActionMethod.DESTROY.equals(methodName)) {
      uriMapping = "/{id}";
      httpMethod = HttpMethod.DELETE;

      ResultConfigBean rcb = new ResultConfigBean();
      rcb.setName(ActionMethod.INDEX);
      rcb.setLocation(moduleName);
      rcb.setType(RenderType.ACTION);
      acb.getResult().add(rcb);
    } else if (ActionMethod.NEW.equals(methodName)) {
      uriMapping = "/new";
      httpMethod = HttpMethod.GET;
      ResultConfigBean rcb = new ResultConfigBean();
      rcb.setName("jsp");
      rcb.setLocation(moduleName + "/view/new.jsp");
      acb.getResult().add(rcb);
      ResultConfigBean rcb2 = new ResultConfigBean();
      rcb2.setName("html");
      rcb2.setType(RenderType.FREEMARKER);
      rcb2.setLocation(moduleName + "/view/new.html");
      acb.getResult().add(rcb2);
    } else {
      acb = null;
    }

   
   
    if (acb != null) {
      acb.setHttpMethod(httpMethod);
      acb.setUriMapping(uriMapping);
    }
   
    return acb;
  }

  private static String parseHttpMethodByClazz(Class<?> cls) {
    final String GET = HttpMethod.GET;
    final String POST = HttpMethod.POST;
    final String PUT = HttpMethod.PUT;
    final String DELETE = HttpMethod.DELETE;

    String[] methods = new String[4];
    methods[0] = cls.getAnnotation(GET.class) != null ? GET : "";
    methods[1] = cls.getAnnotation(POST.class) != null ? POST : "";
    methods[2] = cls.getAnnotation(DELETE.class) != null ? DELETE : "";
    methods[3] = cls.getAnnotation(PUT.class) != null ? PUT : "";

    StringBuilder m_sb = new StringBuilder();
    for (String s : methods) {
      if (m_sb.length() > 0 && s.length() > 0)
        m_sb.append("|");

      m_sb.append(s);
    }

    if (m_sb.length() == 0)
      return null;

    return m_sb.toString();
  }

  private static String parseFullUriMapping(Class<?> cls, Method m, final String httpMethod, final String uriMapping) {
    // Action全名,框架用,包括对“{xxx}”url参数的正则化,HttpRequestMethod
    String actionFullName = ActionUrlUtil.mathersUrlMapping(m, uriMapping, cls);
    if (actionFullName == null)
      return null;

    if (actionFullName.endsWith("/")) {
      actionFullName.substring(0, actionFullName.length() - 1);
    }

    actionFullName = actionFullName + ActionMethod.CON + httpMethod;
   
    return actionFullName;
  }

  private static List<ValidatorConfigBean> parseValidators(ReflectUtil ru,
      Method m) {
    List<ValidatorConfigBean> vals = new ArrayList<ValidatorConfigBean>();

    // 读取@Validate注解,拿到需要被验证的参数名称
    Validate validate = m.getAnnotation(Validate.class);
    if (validate == null)
      return vals;
   
    String[] fields = validate.value();
    String[] excepts = validate.except();
    if (fields != null) {
      // 读取Action object 的属性 验证信息
      List<ValidatorConfigBean> fieldVal = ValidatorUtil.readValidator(fields,excepts, null, ru, null, null);
      if (fieldVal != null)
        vals.addAll(fieldVal);
    }

    return vals;
  }

  private static List<String> parseProduces(Method m) {
    // 读取@Produces注解
    Produces producesAnn = m.getAnnotation(Produces.class);
    List<String> pcbs = null;
    if (producesAnn != null) {
      pcbs = new ArrayList<String>();
      String producesStr = StringUtil.parsePropValue(producesAnn.value()[0]);
      pcbs.add(producesStr);
    }

    return pcbs;
  }

  private static int parseActionLevel(Class<?> cls, Method m) {
    // 读取@ActionLevel注解
    ActionLevel actionLevel = cls.getAnnotation(ActionLevel.class);
    if (actionLevel == null)
      actionLevel = m.getAnnotation(ActionLevel.class);
    int level = 1;
    if (actionLevel != null)
      level = actionLevel.value();
    return level;
  }

  private static String parseShowValErrType(Class<?> cls, Method m) {
    ShowValMess cls_vm = cls.getAnnotation(ShowValMess.class);
    String clsShowValErr = cls_vm == null ? "alert" : cls_vm.value();

    clsShowValErr = StringUtil.parsePropValue(clsShowValErr);

    String methodShowValErr = clsShowValErr.trim().length() == 0 ? "alert" : clsShowValErr;// 验证器验证信息输出方式默认”alert“

    ShowValMess m_vm = m.getAnnotation(ShowValMess.class);
    methodShowValErr = m_vm == null ? methodShowValErr : m_vm.value();

    return methodShowValErr;
  }

  private static String parseHttpMethodByAnnotation(Class<?> cls, Method m) {
    String clazzHttpMethod = parseHttpMethodByClazz(cls);

    String methodHttpMethod = parseHttpMethodByMethodAnnotation(m);

    if (methodHttpMethod != null)
      return methodHttpMethod;

    return clazzHttpMethod;
  }

  private static String parseHttpMethodByMethodAnnotation(Method m) {
    String[] _methods = new String[4];
    _methods[0] = m.getAnnotation(GET.class) != null ? HttpMethod.GET : "";
    _methods[1] = m.getAnnotation(POST.class) != null ? HttpMethod.POST
        : "";
    _methods[2] = m.getAnnotation(DELETE.class) != null ? HttpMethod.DELETE
        : "";
    _methods[3] = m.getAnnotation(PUT.class) != null ? HttpMethod.PUT : "";

    StringBuilder _sb = new StringBuilder();
    for (String s : _methods) {
      if (_sb.length() > 0 && s.length() > 0)
        _sb.append("|");

      _sb.append(s);
    }

    if (_sb.length() == 0)
      return null;

    return _sb.toString();
  }

  /**
   * 解析 Uri Mapping 的前部分
   *
   * @param cls
   * @param moduleName
   * @return
   */
  private static String parseUriMappingPrefix(Class<?> cls, String moduleName) {
    Path cls_path = cls.getAnnotation(Path.class);
    String clazzUriMapping = cls_path == null ? moduleName : cls_path.value();

    clazzUriMapping = StringUtil.parsePropValue(clazzUriMapping);

    return clazzUriMapping;
  }

  /**
   * 解析
   *
   * @param cls
   * @param moduleName
   * @param methodUriMapping
   * @return
   */
  private static String parseUriMapping(Class<?> cls, String moduleName,
      String uriMappingSuffix) {
    String uriPrefix = parseUriMappingPrefix(cls, moduleName);
    if (uriPrefix.length() > 0 && !uriMappingSuffix.startsWith("/"))
      uriPrefix = uriPrefix + "/";

    String uriMapping = uriPrefix + uriMappingSuffix;
    if (uriMapping.startsWith("/"))
      uriMapping = uriMapping.substring(1);
    if (uriMapping.endsWith("/"))
      uriMapping = uriMapping.substring(0, uriMapping.length() - 1);

    return uriMapping;
  }

}
TOP

Related Classes of org.eweb4j.mvc.config.ActionAnnotationConfig

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.