001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.rest;
014
015import static javax.servlet.http.HttpServletResponse.*;
016
017import java.util.*;
018
019import javax.servlet.http.*;
020
021import org.apache.juneau.rest.util.*;
022
023/**
024 * Represents a group of CallMethods on a REST resource that handle the same HTTP Method name but with different
025 * paths/matchers/guards/etc...
026 *
027 * <p>
028 * Incoming requests for a particular HTTP method type (e.g. <js>"GET"</js>) are handed off to this class and then
029 * dispatched to the appropriate RestJavaMethod.
030 */
031public class RestCallRouter {
032   private final RestMethodContext[] restJavaMethods;
033
034   RestCallRouter(RestMethodContext[] callMethods) {
035      this.restJavaMethods = callMethods;
036   }
037
038   /**
039    * Builder class.
040    */
041   static final class Builder {
042      private List<RestMethodContext> childMethods = new ArrayList<>();
043      private String httpMethodName;
044
045      Builder(String httpMethodName) {
046         this.httpMethodName = httpMethodName;
047      }
048
049      String getHttpMethodName() {
050         return httpMethodName;
051      }
052
053      Builder add(RestMethodContext m) {
054         childMethods.add(m);
055         return this;
056      }
057
058      RestCallRouter build() {
059         Collections.sort(childMethods);
060         return new RestCallRouter(childMethods.toArray(new RestMethodContext[childMethods.size()]));
061      }
062   }
063
064   boolean matches(RestCall call) {
065      UrlPathInfo pi = call.getUrlPathInfo();
066      for (RestMethodContext m : restJavaMethods)
067         if (m.matches(pi))
068            return true;
069      return false;
070   }
071
072   /**
073    * Workhorse method.
074    *
075    * <p>
076    * Routes this request to one of the CallMethods.
077    *
078    * @param pathInfo The value of {@link HttpServletRequest#getPathInfo()} (sorta)
079    * @return The HTTP response code.
080    */
081   int invoke(RestCall call) throws Throwable {
082      if (restJavaMethods.length == 1)
083         return restJavaMethods[0].invoke(call);
084
085      int maxRc = 0;
086      for (RestMethodContext m : restJavaMethods) {
087         int rc = m.invoke(call);
088         if (rc == SC_OK)
089            return SC_OK;
090         maxRc = Math.max(maxRc, rc);
091      }
092      return maxRc;
093   }
094
095   @Override /* Object */
096   public String toString() {
097      StringBuilder sb = new StringBuilder("RestCallRouter: [\n");
098      for (RestMethodContext sm : restJavaMethods)
099         sb.append("\t" + sm + "\n");
100      sb.append("]");
101      return sb.toString();
102   }
103}