Add @SkipInterfaceValidation to RequestFactory to selectively bypass matching
interface methods to domain methods.
http://gwt-code-reviews.appspot.com/1338807
Patch by: t.broyer
Review by: bobv
git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@10022 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/web/bindery/requestfactory/gwt/rebind/model/EntityProxyModel.java b/user/src/com/google/web/bindery/requestfactory/gwt/rebind/model/EntityProxyModel.java
index 139aef0..87c2eac 100644
--- a/user/src/com/google/web/bindery/requestfactory/gwt/rebind/model/EntityProxyModel.java
+++ b/user/src/com/google/web/bindery/requestfactory/gwt/rebind/model/EntityProxyModel.java
@@ -44,10 +44,6 @@
return toReturn;
}
- public void setProxyFor(Class<?> value) {
- toReturn.proxyFor = value;
- }
-
public void setQualifiedBinaryName(String qualifiedBinaryName) {
toReturn.qualifiedBinaryName = qualifiedBinaryName;
}
@@ -74,7 +70,6 @@
ENTITY, VALUE
}
- private Class<?> proxyFor;
private String qualifiedBinaryName;
private String qualifiedSourceName;
private List<RequestMethod> requestMethods;
@@ -92,10 +87,6 @@
visitor.endVisit(this);
}
- public Class<?> getProxyFor() {
- return proxyFor;
- }
-
public String getQualifiedBinaryName() {
return qualifiedBinaryName;
}
diff --git a/user/src/com/google/web/bindery/requestfactory/server/RequestFactoryInterfaceValidator.java b/user/src/com/google/web/bindery/requestfactory/server/RequestFactoryInterfaceValidator.java
index b6841ab..5e3dfe3 100644
--- a/user/src/com/google/web/bindery/requestfactory/server/RequestFactoryInterfaceValidator.java
+++ b/user/src/com/google/web/bindery/requestfactory/server/RequestFactoryInterfaceValidator.java
@@ -39,6 +39,7 @@
import com.google.web.bindery.requestfactory.shared.RequestFactory;
import com.google.web.bindery.requestfactory.shared.Service;
import com.google.web.bindery.requestfactory.shared.ServiceName;
+import com.google.web.bindery.requestfactory.shared.SkipInterfaceValidation;
import com.google.web.bindery.requestfactory.shared.ValueProxy;
import java.io.IOException;
@@ -416,17 +417,27 @@
if ("<clinit>".equals(name) || "<init>".equals(name)) {
return null;
}
- RFMethod method = new RFMethod(name, desc);
+ final RFMethod method = new RFMethod(name, desc);
method.setDeclaredStatic((access & Opcodes.ACC_STATIC) != 0);
method.setDeclaredSignature(signature);
methods.add(method);
- return null;
+
+ return new EmptyVisitor() {
+ @Override
+ public AnnotationVisitor visitAnnotation(String desc, boolean visible) {
+ if (desc.equals(Type.getDescriptor(SkipInterfaceValidation.class))) {
+ method.setValidationSkipped(true);
+ }
+ return null;
+ }
+ };
}
}
private static class RFMethod extends Method {
private boolean isDeclaredStatic;
private String signature;
+ private boolean isValidationSkipped;
public RFMethod(String name, String desc) {
super(name, desc);
@@ -440,6 +451,10 @@
return isDeclaredStatic;
}
+ public boolean isValidationSkipped() {
+ return isValidationSkipped;
+ }
+
public void setDeclaredSignature(String signature) {
this.signature = signature;
}
@@ -448,6 +463,10 @@
isDeclaredStatic = value;
}
+ public void setValidationSkipped(boolean isValidationSkipped) {
+ this.isValidationSkipped = isValidationSkipped;
+ }
+
@Override
public String toString() {
return (isDeclaredStatic ? "static " : "") + super.toString();
@@ -727,7 +746,7 @@
* annotation</li>
* <li>The domain object has getId() and getVersion() methods</li>
* <li>All property methods in the EntityProxy can be mapped onto an
- * equivalent domain method</li>
+ * equivalent domain method (unless validation is skipped for the method)</li>
* <li>All referenced proxy types are valid</li>
* </ul>
*
@@ -778,7 +797,7 @@
* <li><code>binaryName</code> has a {@link Service} or {@link ServiceName}
* annotation</li>
* <li>All service methods in the RequestContext can be mapped onto an
- * equivalent domain method</li>
+ * equivalent domain method (unless validation is skipped for the method)</li>
* <li>All referenced EntityProxy types are valid</li>
* </ul>
*
@@ -886,7 +905,7 @@
* <li><code>binaryName</code> has a {@link ProxyFor} or {@link ProxyForName}
* annotation</li>
* <li>All property methods in the EntityProxy can be mapped onto an
- * equivalent domain method</li>
+ * equivalent domain method (unless validation is skipped for the method)</li>
* <li>All referenced proxy types are valid</li>
* </ul>
*
@@ -985,7 +1004,7 @@
returnType, method.getArgumentTypes()));
RFMethod found = findCompatibleServiceMethod(logger, domainServiceType,
- searchFor);
+ searchFor, !method.isValidationSkipped());
if (found != null) {
boolean isInstance = isAssignable(logger, instanceRequestIntf,
@@ -1069,11 +1088,12 @@
* domain object.
*/
private void checkPropertyMethod(ErrorContext logger,
- Method clientPropertyMethod, Type domainType) {
+ RFMethod clientPropertyMethod, Type domainType) {
logger = logger.setMethod(clientPropertyMethod);
findCompatiblePropertyMethod(logger, domainType,
- createDomainMethod(logger, clientPropertyMethod));
+ createDomainMethod(logger, clientPropertyMethod),
+ !clientPropertyMethod.isValidationSkipped());
}
private void checkUnresolvedKeyTypes(ErrorContext logger) {
@@ -1207,8 +1227,8 @@
* hierarchy that is assignment-compatible with the given Method.
*/
private RFMethod findCompatiblePropertyMethod(final ErrorContext logger,
- Type domainType, Method searchFor) {
- return findCompatibleMethod(logger, domainType, searchFor, true, false,
+ Type domainType, Method searchFor, boolean mustFind) {
+ return findCompatibleMethod(logger, domainType, searchFor, mustFind, false,
false);
}
@@ -1217,8 +1237,8 @@
* hierarchy that is assignment-compatible with the given Method.
*/
private RFMethod findCompatibleServiceMethod(final ErrorContext logger,
- Type domainType, Method searchFor) {
- return findCompatibleMethod(logger, domainType, searchFor, true, false,
+ Type domainType, Method searchFor, boolean mustFind) {
+ return findCompatibleMethod(logger, domainType, searchFor, mustFind, false,
true);
}
diff --git a/user/src/com/google/web/bindery/requestfactory/shared/SkipInterfaceValidation.java b/user/src/com/google/web/bindery/requestfactory/shared/SkipInterfaceValidation.java
new file mode 100644
index 0000000..ad6575f
--- /dev/null
+++ b/user/src/com/google/web/bindery/requestfactory/shared/SkipInterfaceValidation.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2011 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.web.bindery.requestfactory.shared;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation on methods of {@link RequestContext}, {@link EntityProxy}, or
+ * {@link ValueProxy} interfaces so that the
+ * {@link com.google.web.bindery.requestfactory.server.RequestFactoryInterfaceValidator
+ * RequestFactoryInterfaceValidator} doesn't enforce the presence of a
+ * corresponding method on the domain type.
+ */
+@Documented
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface SkipInterfaceValidation {
+}
diff --git a/user/test/com/google/web/bindery/requestfactory/server/RequestFactoryInterfaceValidatorTest.java b/user/test/com/google/web/bindery/requestfactory/server/RequestFactoryInterfaceValidatorTest.java
index 98fa37d..698b2b4 100644
--- a/user/test/com/google/web/bindery/requestfactory/server/RequestFactoryInterfaceValidatorTest.java
+++ b/user/test/com/google/web/bindery/requestfactory/server/RequestFactoryInterfaceValidatorTest.java
@@ -27,6 +27,7 @@
import com.google.web.bindery.requestfactory.shared.Service;
import com.google.web.bindery.requestfactory.shared.ServiceName;
import com.google.web.bindery.requestfactory.shared.SimpleRequestFactory;
+import com.google.web.bindery.requestfactory.shared.SkipInterfaceValidation;
import com.google.web.bindery.requestfactory.shared.ValueProxy;
import com.google.web.bindery.requestfactory.shared.impl.FindRequest;
@@ -247,6 +248,28 @@
Request<Integer> doesNotExist(int a);
}
+ @Service(Domain.class)
+ interface SkipValidationContext extends RequestContext {
+ @SkipInterfaceValidation
+ Request<Integer> doesNotExist(int a);
+
+ @SkipInterfaceValidation
+ Request<Long> foo(int a);
+ }
+
+ @Service(Domain.class)
+ interface SkipValidationProxy extends ValueProxy {
+ @SkipInterfaceValidation
+ boolean doesNotExist();
+ }
+
+ @Service(Domain.class)
+ interface SkipValidationChecksReferredProxies extends ValueProxy {
+ @SkipInterfaceValidation
+ // still validates other proxies
+ DomainProxyMissingAnnotation getDomainProxyMissingAnnotation();
+ }
+
@ProxyFor(Domain.class)
@ProxyForName("Domain")
@Service(Domain.class)
@@ -421,6 +444,21 @@
assertTrue(v.isPoisoned());
}
+ public void testSkipValidationChecksReferredProxies() {
+ v.validateValueProxy(SkipValidationChecksReferredProxies.class.getName());
+ assertTrue(v.isPoisoned());
+ }
+
+ public void testSkipValidationContext() {
+ v.validateRequestContext(SkipValidationContext.class.getName());
+ assertFalse(v.isPoisoned());
+ }
+
+ public void testSkipValidationProxy() {
+ v.validateValueProxy(SkipValidationProxy.class.getName());
+ assertFalse(v.isPoisoned());
+ }
+
/**
* Perform a full test of the RequestFactory used for most tests.
*/