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. */