/* * Copyright 2014 ArcBees Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not * use this file except in compliance with the License. You may obtain a copy of * the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and limitations under * the License. */ package com.gwtplatform.dispatch.rest.client.context; import java.util.List; import com.gwtplatform.dispatch.rest.shared.HttpMethod; import com.gwtplatform.dispatch.rest.shared.HttpParameter; import com.gwtplatform.dispatch.rest.shared.HttpParameter.Type; import com.gwtplatform.dispatch.rest.shared.RestAction; /** * Context class used for the RestInterceptor and RestFilter mappings. */ public class RestContext { /** * {@link RestContext} Builder. */ public static class Builder { // Template domain private RestAction<?> template; // Manual domain private String path; private HttpMethod httpMethod; private int queryCount; // Check Properties private boolean transcendent; private boolean anyHttpMethod; private boolean anyQueryCount; /** * Constructs {@link RestContext} builder. */ public Builder() { } /** * Constructs {@link RestContext} builder. * * @param template the {@link RestAction} used as a template. */ public Builder(RestAction<?> template) { this.template = template; } /** * Explicitly provide a REST path string. * * @param path the rest path. * * @return this {@link Builder} object. */ public Builder path(String path) { this.path = path; return this; } /** * Explicitly provide an HttpMethod. * * @param httpMethod the REST {@link HttpMethod}. * * @return this {@link Builder} object. */ public Builder httpMethod(HttpMethod httpMethod) { this.httpMethod = httpMethod; return this; } /** * Explicitly provide a query count. * * @param queryCount the query count. * * @return this {@link Builder} object. */ public Builder queryCount(int queryCount) { this.queryCount = queryCount; return this; } /** * Allow for transcendent context mapping. * * @param transcendent Use a transcendent strategy on the path, e.g. /path will be detected using /path/2. * * @return this {@link Builder} object. */ public Builder transcendent(boolean transcendent) { this.transcendent = transcendent; return this; } /** * Any {@link HttpMethod} for context mapping. * * @param anyHttpMethod Allow any HTTP httpMethod when checking. * * @return this {@link Builder} object. */ public Builder anyHttpMethod(boolean anyHttpMethod) { this.anyHttpMethod = anyHttpMethod; return this; } /** * Any query count for context mapping. * * @param anyQueryCount true allows any query param count. * * @return this {@link Builder} object. */ public Builder anyQueryCount(boolean anyQueryCount) { this.anyQueryCount = anyQueryCount; return this; } /** * Build the {@link RestContext}. * * @return built context. */ public RestContext build() { return new RestContext(this); } @Override public int hashCode() { int result = template != null ? template.hashCode() : 0; result = 31 * result + (path != null ? path.hashCode() : 0); result = 31 * result + (httpMethod != null ? httpMethod.hashCode() : 0); result = 31 * result + queryCount; result = 31 * result + (transcendent ? 1 : 0); result = 31 * result + (anyHttpMethod ? 1 : 0); result = 31 * result + (anyQueryCount ? 1 : 0); return result; } } private Builder builder; protected RestContext(Builder builder) { assert builder != null; this.builder = builder; if (builder.httpMethod == null) { builder.anyHttpMethod = true; } if (builder.queryCount < 0) { builder.anyQueryCount = true; } } protected boolean canIntercept(RestAction<?> action) { String path = builder.path; HttpMethod httpMethod = builder.httpMethod; int queryCount = builder.queryCount; // Required check types if (useTemplate()) { path = builder.template.getPath(); httpMethod = builder.template.getHttpMethod(); queryCount = builder.template.getParameters(Type.QUERY).size(); } // Path Check if (isTranscendent()) { if (!action.getPath().startsWith(path)) { return false; } } else if (!action.getPath().equals(path)) { return false; } // Http Method Check if (!isAnyHttpMethod()) { if (!action.getHttpMethod().equals(httpMethod)) { return false; } } // Query Parameters if (!builder.anyQueryCount) { List<HttpParameter> queryParams = action.getParameters(Type.QUERY); if (queryParams.size() != queryCount) { return false; } else if (useTemplate()) { // We can do some thorough checking with templates if (!queryParams.equals(builder.template.getParameters(Type.QUERY))) { return false; } } } return true; } private boolean useTemplate() { return builder.template != null; } private boolean isAnyHttpMethod() { return builder.anyHttpMethod; } public String getPath() { return builder.path; } public HttpMethod getHttpMethod() { return builder.httpMethod; } public int getQueryCount() { return builder.queryCount; } public RestAction<?> getTemplate() { return builder.template; } public boolean isTranscendent() { return builder.transcendent; } @Override public boolean equals(Object o) { if (this == o) { return true; } if (o == null || getClass() != o.getClass()) { return false; } RestContext that = (RestContext) o; RestAction<?> action; if (that.useTemplate()) { action = that.getTemplate(); } else { action = new RestContextRestAction(that.getHttpMethod(), that.getPath(), that.getQueryCount()); } return canIntercept(action); } @Override public int hashCode() { return builder.hashCode(); } }