/**
   * Merges all path patterns and and creates a single string value which will be equal with service
   * methods path annotation value and HTTP method type. Generated string will be used for
   * permission checks.
   *
   * @param token for checking permission list
   * @param matchedTemplates matched templates of context. They will be merged with reverse order
   * @param method HTTP Method of the request. Will be merged with
   * @return true if user is Authorized.
   */
  private boolean isAuthorized(Token token, List<UriTemplate> matchedTemplates, String method) {
    StringBuilder path = new StringBuilder();
    // Merge all path templates and generate a path.
    for (UriTemplate template : matchedTemplates) {
      path.insert(0, template.getTemplate());
    }
    path.append(":").append(method);

    // Look at user permissions to see if the service is permitted.
    return token.getPermissions().contains(path.toString());
  }
  private void loadPathPatterns() throws ClassNotFoundException {
    String pkg = "com.xasecure.service";
    // List<Class> cList = findClasses(new File(dir), pkg);
    @SuppressWarnings("rawtypes")
    List<Class> cList = findClasses(pkg);
    for (@SuppressWarnings("rawtypes") Class klass : cList) {
      Annotation[] annotations = klass.getAnnotations();
      for (Annotation annotation : annotations) {
        if (!(annotation instanceof Path)) {
          continue;
        }
        Path path = (Path) annotation;
        if (path.value().startsWith("crud")) {
          continue;
        }
        // logger.info("path=" + path.value());
        // Loop over the class methods
        for (Method m : klass.getMethods()) {
          Annotation[] methodAnnotations = m.getAnnotations();
          String httpMethod = null;
          String servicePath = null;
          for (int ma = 0; ma < methodAnnotations.length; ma++) {
            if (methodAnnotations[ma] instanceof GET) {
              httpMethod = "GET";
            } else if (methodAnnotations[ma] instanceof PUT) {
              httpMethod = "PUT";
            } else if (methodAnnotations[ma] instanceof POST) {
              httpMethod = "POST";
            } else if (methodAnnotations[ma] instanceof DELETE) {
              httpMethod = "DELETE";
            } else if (methodAnnotations[ma] instanceof Path) {
              servicePath = ((Path) methodAnnotations[ma]).value();
            }
          }

          if (httpMethod == null) {
            continue;
          }

          String fullPath = path.value();
          String regEx = httpMethod + ":" + path.value();
          if (servicePath != null) {
            if (!servicePath.startsWith("/")) {
              servicePath = "/" + servicePath;
            }
            UriTemplate ut = new UriTemplate(servicePath);
            regEx = httpMethod + ":" + path.value() + ut.getPattern().getRegex();
            fullPath += servicePath;
          }
          Pattern regexPattern = Pattern.compile(regEx);

          if (regexPatternMap.containsKey(regEx)) {
            logger.warn("Duplicate regex=" + regEx + ", fullPath=" + fullPath);
          }
          regexList.add(regEx);
          regexPathMap.put(regEx, fullPath);
          regexPatternMap.put(regEx, regexPattern);

          logger.info(
              "path="
                  + path.value()
                  + ", servicePath="
                  + servicePath
                  + ", fullPath="
                  + fullPath
                  + ", regEx="
                  + regEx);
        }
      }
    }
    // ReOrder list
    int i = 0;
    for (i = 0; i < 10; i++) {
      boolean foundMatches = false;
      List<String> tmpList = new ArrayList<String>();
      for (int x = 0; x < regexList.size(); x++) {
        boolean foundMatch = false;
        String rX = regexList.get(x);
        for (int y = 0; y < x; y++) {
          String rY = regexList.get(y);
          Matcher matcher = regexPatternMap.get(rY).matcher(rX);
          if (matcher.matches()) {
            foundMatch = true;
            foundMatches = true;
            // logger.info("rX " + rX + " matched with rY=" + rY
            // + ". Moving rX to the top. Loop count=" + i);
            break;
          }
        }
        if (foundMatch) {
          tmpList.add(0, rX);
        } else {
          tmpList.add(rX);
        }
      }
      regexList = tmpList;
      if (!foundMatches) {
        logger.info("Done rearranging. loopCount=" + i);
        break;
      }
    }
    if (i == 10) {
      logger.warn("Couldn't rearrange even after " + i + " loops");
    }

    logger.info("Loaded " + regexList.size() + " API methods.");
    // for (String regEx : regexList) {
    // logger.info("regEx=" + regEx);
    // }
  }