Package org.jrest4guice.rest.helper

Source Code of org.jrest4guice.rest.helper.ServiceHelper$SingletonHolder

package org.jrest4guice.rest.helper;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.jrest4guice.guice.GuiceContext;
import org.jrest4guice.rest.RestContextManager;
import org.jrest4guice.rest.Service;
import org.jrest4guice.rest.ServiceRoute;
import org.jrest4guice.rest.annotations.Path;

/**
*
* @author <a href="mailto:zhangyouqun@gmail.com">cnoss (QQ:86895156)</a>
*
*/
@SuppressWarnings("unchecked")
public class ServiceHelper {
  private ServiceRoute root = new ServiceRoute();
  private Pattern paramPattern = Pattern.compile("\\{([a-zA-Z_]+[0-9]*)\\}");
  private static final String PARAM_KEY = "_$__PARAM_$__";

  private Map<String, Class<?>> remoteService;

  private ServiceHelper() {
    remoteService = new HashMap<String, Class<?>>();
  }

  private static class SingletonHolder {
    static ServiceHelper instance = new ServiceHelper();
  }

  public static ServiceHelper getInstance() {
    return SingletonHolder.instance;
  }

  public ServiceHelper addRemoteService(String name, Class<?> service) {
    this.remoteService.put(name, service);
    return this;
  }

  public Class<?> getRemoteService(String name) {
    return this.remoteService.get(name);
  }

  /**
   * 添加资源到上下文
   *
   * @param uri
   *            资源的路径
   * @param resourceClass
   *            资源对应的实现类
   */
  public void addResource(String uri, Class resourceClass,
      boolean processMethod) {
    ServiceRoute current = this.doAddResource(uri, resourceClass, root,
        null);
    if (!processMethod)
      return;

    this.addResourceByClassMethodInfo(resourceClass, current);
  }

  public void addResourceByClassMethodInfo(Class resourceClass) {
    this.addResourceByClassMethodInfo(resourceClass, root);
  }

  public void addResourceByClassMethodInfo(Class resourceClass,
      ServiceRoute current) {
    Method[] methods = resourceClass.getMethods();
    String[] paths;
    for (Method method : methods) {
      if (method.isAnnotationPresent(Path.class)) {
        paths = ((Path) method.getAnnotation(Path.class)).value();
        for (String path : paths)
          this.doAddResource(path, resourceClass, current, method);
      }
    }
  }

  private ServiceRoute doAddResource(String uri, Class resourceClass,
      ServiceRoute parent, Method method) {
    // 如果URI以"/"开头,则将当前的父结点指向root
    if (uri.startsWith("/"))
      parent = root;

    String[] routePath = uri.split("/");
    ServiceRoute current = parent;
    ServiceRoute child = null;
    for (String s : routePath) {
      s = s.trim();
      if ("".equals(s))
        continue;
      child = current.getRouteChild(s);
      Matcher matcher = paramPattern.matcher(s);
      if (matcher.matches()) {// 处理参数类型的路由节点
        child = new ServiceRoute(matcher.group(1));
        current.addParamChild(PARAM_KEY, child);
      } else {// 处理变通类型的路由节点(只有最末端的节点才会绑定到服务)
        if (child == null)
          child = new ServiceRoute();
        current.addRouteChild(s, child);
      }

      current = child;
    }
    // 绑定服务到当前的路由节点
    current.setServiceClass(resourceClass);
    // 设置当前服务所对应的Rest方法(只在@Path被声明在方法上时生效,实现subpath的功能)
    current.addRestMethod(method);

    return current;
  }

  /**
   *
   * @param uri
   * @param params
   * @return
   */
  public Service lookupResource(String uri) {
    String[] routePath = uri.split("/");
    ServiceRoute current = root;
    ServiceRoute child = null;
    List<ServiceRoute> paramChild = null;
    int index = 0;
    int len = routePath.length;
    for (String path : routePath) {
      index++;

      if (current == null)
        break;

      path = path.trim();
      if ("".equals(path))
        continue;

      paramChild = current.getParamChild(PARAM_KEY);
      if (paramChild != null) {
        for (ServiceRoute p : paramChild)
          RestContextManager.getModelMap()
              .put(p.getParamName(), path);
      }

      child = current.getRouteChild(path);
      if (child == null && paramChild != null && index < len) {
        child = this.lookupNextRoute(routePath[index], paramChild);
      }

      if (child == null && paramChild != null) {
        child = this.lookupNextRoute(null, paramChild);
      }

      ServiceRoute parent = current.getParent();
      if (child == null
          && (parent != null && this.hasRouteNode(path, parent
              .getRouteChildren()))) {
        continue;
      }

      current = child;
      child = null;
    }

    if (current == null)
      return null;
    Class resourceClaz = current.getServiceClass();
    if (resourceClaz != null) {
      try {
        Object instance = GuiceContext.getInstance().getBean(
            resourceClaz);
        return new Service(instance, current.getMethod());
      } catch (Exception e) {
        e.printStackTrace();
      }
    }

    return null;
  }

  private boolean hasRouteNode(String nodeName,
      Map<String, ServiceRoute> routeChildren) {
    boolean result = false;
    for (String key : routeChildren.keySet()) {
      if (key.equals(nodeName)) {
        result = true;
        break;
      }
    }
    return result;
  }

  private ServiceRoute lookupNextRoute(String nodeName,
      List<ServiceRoute> paramChild) {
    ServiceRoute route = null;
    Map<String, ServiceRoute> routeChildren;
    top: for (ServiceRoute r : paramChild) {
      routeChildren = r.getRouteChildren();
      if (routeChildren.size() > 0) {
        for (String key : routeChildren.keySet()) {
          if (key.equals(nodeName)) {
            route = routeChildren.get(key);
            break top;
          }
        }
      } else {
        if (route == null)
          route = r;
      }
    }
    return route;
  }
}
TOP

Related Classes of org.jrest4guice.rest.helper.ServiceHelper$SingletonHolder

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.