Skip to content

Commit

Permalink
Fixing issue ArcBees#201
Browse files Browse the repository at this point in the history
If a field has a UseProxy annotation and is of type List or Set, then in
the generated Proxy class this field (and its getters and setters) will
also be of type List or Set.
Extending test case for both scenarios; unfortunately it's not possible
to test if the generic type of the List or Set has been generated
correctly.


Former-commit-id: 770f013
  • Loading branch information
bmoritz committed Jun 25, 2013
1 parent 6b6d110 commit b4efb93
Show file tree
Hide file tree
Showing 4 changed files with 113 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,14 @@ protected void generateProxy(Element proxyElement, String targetPackage, String[
String proxyElementClassName = reflection.getClassName();
String proxyElementPackage = reflection.getPackageName();

String preparedProxyElementClassName = proxyElementClassName;
String preparedProxyElementPackage = proxyElementPackage;
// Magic: By default proxies should be available for client and server side.
String preparedProxyElementClassName = proxyElementClassName.replace(".server", ".shared");
String preparedProxyElementPackage = proxyElementPackage.replace(".server", ".shared");

if (targetPackage != null && !targetPackage.isEmpty()) {
// Prepare user defined proxy target package and do not replace server with shared.
preparedProxyElementClassName = targetPackage + "." + proxyElementSimpleName;
preparedProxyElementPackage = targetPackage;
} else {
// Magic: By default proxies should be available for client and server side.
preparedProxyElementClassName = proxyElementClassName.replace(".server", ".shared");
preparedProxyElementPackage = proxyElementPackage.replace(".server", ".shared");
}

String proxySimpleName = proxyElementSimpleName + "Proxy";
Expand All @@ -89,11 +86,6 @@ protected void generateProxy(Element proxyElement, String targetPackage, String[
Writer sourceWriter = getEnvironment().getFiler().createSourceFile(proxyClassName,
proxyElement).openWriter();
writer = new InterfaceGenerationHelper(sourceWriter);

Collection<VariableElement> allFields = reflection.getNonConstantFields();
Collection<VariableElement> setterFields = reflection.filterFields(allFields, filterSetter);
Collection<VariableElement> getterFields = reflection.filterFields(allFields, filterGetter);

writer.generatePackageDeclaration(preparedProxyElementPackage);

if (isEmbeddedType) {
Expand All @@ -104,12 +96,16 @@ protected void generateProxy(Element proxyElement, String targetPackage, String[

writer.println();

Collection<VariableElement> allFields = reflection.getNonConstantFields();

// Generate getters.
Collection<VariableElement> getterFields = reflection.filterFields(allFields, filterGetter);
for (VariableElement getterField : getterFields) {
generateGetter(writer, getterField);
}

// Generate setters.
Collection<VariableElement> setterFields = reflection.filterFields(allFields, filterSetter);
for (VariableElement setterField : setterFields) {
generateSetter(writer, setterField);
}
Expand Down Expand Up @@ -166,9 +162,9 @@ protected void generateGetter(InterfaceGenerationHelper writer, VariableElement
UseProxy useProxyAnnotation = getterField.getAnnotation(UseProxy.class);
UseProxyName useProxyNameAnnotation = getterField.getAnnotation(UseProxyName.class);
if (useProxyAnnotation != null) {
writer.generateGetter(getterField.getSimpleName().toString(), getProxyTypeMirror(useProxyAnnotation)
.toString());
} else if (useProxyAnnotation == null && useProxyNameAnnotation != null) {
writer.generateGetter(getterField.getSimpleName().toString(), getProxyTypeMirrorName(useProxyAnnotation,
getterField.asType()));
} else if (useProxyNameAnnotation != null) {
writer.generateGetter(getterField.getSimpleName().toString(), useProxyNameAnnotation.value());
} else {
writer.generateGetter(getterField);
Expand All @@ -180,33 +176,46 @@ protected void generateSetter(InterfaceGenerationHelper writer, VariableElement
UseProxy useProxyAnnotation = setterField.getAnnotation(UseProxy.class);
UseProxyName useProxyNameAnnotation = setterField.getAnnotation(UseProxyName.class);
if (useProxyAnnotation != null) {
writer.generateSetter(setterField.getSimpleName().toString(), getProxyTypeMirror(useProxyAnnotation)
.toString());
} else if (useProxyAnnotation == null && useProxyNameAnnotation != null) {
writer.generateSetter(setterField.getSimpleName().toString(), getProxyTypeMirrorName(useProxyAnnotation,
setterField.asType()));
} else if (useProxyNameAnnotation != null) {
writer.generateSetter(setterField.getSimpleName().toString(), useProxyNameAnnotation.value());
} else {
writer.generateSetter(setterField);
}
}

/**
* Workaround for MirroredTypeException (Attempt to access Class object for
* TypeMirror).
* Workaround for MirroredTypeException (Attempt to access Class object for TypeMirror).
*
* @see http://goo.gl/7ee2R
* @see <a href="http://goo.gl/7ee2R">Getting class values from annotations in an annotationprocessor</a>
*/
protected final TypeMirror getProxyTypeMirror(UseProxy useProxyAnnotation) {
protected final String getProxyTypeMirrorName(UseProxy useProxyAnnotation, TypeMirror originalTypeMirror) {
TypeMirror mirror = null;
try {
useProxyAnnotation.value();
} catch (MirroredTypeException e) {
mirror = e.getTypeMirror();
}
return mirror;

return nestIntoCollectionIfNeccessary(mirror, originalTypeMirror);
}

private String nestIntoCollectionIfNeccessary(TypeMirror mirror, TypeMirror originalTypeMirror) {
String originalTypeDeclaration = originalTypeMirror.toString();
StringBuilder builder = new StringBuilder();
if (originalTypeDeclaration.startsWith("java.util.List<")) {
builder.append("java.util.List<").append(mirror.toString()).append(">");
} else if (originalTypeDeclaration.startsWith("java.util.Set<")) {
builder.append("java.util.Set<").append(mirror.toString()).append(">");
} else {
builder.append(mirror.toString());
}
return builder.toString();
}

/**
* @see #getTypeMirror(UseProxy)
* @see #getProxyTypeMirrorName(com.gwtplatform.dispatch.annotation.UseProxy, javax.lang.model.type.TypeMirror)
*/
protected final TypeMirror getLocatorTypeMirror(GenProxy genProxyAnnotation) {
TypeMirror mirror = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package com.gwtplatform.dispatch.annotation;

import java.util.List;

/**
* For testing purposes only.
*
Expand All @@ -33,6 +35,9 @@ public class Employee {
private Long id;
private Integer version;

@UseProxy(DetailProxy.class)
private List<Detail> details;

@UseProxyName("com.gwtplatform.dispatch.annotation.proxy.EmployeeProxy")
private Employee supervisor;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@

package com.gwtplatform.dispatch.annotation;

import java.util.Set;

/**
* For testing purposes only.
*
Expand All @@ -34,4 +36,7 @@ public class Person {

@UseProxy(DetailProxy.class)
Detail detail;

@UseProxy(DetailProxy.class)
Set<Detail> details;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,66 +16,111 @@

package com.gwtplatform.dispatch.annotation;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Set;

import org.junit.Test;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

import com.google.web.bindery.requestfactory.shared.EntityProxy;
import com.google.web.bindery.requestfactory.shared.ProxyFor;
import com.google.web.bindery.requestfactory.shared.ValueProxy;
import com.gwtplatform.dispatch.annotation.proxy.AddressProxy;
import com.gwtplatform.dispatch.annotation.proxy.EmployeeProxy;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

/**
* This test is being run by ant, but is not run in eclipse.
* <p/>
* TODO: Make a test suite with a couple of permutations (with/without Order, Optional, both...).
*
* @author Brendan Doherty
* @author Florian Sauter
*/
public class ProxyAnnotationProcessingTest {

@Test
public void shouldGenerateEntityProxy() throws SecurityException, NoSuchMethodException {
public void shouldGenerateEntityProxy() throws NoSuchMethodException {
// If the proxy exists and we can access the class element, the class type generation was successful.
Class<?> proxyClass = EmployeeProxy.class;
ProxyFor proxyAnnotation = EmployeeProxy.class.getAnnotation(ProxyFor.class);

// Check if all expected methods have been generated.
proxyClass.getMethod("getDisplayName");
proxyClass.getMethod("getSupervisorKey");
proxyClass.getMethod("getId");
proxyClass.getMethod("getSupervisor");
proxyClass.getMethod("setSupervisorKey", Long.class);
assertNotNull(proxyClass.getMethod("getDisplayName"));
assertNotNull(proxyClass.getMethod("getSupervisorKey"));
assertNotNull(proxyClass.getMethod("getId"));
assertNotNull(proxyClass.getMethod("getSupervisor"));
assertNotNull(proxyClass.getMethod("setSupervisorKey", Long.class));
// Due to the @UseProxyName annotation on the supervisor field, setSupervisor
// should take the given proxy (instead of the origin domain type) as argument.
proxyClass.getMethod("setSupervisor", EmployeeProxy.class);
proxyClass.getMethod("setVersion", Integer.class);
assertNotNull(proxyClass.getMethod("setSupervisor", EmployeeProxy.class));
assertNotNull(proxyClass.getMethod("setVersion", Integer.class));
// Since we use a EntityProxy this method must be present.
proxyClass.getMethod("stableId");
assertNotNull(proxyClass.getMethod("stableId"));

// Assert that methods that should be filtered have not been generated.
boolean filteredFieldsWereNotGenerated = false;
try {
proxyClass.getMethod("setId", Long.class);
proxyClass.getMethod("getVersion", Long.class);
} catch (NoSuchMethodException e) {
filteredFieldsWereNotGenerated = true;
}

assertTrue(filteredFieldsWereNotGenerated);
assertTrue(EntityProxy.class.isAssignableFrom(EmployeeProxy.class));

ProxyFor proxyAnnotation = EmployeeProxy.class.getAnnotation(ProxyFor.class);
assertEquals(proxyAnnotation.value(), Employee.class);
assertEquals(proxyAnnotation.locator(), EmployeeLocator.class);
}

@Test(expected = NoSuchMethodException.class)
public void shouldNotGenerateFilteredMethods() throws NoSuchMethodException {
Class<?> proxyClass = EmployeeProxy.class;

// Assert that methods that should be filtered have not been generated.
proxyClass.getMethod("setId", Long.class);
proxyClass.getMethod("getVersion", Long.class);
}

@Test
public void shouldGenerateListProxy() throws NoSuchMethodException {
// If the proxy exists and we can access the class element, the class type generation was successful.
Class<?> proxyClass = EmployeeProxy.class;

// Check if all methods for details parameter have been generated
Method getDetailsMethod = proxyClass.getMethod("getDetails");
assertNotNull(getDetailsMethod);
Class<?> returnType = getDetailsMethod.getReturnType();
assertNotNull(returnType);
assertTrue(returnType.isAssignableFrom(List.class));

Method setDetailsMethod = proxyClass.getMethod("setDetails", List.class);
assertNotNull(setDetailsMethod);
Class<?>[] parameterTypes = setDetailsMethod.getParameterTypes();
assertNotNull(parameterTypes);
assertThat(parameterTypes.length, equalTo(1));
assertTrue(parameterTypes[0].isAssignableFrom(List.class));
}

@Test
public void shouldGenerateValueProxy() throws SecurityException, NoSuchMethodException {
public void shouldGenerateSetProxy() throws NoSuchMethodException {
// If the proxy exists and we can access the class element, the class type generation was successful.
Class<?> proxyClass = PersonProxy.class;

// Check if all methods for details parameter have been generated
Method getDetailsMethod = proxyClass.getMethod("getDetails");
assertNotNull(getDetailsMethod);
Class<?> returnType = getDetailsMethod.getReturnType();
assertNotNull(returnType);
assertTrue(returnType.isAssignableFrom(Set.class));

Method setDetailsMethod = proxyClass.getMethod("setDetails", Set.class);
assertNotNull(setDetailsMethod);
Class<?>[] parameterTypes = setDetailsMethod.getParameterTypes();
assertNotNull(parameterTypes);
assertThat(parameterTypes.length, equalTo(1));
assertTrue(parameterTypes[0].isAssignableFrom(Set.class));
}

@Test
public void shouldGenerateValueProxy() throws NoSuchMethodException {
ProxyFor proxyAnnotation = AddressProxy.class.getAnnotation(ProxyFor.class);
assertTrue(ValueProxy.class.isAssignableFrom(AddressProxy.class));
assertEquals(proxyAnnotation.value(), Address.class);
}

}

0 comments on commit b4efb93

Please sign in to comment.