-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Re-implement and adapt resource delegate generators as an extension.
Summary of squashed commits: Extract part of delegated method generation to velocity + framework. Extracted the complete output of delegated methods to template Added basic root pom to help IDE import Imported client and test code for delegates. Use parameterized name when possible canGenerate() should not throw Generate delegates for sub resources Ensure delegate methods are valid before generating Don't use die() to fake a return value Improved method generator restrictions
- Loading branch information
Showing
26 changed files
with
1,820 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
<?xml version="1.0" encoding="UTF-8"?> | ||
<project xmlns="http://maven.apache.org/POM/4.0.0" | ||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
|
||
<parent> | ||
<groupId>org.sonatype.oss</groupId> | ||
<artifactId>oss-parent</artifactId> | ||
<version>9</version> | ||
</parent> | ||
|
||
<groupId>com.gwtplatform.extensions</groupId> | ||
<artifactId>dispatch-rest-delegates</artifactId> | ||
<version>${gwtp.version}</version> | ||
<packaging>jar</packaging> | ||
<name>Rest-Dispatch Resource Delegates</name> | ||
<description>Allow Rest-Dispatch resources to return their raw result type directly.</description> | ||
<inceptionYear>2014</inceptionYear> | ||
<url>http://arcbees.github.io/GWTP/</url> | ||
|
||
<properties> | ||
<gwtp.version>1.4-SNAPSHOT</gwtp.version> | ||
<gwt.version>2.7.0</gwt.version> | ||
<mockito.version>1.10.8</mockito.version> | ||
|
||
<maven-checkstyle-plugin.version>2.13</maven-checkstyle-plugin.version> | ||
</properties> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>com.gwtplatform</groupId> | ||
<artifactId>gwtp-dispatch-rest</artifactId> | ||
<version>${gwtp.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.google.gwt</groupId> | ||
<artifactId>gwt-user</artifactId> | ||
<version>${gwt.version}</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>com.google.gwt</groupId> | ||
<artifactId>gwt-dev</artifactId> | ||
<version>${gwt.version}</version> | ||
</dependency> | ||
|
||
<!-- For testing tools --> | ||
<dependency> | ||
<groupId>org.mockito</groupId> | ||
<artifactId>mockito-core</artifactId> | ||
<version>${mockito.version}</version> | ||
<scope>compile</scope> | ||
<optional>true</optional> | ||
</dependency> | ||
</dependencies> | ||
|
||
<build> | ||
<resources> | ||
<!-- Bundle sources with the jar, so they are visible to GWT's compiler --> | ||
<resource> | ||
<directory>src/main/java</directory> | ||
<includes> | ||
<include>**/*.java</include> | ||
</includes> | ||
</resource> | ||
<resource> | ||
<directory>src/main/resources</directory> | ||
</resource> | ||
</resources> | ||
|
||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-checkstyle-plugin</artifactId> | ||
<version>${maven-checkstyle-plugin.version}</version> | ||
|
||
<configuration> | ||
<configLocation>/gwtp-checkstyle.xml</configLocation> | ||
<suppressionsLocation>/gwtp-suppressions.xml</suppressionsLocation> | ||
<propertiesLocation>/gwtp-checkstyle.properties</propertiesLocation> | ||
<propertyExpansion>basedir=${basedir}</propertyExpansion> | ||
<consoleOutput>true</consoleOutput> | ||
<failsOnError>true</failsOnError> | ||
<linkXRef>false</linkXRef> | ||
<includeTestSourceDirectory>true</includeTestSourceDirectory> | ||
</configuration> | ||
|
||
<dependencies> | ||
<dependency> | ||
<groupId>com.gwtplatform</groupId> | ||
<artifactId>gwtp-build-tools</artifactId> | ||
<version>${gwtp.version}</version> | ||
</dependency> | ||
</dependencies> | ||
|
||
<executions> | ||
<execution> | ||
<id>validate</id> | ||
<phase>validate</phase> | ||
<goals> | ||
<goal>checkstyle</goal> | ||
</goals> | ||
</execution> | ||
</executions> | ||
</plugin> | ||
</plugins> | ||
</build> | ||
</project> |
95 changes: 95 additions & 0 deletions
95
...rc/main/java/com/gwtplatform/dispatch/rest/delegates/client/AbstractResourceDelegate.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
/** | ||
* 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.delegates.client; | ||
|
||
import com.google.gwt.user.client.rpc.AsyncCallback; | ||
import com.gwtplatform.dispatch.client.DelegatingDispatchRequest; | ||
import com.gwtplatform.dispatch.rest.client.RestDispatch; | ||
import com.gwtplatform.dispatch.rest.shared.RestAction; | ||
import com.gwtplatform.dispatch.shared.DispatchRequest; | ||
|
||
/** | ||
* Common code used by generated implementations of {@link ResourceDelegate}. | ||
* | ||
* @param <T> The resource used by this delegate. | ||
*/ | ||
public abstract class AbstractResourceDelegate<T> implements ResourceDelegate<T>, Cloneable { | ||
private static final AsyncCallback<Object> NO_OP_CALLBACK = new AsyncCallback<Object>() { | ||
@Override | ||
public void onFailure(Throwable caught) { | ||
} | ||
|
||
@Override | ||
public void onSuccess(Object result) { | ||
} | ||
}; | ||
|
||
protected final RestDispatch dispatcher; | ||
|
||
protected AsyncCallback<?> callback; | ||
protected DelegatingDispatchRequest delegatingDispatchRequest; | ||
|
||
protected AbstractResourceDelegate(RestDispatch dispatcher) { | ||
this.dispatcher = dispatcher; | ||
} | ||
|
||
@Override | ||
public ResourceDelegate<T> withDelegatingDispatchRequest(DelegatingDispatchRequest delegatingDispatchRequest) { | ||
AbstractResourceDelegate<T> delegate = createCopy(); | ||
delegate.delegatingDispatchRequest = delegatingDispatchRequest; | ||
|
||
return this; | ||
} | ||
|
||
@Override | ||
public T withoutCallback() { | ||
return withCallback(NO_OP_CALLBACK); | ||
} | ||
|
||
@Override | ||
public T withCallback(AsyncCallback<?> callback) { | ||
AbstractResourceDelegate<T> delegate = createCopy(); | ||
delegate.callback = callback; | ||
|
||
return delegate.asResource(); | ||
} | ||
|
||
@SuppressWarnings({"unchecked"}) | ||
protected <R> void execute(RestAction<R> action) { | ||
DispatchRequest dispatchRequest = dispatcher.execute(action, (AsyncCallback<R>) callback); | ||
|
||
if (delegatingDispatchRequest != null) { | ||
delegatingDispatchRequest.setDelegate(dispatchRequest); | ||
} | ||
} | ||
|
||
protected void copyFields(AbstractResourceDelegate<?> delegate) { | ||
delegate.delegatingDispatchRequest = delegatingDispatchRequest; | ||
delegate.callback = callback; | ||
} | ||
|
||
protected abstract AbstractResourceDelegate<T> newInstance(); | ||
|
||
protected abstract T asResource(); | ||
|
||
private AbstractResourceDelegate<T> createCopy() { | ||
AbstractResourceDelegate<T> delegate = newInstance(); | ||
copyFields(delegate); | ||
|
||
return delegate; | ||
} | ||
} |
93 changes: 93 additions & 0 deletions
93
...egates/src/main/java/com/gwtplatform/dispatch/rest/delegates/client/ResourceDelegate.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
/** | ||
* 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.delegates.client; | ||
|
||
import com.google.gwt.user.client.rpc.AsyncCallback; | ||
import com.gwtplatform.dispatch.client.DelegatingDispatchRequest; | ||
import com.gwtplatform.dispatch.shared.DispatchRequest; | ||
|
||
/** | ||
* Delegate used to build and call HTTP resources. You can inject this interface instead of injecting your resource | ||
* interface and {@link com.gwtplatform.dispatch.rest.client.RestDispatch} to simplify your code. Note that if your | ||
* resource interfaces don't return {@link com.gwtplatform.dispatch.rest.shared.RestAction RestAction<?>}s but the | ||
* result type directly, you will need to inject a {@link ResourceDelegate} to use your resource. | ||
* <p/> | ||
* This delegate will not send the HTTP request until you call a method, that is not a sub-resource, from the underlying | ||
* resource. The underlying resource is returned when either {@link #withoutCallback()} or {@link | ||
* #withCallback(AsyncCallback)} are called. | ||
* <p/> | ||
* The following example shows how to retrieve the {@link DispatchRequest} and delete a potential car: | ||
* <pre><code> | ||
* {@literal @}Path("/cars") | ||
* public interface CarsResource { | ||
* CarResource car(int id); | ||
* } | ||
* <p/> | ||
* public interface CarResource { | ||
* {@literal @}DELETE | ||
* void delete(); | ||
* } | ||
* <p/> | ||
* public class CarPresenter { | ||
* private final ResourceDelegate<CarsResource> carsResourceDelegate; | ||
* <p/> | ||
* {@literal @}Inject | ||
* CarPresenter(ResourceDelegate<CarsResource> carsResourceDelegate) { | ||
* this.carsResourceDelegate = carsResourceDelegate; | ||
* } | ||
* <p/> | ||
* {@literal @}Override | ||
* public void onReveal() { | ||
* DelegatingDispatchRequest dispatchRequest = new DelegatingDispatchRequest(); | ||
* <p/> | ||
* carsResourceDelegate | ||
* .withDelegatingDispatchRequest(dispatchRequest) | ||
* .withCallback(new AsyncCallback<Void>() {/{@literal * snip *}/}); | ||
* .car(8) | ||
* .delete(); | ||
* } | ||
* } | ||
* </code></pre> | ||
* | ||
* @param <T> The type of the resource used by this delegate. | ||
*/ | ||
public interface ResourceDelegate<T> { | ||
/** | ||
* Used as a mean to access the {@link DispatchRequest} instance returned by the underlying HTTP call. This may be | ||
* useful for canceling a long running call. {@code delegatingDispatchRequest} will be populated when the HTTP call | ||
* is sent, that is when you call any method from the service used by this delegate. | ||
* | ||
* @param delegatingDispatchRequest the {@link DelegatingDispatchRequest} to populate when the HTTP call is sent. | ||
* | ||
* @return a copy of this {@link ResourceDelegate} using the provided {@link DelegatingDispatchRequest}. | ||
*/ | ||
ResourceDelegate<T> withDelegatingDispatchRequest(DelegatingDispatchRequest delegatingDispatchRequest); | ||
|
||
/** | ||
* Provide the callback when the HTTP call returns or if any error occur. | ||
* | ||
* @param callback The callback to use when the HTTP call returns or if any error occur. | ||
* | ||
* @return the service wrapped by this delegate. | ||
*/ | ||
T withCallback(AsyncCallback<?> callback); | ||
|
||
/** | ||
* This method is the same as colling {@link #withCallback(AsyncCallback)} with a no-op callback. | ||
*/ | ||
T withoutCallback(); | ||
} |
78 changes: 78 additions & 0 deletions
78
...java/com/gwtplatform/dispatch/rest/delegates/rebind/AbstractDelegatedMethodGenerator.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/** | ||
* 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.delegates.rebind; | ||
|
||
import org.apache.velocity.app.VelocityEngine; | ||
|
||
import com.google.gwt.core.ext.GeneratorContext; | ||
import com.google.gwt.core.ext.typeinfo.JMethod; | ||
import com.gwtplatform.dispatch.rest.rebind.AbstractVelocityGenerator; | ||
import com.gwtplatform.dispatch.rest.rebind.resource.MethodContext; | ||
import com.gwtplatform.dispatch.rest.rebind.resource.MethodDefinition; | ||
import com.gwtplatform.dispatch.rest.rebind.resource.MethodGenerator; | ||
import com.gwtplatform.dispatch.rest.rebind.resource.ResourceDefinition; | ||
import com.gwtplatform.dispatch.rest.rebind.utils.Logger; | ||
|
||
public abstract class AbstractDelegatedMethodGenerator extends AbstractVelocityGenerator implements MethodGenerator { | ||
private DelegatedMethodContext context; | ||
|
||
protected AbstractDelegatedMethodGenerator( | ||
Logger logger, | ||
GeneratorContext context, | ||
VelocityEngine velocityEngine) { | ||
super(logger, context, velocityEngine); | ||
} | ||
|
||
@Override | ||
public byte getPriority() { | ||
// This really need to run before core method generators | ||
return (byte) (super.getPriority() - 5); | ||
} | ||
|
||
protected void setContext(MethodContext context) { | ||
this.context = (DelegatedMethodContext) context; | ||
} | ||
|
||
protected ResourceDefinition getResourceDefinition() { | ||
return context.getResourceDefinition(); | ||
} | ||
|
||
protected MethodDefinition getMethodDefinition() { | ||
return context.getMethodDefinition(); | ||
} | ||
|
||
protected JMethod getMethod() { | ||
return getMethodDefinition().getMethod(); | ||
} | ||
|
||
protected void replaceMethodContent(StringBuilder methodBuilder, String newContent) { | ||
int openBraceIndex = methodBuilder.indexOf("{"); | ||
int closeBraceIndex = methodBuilder.lastIndexOf("}"); | ||
|
||
methodBuilder.replace(openBraceIndex + 1, closeBraceIndex, newContent); | ||
} | ||
|
||
@Override | ||
protected String getImplName() { | ||
return getResourceDefinition() + DelegateGenerator.IMPL + "#" + getMethod().getName(); | ||
} | ||
|
||
@Override | ||
protected String getPackageName() { | ||
return getResourceDefinition().getPackageName(); | ||
} | ||
} |
Oops, something went wrong.