Renamed Id to ValueBasedId
renamed RestClient to ResourceDepotClient. Added ability to simulate an HTTP PUT or GET with a POST. Added support for extracting resource Id in callpath. Added Id to RestRequest.
This commit is contained in:
parent
103edb9c36
commit
be05420c6b
@ -15,7 +15,11 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.gson.rest.client;
|
package com.google.gson.rest.client;
|
||||||
|
|
||||||
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.rest.definition.ID;
|
import com.google.gson.rest.definition.ID;
|
||||||
|
import com.google.gson.rest.definition.ResourceDepot;
|
||||||
import com.google.gson.rest.definition.RestCallSpec;
|
import com.google.gson.rest.definition.RestCallSpec;
|
||||||
import com.google.gson.rest.definition.RestRequest;
|
import com.google.gson.rest.definition.RestRequest;
|
||||||
import com.google.gson.rest.definition.RestResource;
|
import com.google.gson.rest.definition.RestResource;
|
||||||
@ -24,26 +28,31 @@ import com.google.gson.webservice.definition.CallPath;
|
|||||||
import com.google.gson.webservice.definition.HeaderMap;
|
import com.google.gson.webservice.definition.HeaderMap;
|
||||||
import com.google.gson.webservice.definition.HttpMethod;
|
import com.google.gson.webservice.definition.HttpMethod;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A client class to access a rest resource
|
* A client class to access a rest resource
|
||||||
*
|
*
|
||||||
* @author Inderjeet Singh
|
* @author Inderjeet Singh
|
||||||
*/
|
*/
|
||||||
public class RestClient<I extends ID, R extends RestResource<I, R>> {
|
public class ResourceDepotClient<I extends ID, R extends RestResource<I, R>> implements ResourceDepot<I, R> {
|
||||||
private final RestClientStub stub;
|
private final RestClientStub stub;
|
||||||
private final RestCallSpec callSpec;
|
private final RestCallSpec callSpec;
|
||||||
private final Type resourceType;
|
private final Type resourceType;
|
||||||
|
private final Gson gson;
|
||||||
|
|
||||||
public RestClient(RestClientStub stub, CallPath callPath, Type resourceType) {
|
/**
|
||||||
this(stub, resourceType, generateRestCallSpec(callPath, resourceType));
|
* @param stub stub containing server info to access the rest client
|
||||||
|
* @param callPath relative path to the resource
|
||||||
|
* @param resourceType Class for the resource. Such as Cart.class
|
||||||
|
*/
|
||||||
|
public ResourceDepotClient(RestClientStub stub, CallPath callPath, Type resourceType, Gson gson) {
|
||||||
|
this(stub, resourceType, generateRestCallSpec(callPath, resourceType), gson);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected RestClient(RestClientStub stub, Type resourceType, RestCallSpec callSpec) {
|
protected ResourceDepotClient(RestClientStub stub, Type resourceType, RestCallSpec callSpec, Gson gson) {
|
||||||
this.stub = stub;
|
this.stub = stub;
|
||||||
this.callSpec = callSpec;
|
this.callSpec = callSpec;
|
||||||
this.resourceType = resourceType;
|
this.resourceType = resourceType;
|
||||||
|
this.gson = gson;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T> RestCallSpec generateRestCallSpec(CallPath callPath, Type resourceType) {
|
private static <T> RestCallSpec generateRestCallSpec(CallPath callPath, Type resourceType) {
|
||||||
@ -54,8 +63,8 @@ public class RestClient<I extends ID, R extends RestResource<I, R>> {
|
|||||||
HeaderMap requestHeaders =
|
HeaderMap requestHeaders =
|
||||||
new HeaderMap.Builder(callSpec.getRequestSpec().getHeadersSpec()).build();
|
new HeaderMap.Builder(callSpec.getRequestSpec().getHeadersSpec()).build();
|
||||||
RestRequest<I, R> request =
|
RestRequest<I, R> request =
|
||||||
new RestRequest<I, R>(HttpMethod.GET, requestHeaders, null, resourceType);
|
new RestRequest<I, R>(HttpMethod.GET, requestHeaders, resourceId, null, resourceType);
|
||||||
RestResponse<I, R> response = stub.getResponse(callSpec, request);
|
RestResponse<I, R> response = stub.getResponse(callSpec, request, gson);
|
||||||
return response.getBody();
|
return response.getBody();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -63,8 +72,8 @@ public class RestClient<I extends ID, R extends RestResource<I, R>> {
|
|||||||
HeaderMap requestHeaders =
|
HeaderMap requestHeaders =
|
||||||
new HeaderMap.Builder(callSpec.getRequestSpec().getHeadersSpec()).build();
|
new HeaderMap.Builder(callSpec.getRequestSpec().getHeadersSpec()).build();
|
||||||
RestRequest<I, R> request =
|
RestRequest<I, R> request =
|
||||||
new RestRequest<I, R>(HttpMethod.POST, requestHeaders, resource, resourceType);
|
new RestRequest<I, R>(HttpMethod.POST, requestHeaders, resource.getId(), resource, resourceType);
|
||||||
RestResponse<I, R> response = stub.getResponse(callSpec, request);
|
RestResponse<I, R> response = stub.getResponse(callSpec, request, gson);
|
||||||
return response.getBody();
|
return response.getBody();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,8 +81,8 @@ public class RestClient<I extends ID, R extends RestResource<I, R>> {
|
|||||||
HeaderMap requestHeaders =
|
HeaderMap requestHeaders =
|
||||||
new HeaderMap.Builder(callSpec.getRequestSpec().getHeadersSpec()).build();
|
new HeaderMap.Builder(callSpec.getRequestSpec().getHeadersSpec()).build();
|
||||||
RestRequest<I, R> request =
|
RestRequest<I, R> request =
|
||||||
new RestRequest<I, R>(HttpMethod.PUT, requestHeaders, resource, resourceType);
|
new RestRequest<I, R>(HttpMethod.PUT, requestHeaders, resource.getId(), resource, resourceType);
|
||||||
RestResponse<I, R> response = stub.getResponse(callSpec, request);
|
RestResponse<I, R> response = stub.getResponse(callSpec, request, gson);
|
||||||
return response.getBody();
|
return response.getBody();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +90,7 @@ public class RestClient<I extends ID, R extends RestResource<I, R>> {
|
|||||||
HeaderMap requestHeaders =
|
HeaderMap requestHeaders =
|
||||||
new HeaderMap.Builder(callSpec.getRequestSpec().getHeadersSpec()).build();
|
new HeaderMap.Builder(callSpec.getRequestSpec().getHeadersSpec()).build();
|
||||||
RestRequest<I, R> request =
|
RestRequest<I, R> request =
|
||||||
new RestRequest<I, R>(HttpMethod.DELETE, requestHeaders, null, resourceType);
|
new RestRequest<I, R>(HttpMethod.DELETE, requestHeaders, resourceId, null, resourceType);
|
||||||
stub.getResponse(callSpec, request);
|
stub.getResponse(callSpec, request, gson);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -79,10 +79,7 @@ public class RestClientStub {
|
|||||||
RestCallSpec callSpec, RestRequest<I, R> request, Gson gson) {
|
RestCallSpec callSpec, RestRequest<I, R> request, Gson gson) {
|
||||||
HttpURLConnection conn = null;
|
HttpURLConnection conn = null;
|
||||||
try {
|
try {
|
||||||
URL webServiceUrl = getWebServiceUrl(callSpec, getId(request.getBody()));
|
URL webServiceUrl = getWebServiceUrl(callSpec, request.getId());
|
||||||
if (logger != null) {
|
|
||||||
logger.log(logLevel, "Opening connection to " + webServiceUrl);
|
|
||||||
}
|
|
||||||
conn = (HttpURLConnection) webServiceUrl.openConnection();
|
conn = (HttpURLConnection) webServiceUrl.openConnection();
|
||||||
return getResponse(callSpec, request, gson, conn);
|
return getResponse(callSpec, request, gson, conn);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
@ -97,10 +94,11 @@ public class RestClientStub {
|
|||||||
* want to use HTTP pipelining.
|
* want to use HTTP pipelining.
|
||||||
*/
|
*/
|
||||||
public <I extends ID, R extends RestResource<I, R>> RestResponse<I, R> getResponse(
|
public <I extends ID, R extends RestResource<I, R>> RestResponse<I, R> getResponse(
|
||||||
RestCallSpec callSpec, RestRequest<I, R> request, Gson gson, HttpURLConnection conn) {
|
RestCallSpec callSpec, RestRequest<I, R> request, Gson gson,
|
||||||
|
HttpURLConnection conn) {
|
||||||
try {
|
try {
|
||||||
if (logger != null) {
|
if (logger != null) {
|
||||||
URL webServiceUrl = getWebServiceUrl(callSpec, getId(request.getBody()));
|
URL webServiceUrl = getWebServiceUrl(callSpec, request.getId());
|
||||||
logger.log(logLevel, "Opening connection to " + webServiceUrl);
|
logger.log(logLevel, "Opening connection to " + webServiceUrl);
|
||||||
}
|
}
|
||||||
RestRequestSender requestSender = new RestRequestSender(gson, logLevel);
|
RestRequestSender requestSender = new RestRequestSender(gson, logLevel);
|
||||||
@ -119,10 +117,6 @@ public class RestClientStub {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <I extends ID, R extends RestResource<I, R>> I getId(R resource) {
|
|
||||||
return (resource == null || !resource.hasId()) ? null : resource.getId();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("config:%s", config);
|
return String.format("config:%s", config);
|
||||||
|
@ -28,6 +28,7 @@ import com.google.gson.rest.definition.RestRequest;
|
|||||||
import com.google.gson.rest.definition.RestResource;
|
import com.google.gson.rest.definition.RestResource;
|
||||||
import com.google.gson.webservice.definition.HeaderMap;
|
import com.google.gson.webservice.definition.HeaderMap;
|
||||||
import com.google.gson.webservice.definition.HeaderMapSpec;
|
import com.google.gson.webservice.definition.HeaderMapSpec;
|
||||||
|
import com.google.gson.webservice.definition.HttpMethod;
|
||||||
import com.google.gson.webservice.definition.WebServiceSystemException;
|
import com.google.gson.webservice.definition.WebServiceSystemException;
|
||||||
import com.google.gson.wsclient.internal.utils.Streams;
|
import com.google.gson.wsclient.internal.utils.Streams;
|
||||||
|
|
||||||
@ -37,6 +38,9 @@ import com.google.gson.wsclient.internal.utils.Streams;
|
|||||||
* @author inder
|
* @author inder
|
||||||
*/
|
*/
|
||||||
public final class RestRequestSender {
|
public final class RestRequestSender {
|
||||||
|
private static final boolean SIMULATE_GET_WITH_POST = true;
|
||||||
|
private static final boolean SIMULATE_PUT_WITH_POST = true;
|
||||||
|
|
||||||
private final Gson gson;
|
private final Gson gson;
|
||||||
private final Logger logger;
|
private final Logger logger;
|
||||||
private final Level logLevel;
|
private final Level logLevel;
|
||||||
@ -51,9 +55,18 @@ public final class RestRequestSender {
|
|||||||
this.logLevel = logLevel;
|
this.logLevel = logLevel;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <I extends ID, R extends RestResource<I, R>> void send(HttpURLConnection conn, RestRequest<I, R> request) {
|
public <I extends ID, R extends RestResource<I, R>> void send(
|
||||||
|
HttpURLConnection conn, RestRequest<I, R> request) {
|
||||||
try {
|
try {
|
||||||
conn.setRequestMethod(request.getHttpMethod().toString());
|
HttpMethod method = request.getHttpMethod();
|
||||||
|
if (SIMULATE_PUT_WITH_POST && method == HttpMethod.PUT) {
|
||||||
|
method = HttpMethod.POST;
|
||||||
|
setHeader(conn, HttpMethod.SIMULATED_METHOD_HEADER, HttpMethod.PUT.toString(), true);
|
||||||
|
} else if (SIMULATE_GET_WITH_POST && method == HttpMethod.GET) {
|
||||||
|
method = HttpMethod.POST;
|
||||||
|
setHeader(conn, HttpMethod.SIMULATED_METHOD_HEADER, HttpMethod.GET.toString(), true);
|
||||||
|
}
|
||||||
|
conn.setRequestMethod(method.toString());
|
||||||
setHeader(conn, "Content-Type", request.getContentType(), true);
|
setHeader(conn, "Content-Type", request.getContentType(), true);
|
||||||
|
|
||||||
// Assume conservatively that the response will need to be read.
|
// Assume conservatively that the response will need to be read.
|
||||||
@ -63,8 +76,10 @@ public final class RestRequestSender {
|
|||||||
|
|
||||||
R requestBody = request.getBody();
|
R requestBody = request.getBody();
|
||||||
String requestBodyContents = "";
|
String requestBodyContents = "";
|
||||||
|
if (method == HttpMethod.POST || method == HttpMethod.PUT) {
|
||||||
// Android Java VM ignore Content-Length if setDoOutput is not set
|
// Android Java VM ignore Content-Length if setDoOutput is not set
|
||||||
conn.setDoOutput(true);
|
conn.setDoOutput(true);
|
||||||
|
}
|
||||||
if (requestBody != null) {
|
if (requestBody != null) {
|
||||||
requestBodyContents = gson.toJson(requestBody, request.getSpec().getResourceType());
|
requestBodyContents = gson.toJson(requestBody, request.getSpec().getResourceType());
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
package com.google.gson.rest.definition;
|
package com.google.gson.rest.definition;
|
||||||
|
|
||||||
public interface ID {
|
public interface ID {
|
||||||
public static final long INVALID_ID = 0L;
|
public static final long INVALID_ID = -1L;
|
||||||
|
|
||||||
public long getValue();
|
public long getValue();
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2010 Google 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.google.gson.rest.definition;
|
package com.google.gson.rest.definition;
|
||||||
|
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A factory to create {@link ValueBasedId)s
|
||||||
|
*
|
||||||
|
* @author inder
|
||||||
|
*
|
||||||
|
* @param <I>
|
||||||
|
*/
|
||||||
public class IDFactory<I extends ID> {
|
public class IDFactory<I extends ID> {
|
||||||
private final Class<? super I> classOfI;
|
private final Class<? super I> classOfI;
|
||||||
private final Type typeOfId;
|
private final Type typeOfId;
|
||||||
@ -11,9 +33,10 @@ public class IDFactory<I extends ID> {
|
|||||||
this.typeOfId = typeOfId;
|
this.typeOfId = typeOfId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public I createId(long value) {
|
public I createId(long value) {
|
||||||
if (classOfI.isAssignableFrom(Id.class)) {
|
if (classOfI.isAssignableFrom(ValueBasedId.class)) {
|
||||||
return (I)Id.get(value, typeOfId);
|
return (I)ValueBasedId.get(value, typeOfId);
|
||||||
}
|
}
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2010 Google 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.google.gson.rest.definition;
|
||||||
|
|
||||||
|
public interface ResourceDepot<I extends ID, R extends RestResource<I, R>> {
|
||||||
|
|
||||||
|
public R get(I resourceId);
|
||||||
|
|
||||||
|
public R post(R resource);
|
||||||
|
|
||||||
|
public R put(R resource);
|
||||||
|
|
||||||
|
public void delete(I resourceId);
|
||||||
|
}
|
@ -32,9 +32,9 @@ public final class ResourceMap {
|
|||||||
private final Map<CallPath, RestCallSpec> resources =
|
private final Map<CallPath, RestCallSpec> resources =
|
||||||
new HashMap<CallPath, RestCallSpec>();
|
new HashMap<CallPath, RestCallSpec>();
|
||||||
|
|
||||||
public Builder set(CallPath callPath, RestCallSpec spec) {
|
public Builder set(CallPath baseCallPath, RestCallSpec spec) {
|
||||||
Preconditions.checkArgument(resources.get(callPath) == null);
|
Preconditions.checkArgument(resources.get(baseCallPath) == null);
|
||||||
resources.put(callPath, spec);
|
resources.put(baseCallPath, spec);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,4 +130,9 @@ public final class RestCallSpec {
|
|||||||
"path: %s, version: %.2f, resourceType: %s, requestSpec: %s, responseSpec: %s",
|
"path: %s, version: %.2f, resourceType: %s, requestSpec: %s, responseSpec: %s",
|
||||||
path, version, resourceType, requestSpec, responseSpec);
|
path, version, resourceType, requestSpec, responseSpec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public RestCallSpec createCopy(CallPath callPath) {
|
||||||
|
return new RestCallSpec(supportedHttpMethods, callPath, requestSpec,
|
||||||
|
responseSpec, resourceType, version);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,19 +32,21 @@ public final class RestRequest<I extends ID, R extends RestResource<I, R>> {
|
|||||||
|
|
||||||
private final HttpMethod method;
|
private final HttpMethod method;
|
||||||
private final HeaderMap headers;
|
private final HeaderMap headers;
|
||||||
|
private final I id;
|
||||||
private final R body;
|
private final R body;
|
||||||
private final RestRequestSpec spec;
|
private final RestRequestSpec spec;
|
||||||
|
|
||||||
public RestRequest(HttpMethod method, HeaderMap requestHeaders,
|
public RestRequest(HttpMethod method, HeaderMap requestHeaders,
|
||||||
R requestBody, Type resourceType) {
|
I resourceId, R requestBody, Type resourceType) {
|
||||||
this.method = method;
|
this.method = method;
|
||||||
|
this.id = resourceId;
|
||||||
this.body = requestBody;
|
this.body = requestBody;
|
||||||
this.headers = requestHeaders;
|
this.headers = requestHeaders;
|
||||||
this.spec = new RestRequestSpec(requestHeaders.getSpec(), resourceType);
|
this.spec = new RestRequestSpec(requestHeaders.getSpec(), resourceType);
|
||||||
}
|
}
|
||||||
|
|
||||||
public I getId() {
|
public I getId() {
|
||||||
return body.getId();
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
public HttpMethod getMethod() {
|
public HttpMethod getMethod() {
|
||||||
|
@ -35,13 +35,11 @@ import java.lang.reflect.WildcardType;
|
|||||||
*
|
*
|
||||||
* @param <R> type variable for the rest resource
|
* @param <R> type variable for the rest resource
|
||||||
*/
|
*/
|
||||||
public final class Id<R> implements ID {
|
public final class ValueBasedId<R> implements ID {
|
||||||
private static final long NULL_VALUE = -1;
|
|
||||||
private final long value;
|
private final long value;
|
||||||
private final Type typeOfId;
|
private final Type typeOfId;
|
||||||
|
|
||||||
private Id(long value, Type typeOfId) {
|
private ValueBasedId(long value, Type typeOfId) {
|
||||||
Preconditions.checkArgument(value != NULL_VALUE);
|
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.typeOfId = typeOfId;
|
this.typeOfId = typeOfId;
|
||||||
}
|
}
|
||||||
@ -51,8 +49,8 @@ public final class Id<R> implements ID {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static long getValue(Id<?> id) {
|
public static long getValue(ValueBasedId<?> id) {
|
||||||
return id == null ? NULL_VALUE : id.getValue();
|
return id == null ? INVALID_ID : id.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getValueAsString() {
|
public String getValueAsString() {
|
||||||
@ -68,8 +66,8 @@ public final class Id<R> implements ID {
|
|||||||
return (int) value;
|
return (int) value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isValid(Id<?> id) {
|
public static boolean isValid(ValueBasedId<?> id) {
|
||||||
return id != null && id.value != NULL_VALUE;
|
return id != null && id.value != INVALID_ID;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -78,7 +76,8 @@ public final class Id<R> implements ID {
|
|||||||
* only id values, not their types. Note that this shortcut doesn't work if you pass raw ids
|
* only id values, not their types. Note that this shortcut doesn't work if you pass raw ids
|
||||||
* to this method
|
* to this method
|
||||||
*/
|
*/
|
||||||
public static <T> boolean equals(/* @Nullable */ Id<T> id1, /* @Nullable */ Id<T> id2) {
|
public static <T> boolean equals(/* @Nullable */ ValueBasedId<T> id1,
|
||||||
|
/* @Nullable */ ValueBasedId<T> id2) {
|
||||||
if ((id1 == null && id2 != null) || (id1 != null && id2 == null)) {
|
if ((id1 == null && id2 != null) || (id1 != null && id2 == null)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -94,7 +93,7 @@ public final class Id<R> implements ID {
|
|||||||
if (obj == null) return false;
|
if (obj == null) return false;
|
||||||
if (getClass() != obj.getClass()) return false;
|
if (getClass() != obj.getClass()) return false;
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Id<R> other = (Id<R>)obj;
|
ValueBasedId<R> other = (ValueBasedId<R>)obj;
|
||||||
if (typeOfId == null) {
|
if (typeOfId == null) {
|
||||||
if (other.typeOfId != null) return false;
|
if (other.typeOfId != null) return false;
|
||||||
} else if (!equivalentTypes(typeOfId, other.typeOfId)) return false;
|
} else if (!equivalentTypes(typeOfId, other.typeOfId)) return false;
|
||||||
@ -135,8 +134,8 @@ public final class Id<R> implements ID {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <RS> Id<RS> get(long value, Type typeOfId) {
|
public static <RS> ValueBasedId<RS> get(long value, Type typeOfId) {
|
||||||
return new Id<RS>(value, typeOfId);
|
return new ValueBasedId<RS>(value, typeOfId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -179,17 +178,18 @@ public final class Id<R> implements ID {
|
|||||||
* @author inder
|
* @author inder
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public static final class GsonTypeAdapter implements JsonSerializer<Id<?>>,
|
public static final class GsonTypeAdapter implements JsonSerializer<ValueBasedId<?>>,
|
||||||
JsonDeserializer<Id<?>> {
|
JsonDeserializer<ValueBasedId<?>> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public JsonElement serialize(Id<?> src, Type typeOfSrc, JsonSerializationContext context) {
|
public JsonElement serialize(ValueBasedId<?> src, Type typeOfSrc,
|
||||||
|
JsonSerializationContext context) {
|
||||||
return new JsonPrimitive(src.getValue());
|
return new JsonPrimitive(src.getValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Id<?> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
public ValueBasedId<?> deserialize(JsonElement json, Type typeOfT,
|
||||||
throws JsonParseException {
|
JsonDeserializationContext context) throws JsonParseException {
|
||||||
if (!(typeOfT instanceof ParameterizedType)) {
|
if (!(typeOfT instanceof ParameterizedType)) {
|
||||||
throw new JsonParseException("Id of unknown type: " + typeOfT);
|
throw new JsonParseException("Id of unknown type: " + typeOfT);
|
||||||
}
|
}
|
||||||
@ -197,7 +197,7 @@ public final class Id<R> implements ID {
|
|||||||
// Since Id takes only one TypeVariable, the actual type corresponding to the first
|
// Since Id takes only one TypeVariable, the actual type corresponding to the first
|
||||||
// TypeVariable is the Type we are looking for
|
// TypeVariable is the Type we are looking for
|
||||||
Type typeOfId = parameterizedType.getActualTypeArguments()[0];
|
Type typeOfId = parameterizedType.getActualTypeArguments()[0];
|
||||||
return Id.get(json.getAsLong(), typeOfId);
|
return ValueBasedId.get(json.getAsLong(), typeOfId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -15,6 +15,9 @@
|
|||||||
*/
|
*/
|
||||||
package com.google.gson.webservice.definition;
|
package com.google.gson.webservice.definition;
|
||||||
|
|
||||||
|
import com.google.gson.rest.definition.ID;
|
||||||
|
import com.google.gson.webservice.definition.internal.utils.Pair;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encapsulation of a Web service path that is sent by the client.
|
* Encapsulation of a Web service path that is sent by the client.
|
||||||
*
|
*
|
||||||
@ -22,28 +25,57 @@ package com.google.gson.webservice.definition;
|
|||||||
*/
|
*/
|
||||||
public final class CallPath {
|
public final class CallPath {
|
||||||
|
|
||||||
|
private static final double IGNORE_VERSION = -1D;
|
||||||
private final String path;
|
private final String path;
|
||||||
private final double version;
|
private final double version;
|
||||||
|
private final long resourceId;
|
||||||
|
|
||||||
public CallPath(String path) {
|
public CallPath(String path) {
|
||||||
if (path == null) {
|
if (path == null) {
|
||||||
this.path = null;
|
this.path = null;
|
||||||
version = -1D;
|
version = IGNORE_VERSION;
|
||||||
|
resourceId = ID.INVALID_ID;
|
||||||
} else {
|
} else {
|
||||||
|
Pair<Double, String> path2 = extractVersion(path);
|
||||||
|
this.version = path2.first;
|
||||||
|
Pair<Long, String> path3 = extractId(path2.second);
|
||||||
|
this.resourceId = path3.first;
|
||||||
|
this.path = path3.second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns path after consuming version number from the begining
|
||||||
|
*/
|
||||||
|
private static Pair<Double, String> extractVersion(String path) {
|
||||||
int index1 = path.indexOf('/');
|
int index1 = path.indexOf('/');
|
||||||
int index2 = path.substring(index1+1).indexOf('/');
|
int index2 = path.substring(index1+1).indexOf('/');
|
||||||
String versionStr = path.substring(index1+1, index2+1);
|
String versionStr = path.substring(index1+1, index2+1);
|
||||||
String callPathStr = path;
|
double extractedVersion = -1.0D;
|
||||||
double givenVersion = -1D;
|
String revisedPath = path;
|
||||||
try {
|
try {
|
||||||
// Skip over the version number from the URL
|
// Skip over the version number from the URL
|
||||||
givenVersion = Double.parseDouble(versionStr);
|
extractedVersion = Double.parseDouble(versionStr);
|
||||||
callPathStr = path.substring(index2+1);
|
revisedPath = path.substring(index2+1);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
// Assume that version number wasn't specified
|
// Assume that version number wasn't specified
|
||||||
}
|
}
|
||||||
this.path = callPathStr;
|
return Pair.create(extractedVersion, revisedPath);
|
||||||
this.version = givenVersion;
|
}
|
||||||
|
|
||||||
|
private static Pair<Long, String> extractId(String path) {
|
||||||
|
Pair<Long, String> originalPath = Pair.create(ID.INVALID_ID, path);
|
||||||
|
int end = path.endsWith("/") ? path.length() - 1 : path.length();
|
||||||
|
int begin = path.substring(0, end-1).lastIndexOf('/') + 1;
|
||||||
|
if (begin < 0 || end < 0 || begin >= end) {
|
||||||
|
return originalPath;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
String id = path.substring(begin, end);
|
||||||
|
String pathWithoutId = path.substring(0, begin-1);
|
||||||
|
return Pair.create(Long.parseLong(id), pathWithoutId);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
return originalPath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -55,11 +87,19 @@ public final class CallPath {
|
|||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getResourceId() {
|
||||||
|
return resourceId;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return path.hashCode();
|
return path.hashCode();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean matches(CallPath callPath) {
|
||||||
|
return path.startsWith(callPath.get());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (this == obj) {
|
if (this == obj) {
|
||||||
@ -77,6 +117,6 @@ public final class CallPath {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return path;
|
return String.format("path:%s, version:%2.f, resourceId: %d", path, version, resourceId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,4 +36,10 @@ public enum HttpMethod {
|
|||||||
|
|
||||||
public static final List<HttpMethod> ALL_METHODS =
|
public static final List<HttpMethod> ALL_METHODS =
|
||||||
Collections.unmodifiableList(Arrays.asList(values()));
|
Collections.unmodifiableList(Arrays.asList(values()));
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This header is used to indicate the real method that is channeled through the current
|
||||||
|
* request. For example, you can use it to send PUT requests under a POST.
|
||||||
|
*/
|
||||||
|
public static final String SIMULATED_METHOD_HEADER = "SimulatedMethod";
|
||||||
}
|
}
|
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2010 Google 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.google.gson.webservice.definition.internal.utils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple object that holds onto a pair of object references, first and second.
|
||||||
|
*
|
||||||
|
* @author Inderjeet Singh
|
||||||
|
*
|
||||||
|
* @param <FIRST>
|
||||||
|
* @param <SECOND>
|
||||||
|
*/
|
||||||
|
public final class Pair<FIRST, SECOND> {
|
||||||
|
|
||||||
|
public final FIRST first;
|
||||||
|
public final SECOND second;
|
||||||
|
|
||||||
|
public Pair(FIRST first, SECOND second) {
|
||||||
|
this.first = first;
|
||||||
|
this.second = second;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <F, S> Pair<F, S> create(F first, S second) {
|
||||||
|
return new Pair<F, S>(first, second);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return 17 * ((first != null) ? first.hashCode() : 0)
|
||||||
|
+ 17 * ((second != null) ? second.hashCode() : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (!(o instanceof Pair<?, ?>)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Pair<?, ?> that = (Pair<?, ?>) o;
|
||||||
|
return equal(this.first, that.first) && equal(this.second, that.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean equal(Object a, Object b) {
|
||||||
|
return a == b || (a != null && a.equals(b));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("{%s,%s}", first, second);
|
||||||
|
}
|
||||||
|
}
|
@ -20,34 +20,34 @@ import java.lang.reflect.ParameterizedType;
|
|||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
import com.google.gson.rest.definition.Id;
|
import com.google.gson.rest.definition.ValueBasedId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit test for {@link Id}
|
* Unit test for {@link ValueBasedId}
|
||||||
*
|
*
|
||||||
* @author inder
|
* @author inder
|
||||||
*/
|
*/
|
||||||
public class IdTest extends TestCase {
|
public class IdTest extends TestCase {
|
||||||
|
|
||||||
public void testRawTypeNotEqualToParameterizedOfConcreteType() {
|
public void testRawTypeNotEqualToParameterizedOfConcreteType() {
|
||||||
ParameterizedType type = (ParameterizedType) new TypeToken<Id<Foo>>(){}.getType();
|
ParameterizedType type = (ParameterizedType) new TypeToken<ValueBasedId<Foo>>(){}.getType();
|
||||||
assertFalse(Id.areEquivalentTypes(type, Id.class));
|
assertFalse(ValueBasedId.areEquivalentTypes(type, ValueBasedId.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testRawTypeEqualToParameterizedOfWildcardType() {
|
public void testRawTypeEqualToParameterizedOfWildcardType() {
|
||||||
ParameterizedType fooType = (ParameterizedType) new TypeToken<Id<?>>(){}.getType();
|
ParameterizedType fooType = (ParameterizedType) new TypeToken<ValueBasedId<?>>(){}.getType();
|
||||||
assertTrue(Id.areEquivalentTypes(fooType, Id.class));
|
assertTrue(ValueBasedId.areEquivalentTypes(fooType, ValueBasedId.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testStaticEquals() {
|
public void testStaticEquals() {
|
||||||
Id<Foo> id1 = Id.get(3L, Foo.class);
|
ValueBasedId<Foo> id1 = ValueBasedId.get(3L, Foo.class);
|
||||||
Id<Foo> id2 = Id.get(3L, Foo.class);
|
ValueBasedId<Foo> id2 = ValueBasedId.get(3L, Foo.class);
|
||||||
Id<Foo> id3 = Id.get(4L, Foo.class);
|
ValueBasedId<Foo> id3 = ValueBasedId.get(4L, Foo.class);
|
||||||
assertTrue(Id.equals(id1, id2));
|
assertTrue(ValueBasedId.equals(id1, id2));
|
||||||
assertFalse(Id.equals(null, id2));
|
assertFalse(ValueBasedId.equals(null, id2));
|
||||||
assertFalse(Id.equals(id1, null));
|
assertFalse(ValueBasedId.equals(id1, null));
|
||||||
assertTrue(Id.equals(null, null));
|
assertTrue(ValueBasedId.equals(null, null));
|
||||||
assertFalse(Id.equals(id1, id3));
|
assertFalse(ValueBasedId.equals(id1, id3));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Foo {
|
private static class Foo {
|
||||||
|
@ -25,21 +25,21 @@ import junit.framework.TestCase;
|
|||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import com.google.gson.reflect.TypeToken;
|
import com.google.gson.reflect.TypeToken;
|
||||||
import com.google.gson.rest.definition.Id;
|
import com.google.gson.rest.definition.ValueBasedId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for {@link Id.GsonTypeAdapter}
|
* Unit tests for {@link ValueBasedId.GsonTypeAdapter}
|
||||||
*
|
*
|
||||||
* @author inder
|
* @author inder
|
||||||
*/
|
*/
|
||||||
public class IdTypeAdapterTest extends TestCase {
|
public class IdTypeAdapterTest extends TestCase {
|
||||||
private static final Id<Student> STUDENT1_ID = Id.get(5L, Student.class);
|
private static final ValueBasedId<Student> STUDENT1_ID = ValueBasedId.get(5L, Student.class);
|
||||||
private static final Id<Student> STUDENT2_ID = Id.get(6L, Student.class);
|
private static final ValueBasedId<Student> STUDENT2_ID = ValueBasedId.get(6L, Student.class);
|
||||||
private static final Student STUDENT1 = new Student(STUDENT1_ID, "first");
|
private static final Student STUDENT1 = new Student(STUDENT1_ID, "first");
|
||||||
private static final Student STUDENT2 = new Student(STUDENT2_ID, "second");
|
private static final Student STUDENT2 = new Student(STUDENT2_ID, "second");
|
||||||
private static final Type TYPE_COURSE_HISTORY =
|
private static final Type TYPE_COURSE_HISTORY =
|
||||||
new TypeToken<Course<HistoryCourse>>(){}.getType();
|
new TypeToken<Course<HistoryCourse>>(){}.getType();
|
||||||
private static final Id<Course<HistoryCourse>> COURSE_ID = Id.get(10L, TYPE_COURSE_HISTORY);
|
private static final ValueBasedId<Course<HistoryCourse>> COURSE_ID = ValueBasedId.get(10L, TYPE_COURSE_HISTORY);
|
||||||
|
|
||||||
private Gson gson;
|
private Gson gson;
|
||||||
private Course<HistoryCourse> course;
|
private Course<HistoryCourse> course;
|
||||||
@ -47,7 +47,7 @@ public class IdTypeAdapterTest extends TestCase {
|
|||||||
@Override
|
@Override
|
||||||
protected void setUp() {
|
protected void setUp() {
|
||||||
gson = new GsonBuilder()
|
gson = new GsonBuilder()
|
||||||
.registerTypeAdapter(Id.class, new Id.GsonTypeAdapter())
|
.registerTypeAdapter(ValueBasedId.class, new ValueBasedId.GsonTypeAdapter())
|
||||||
.create();
|
.create();
|
||||||
course = new Course<HistoryCourse>(COURSE_ID, 4,
|
course = new Course<HistoryCourse>(COURSE_ID, 4,
|
||||||
new Assignment<HistoryCourse>(null, null), createList(STUDENT1, STUDENT2));
|
new Assignment<HistoryCourse>(null, null), createList(STUDENT1, STUDENT2));
|
||||||
@ -71,13 +71,13 @@ public class IdTypeAdapterTest extends TestCase {
|
|||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private static class Student {
|
private static class Student {
|
||||||
Id<Student> id;
|
ValueBasedId<Student> id;
|
||||||
String name;
|
String name;
|
||||||
|
|
||||||
private Student() {
|
private Student() {
|
||||||
this(null, null);
|
this(null, null);
|
||||||
}
|
}
|
||||||
public Student(Id<Student> id, String name) {
|
public Student(ValueBasedId<Student> id, String name) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
@ -85,7 +85,7 @@ public class IdTypeAdapterTest extends TestCase {
|
|||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private static class Course<T> {
|
private static class Course<T> {
|
||||||
final List<Student> students;
|
final List<Student> students;
|
||||||
private final Id<Course<T>> courseId;
|
private final ValueBasedId<Course<T>> courseId;
|
||||||
private final int numAssignments;
|
private final int numAssignments;
|
||||||
private final Assignment<T> assignment;
|
private final Assignment<T> assignment;
|
||||||
|
|
||||||
@ -93,14 +93,14 @@ public class IdTypeAdapterTest extends TestCase {
|
|||||||
this(null, 0, null, new ArrayList<Student>());
|
this(null, 0, null, new ArrayList<Student>());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Course(Id<Course<T>> courseId, int numAssignments,
|
public Course(ValueBasedId<Course<T>> courseId, int numAssignments,
|
||||||
Assignment<T> assignment, List<Student> players) {
|
Assignment<T> assignment, List<Student> players) {
|
||||||
this.courseId = courseId;
|
this.courseId = courseId;
|
||||||
this.numAssignments = numAssignments;
|
this.numAssignments = numAssignments;
|
||||||
this.assignment = assignment;
|
this.assignment = assignment;
|
||||||
this.students = players;
|
this.students = players;
|
||||||
}
|
}
|
||||||
public Id<Course<T>> getId() {
|
public ValueBasedId<Course<T>> getId() {
|
||||||
return courseId;
|
return courseId;
|
||||||
}
|
}
|
||||||
List<Student> getStudents() {
|
List<Student> getStudents() {
|
||||||
@ -110,13 +110,13 @@ public class IdTypeAdapterTest extends TestCase {
|
|||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private static class Assignment<T> {
|
private static class Assignment<T> {
|
||||||
private final Id<Assignment<T>> id;
|
private final ValueBasedId<Assignment<T>> id;
|
||||||
private final T data;
|
private final T data;
|
||||||
|
|
||||||
private Assignment() {
|
private Assignment() {
|
||||||
this(null, null);
|
this(null, null);
|
||||||
}
|
}
|
||||||
public Assignment(Id<Assignment<T>> id, T data) {
|
public Assignment(ValueBasedId<Assignment<T>> id, T data) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.data = data;
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
@ -17,17 +17,43 @@ package com.google.gson.webservice.definition;
|
|||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unit test for {@link CallPath}
|
||||||
|
*
|
||||||
|
* @author inder
|
||||||
|
*/
|
||||||
public class CallPathTest extends TestCase {
|
public class CallPathTest extends TestCase {
|
||||||
|
|
||||||
public void testVersionIsSkipped() {
|
public void testVersionIsSkipped() {
|
||||||
CallPath path = new CallPath("/1.0/rest/service1");
|
CallPath path = new CallPath("/1.0/rest/service1");
|
||||||
assertEquals("/rest/service1", path.get());
|
assertEquals("/rest/service1", path.get());
|
||||||
assertEquals(1D, path.getVersion());
|
assertEquals(1D, path.getVersion());
|
||||||
|
assertEquals(-1L, path.getResourceId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testVersionNotPresent() {
|
public void testVersionNotPresent() {
|
||||||
CallPath path = new CallPath("/rest/service1");
|
CallPath path = new CallPath("/rest/service1");
|
||||||
assertEquals("/rest/service1", path.get());
|
assertEquals("/rest/service1", path.get());
|
||||||
assertEquals(-1D, path.getVersion());
|
assertEquals(-1D, path.getVersion());
|
||||||
|
assertEquals(-1L, path.getResourceId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testResourceIdPresent() {
|
||||||
|
CallPath path = new CallPath("/rest/service/3");
|
||||||
|
assertEquals("/rest/service", path.get());
|
||||||
|
assertEquals(3L, path.getResourceId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testResourceIdWithEndSlashPresent() {
|
||||||
|
CallPath path = new CallPath("/rest/service/3/");
|
||||||
|
assertEquals("/rest/service", path.get());
|
||||||
|
assertEquals(3L, path.getResourceId());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testVersionAndResourceIdPresent() {
|
||||||
|
CallPath path = new CallPath("/3.1/rest/service53/323222");
|
||||||
|
assertEquals(3.1D, path.getVersion());
|
||||||
|
assertEquals("/rest/service53", path.get());
|
||||||
|
assertEquals(323222L, path.getResourceId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,6 +34,7 @@ import com.google.gson.rest.definition.IDFactory;
|
|||||||
*/
|
*/
|
||||||
public class IdMap<I extends ID, T extends HasId<I>> {
|
public class IdMap<I extends ID, T extends HasId<I>> {
|
||||||
public static final Logger LOG = Logger.getLogger(IdMap.class.getName());
|
public static final Logger LOG = Logger.getLogger(IdMap.class.getName());
|
||||||
|
public static final long ID_START_VALUE = 1L;
|
||||||
protected final Map<I, T> map;
|
protected final Map<I, T> map;
|
||||||
private volatile long nextAvailableId;
|
private volatile long nextAvailableId;
|
||||||
private final IDFactory<I> idFactory;
|
private final IDFactory<I> idFactory;
|
||||||
@ -43,7 +44,7 @@ public class IdMap<I extends ID, T extends HasId<I>> {
|
|||||||
*/
|
*/
|
||||||
protected IdMap(Class<? super I> classOfI, Type typeOfId) {
|
protected IdMap(Class<? super I> classOfI, Type typeOfId) {
|
||||||
map = new ConcurrentHashMap<I, T>();
|
map = new ConcurrentHashMap<I, T>();
|
||||||
nextAvailableId = 0;
|
nextAvailableId = ID_START_VALUE;
|
||||||
this.idFactory = new IDFactory<I>(classOfI, typeOfId);
|
this.idFactory = new IDFactory<I>(classOfI, typeOfId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -50,13 +50,17 @@ public final class RestRequestReceiver<I extends ID, R extends RestResource<I, R
|
|||||||
this.spec = spec;
|
this.spec = spec;
|
||||||
}
|
}
|
||||||
|
|
||||||
public RestRequest<I, R> receive(HttpServletRequest request) {
|
public RestRequest<I, R> receive(HttpServletRequest request, I resourceId) {
|
||||||
try {
|
try {
|
||||||
HeaderMap requestParams = buildRequestParams(request);
|
HeaderMap requestParams = buildRequestParams(request);
|
||||||
R requestBody = buildRequestBody(request);
|
R requestBody = buildRequestBody(request);
|
||||||
|
|
||||||
HttpMethod method = HttpMethod.getMethod(request.getMethod());
|
HttpMethod method = HttpMethod.getMethod(request.getMethod());
|
||||||
return new RestRequest<I, R>(method, requestParams, requestBody, spec.getResourceType());
|
String simulatedMethod = request.getHeader(HttpMethod.SIMULATED_METHOD_HEADER);
|
||||||
|
if (simulatedMethod != null && !simulatedMethod.equals("")) {
|
||||||
|
method = HttpMethod.getMethod(simulatedMethod);
|
||||||
|
}
|
||||||
|
return new RestRequest<I, R>(method, requestParams, resourceId, requestBody, spec.getResourceType());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new WebServiceSystemException(e);
|
throw new WebServiceSystemException(e);
|
||||||
} catch (JsonParseException e) {
|
} catch (JsonParseException e) {
|
||||||
|
Loading…
Reference in New Issue
Block a user