DATACASS-164: dyn proxies now implement Serializable, don't require MapId extension
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
package org.springframework.data.cassandra.repository.support;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class IdInterfaceException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = -1635695314254522703L;
|
||||
|
||||
String idInterfaceName;
|
||||
String method;
|
||||
|
||||
public IdInterfaceException(Class<?> idInterface, Method method, String message) {
|
||||
this(idInterface.getClass().getName(), method == null ? null : method.toString(), message);
|
||||
}
|
||||
|
||||
public IdInterfaceException(String idInterfaceName, String method, String message) {
|
||||
super(message);
|
||||
this.idInterfaceName = idInterfaceName;
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public String getIdInterfaceName() {
|
||||
return idInterfaceName;
|
||||
}
|
||||
|
||||
public String getMethod() {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors
|
||||
*
|
||||
* 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 org.springframework.data.cassandra.repository.support;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
* Aggregator of multiple violations for convenience when verifying id interfaces. This allows the framework to
|
||||
* communicate all errors at once, rather than one at a time.
|
||||
*
|
||||
* @author Matthew T. Adams
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class IdInterfaceExceptions extends RuntimeException {
|
||||
|
||||
Collection<IdInterfaceException> exceptions = new LinkedList<IdInterfaceException>();
|
||||
String idInterfaceName;
|
||||
|
||||
public IdInterfaceExceptions(Class<?> idInterface) {
|
||||
this.idInterfaceName = idInterface.getClass().getName();
|
||||
}
|
||||
|
||||
public void add(IdInterfaceException e) {
|
||||
exceptions.add(e);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of the {@link IdInterfaceException}s aggregated within.
|
||||
*/
|
||||
public Collection<IdInterfaceException> getExceptions() {
|
||||
return exceptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of the {@link IdInterfaceException} messages aggregated within.
|
||||
*/
|
||||
public Collection<String> getMessages() {
|
||||
Collection<String> messages = new LinkedList<String>();
|
||||
for (IdInterfaceException e : exceptions) {
|
||||
messages.add(e.getMessage());
|
||||
}
|
||||
return messages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of exceptions aggregated in this exception.
|
||||
*/
|
||||
public int getCount() {
|
||||
return exceptions.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
StringBuilder builder = new StringBuilder(idInterfaceName).append(":\n");
|
||||
for (IdInterfaceException e : exceptions) {
|
||||
builder.append(e.getMessage()).append("\n");
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
|
||||
public String getIdInterfaceName() {
|
||||
return idInterfaceName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package org.springframework.data.cassandra.repository.support;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.data.cassandra.repository.MapId;
|
||||
|
||||
public class IdInterfaceValidator {
|
||||
|
||||
/**
|
||||
* Validates the form of the given id interface candidate type. If the interface violates the following restrictions,
|
||||
* then an {@link IdInterfaceExceptions} is thrown containing all of the violations encountered, which can be obtained
|
||||
* from {@link IdInterfaceExceptions#getExceptions()} or, as a convenience,
|
||||
* {@link IdInterfaceExceptions#getMessages()}.
|
||||
* <p/>
|
||||
* Id interfaces are intended to have methods representing setters and getters. Getter methods take the form
|
||||
* <ul>
|
||||
* <li><code>PropertyType getPropertyName()</code> or</li>
|
||||
* <li><code>PropertyType propertyName()</code>.</li>
|
||||
* </ul>
|
||||
* Setter methods take the form
|
||||
* <ul>
|
||||
* <li><code>void|IdType setPropertyName(PropertyType)</code>,</li>
|
||||
* <li><code>void|IdType withPropertyName(PropertyType)</code>, or</li>
|
||||
* <li><code>void|IdType propertyName(PropertyType)</code>;</li>
|
||||
* </ul>
|
||||
* setter methods may also declare that they return their id interface type to support method chaining.
|
||||
* <p/>
|
||||
* Id interfaces
|
||||
* <ul>
|
||||
* <li>must be an <code>interface</code>, not a <code>class</code>,</li>
|
||||
* <li>may extend {@link Serializable},</li>
|
||||
* <li>may extend {@link MapId},</li>
|
||||
* <li>must have getter methods that only return a {@link Serializable} type,</li>
|
||||
* <li>must have setter methods that only take a single {@link Serializable} type,</li>
|
||||
* <li>must have setter methods that only return <code>void</code> or the id interface's type,</li>
|
||||
* <li>must not define any getter methods with the literal name "get", and</li>
|
||||
* <li>must not define any setter methods with the literal names "set" or "with".</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param id The candidate interface type
|
||||
* @throws IdInterfaceExceptions
|
||||
* @see IdInterfaceExceptions#getExceptions()
|
||||
* @see {@link IdInterfaceException}
|
||||
*/
|
||||
public static void validate(Class<?> id) {
|
||||
|
||||
IdInterfaceExceptions x = new IdInterfaceExceptions(id);
|
||||
|
||||
if (!id.isInterface()) {
|
||||
x.add(new IdInterfaceException(id, null, "id type must be an interface"));
|
||||
}
|
||||
|
||||
Class<?>[] interfaces = id.getInterfaces();
|
||||
if (interfaces.length > 2
|
||||
|| ((interfaces.length == 1 && !(interfaces[0].equals(Serializable.class) || interfaces[0].equals(MapId.class))))) {
|
||||
x.add(new IdInterfaceException(id, null, "id type may only extend Serializable and/or MapId"));
|
||||
}
|
||||
|
||||
for (Method m : id.getDeclaredMethods()) {
|
||||
Class<?>[] args = m.getParameterTypes();
|
||||
String name = m.getName();
|
||||
Class<?> ret = m.getReturnType();
|
||||
switch (args.length) {
|
||||
case 0: // then getter
|
||||
if (name.startsWith("get") && name.length() == 3) {
|
||||
x.add(new IdInterfaceException(id, m, "getter methods must have a property name following 'get' prefix"));
|
||||
}
|
||||
if (!Serializable.class.isAssignableFrom(ret)) {
|
||||
x.add(new IdInterfaceException(id, m, "getter methods must return Serializable types"));
|
||||
}
|
||||
break;
|
||||
case 1: // then setter
|
||||
if (name.startsWith("set") && name.length() == 3) {
|
||||
x.add(new IdInterfaceException(id, m, "setter methods must have a property name following 'set' prefix"));
|
||||
}
|
||||
if (name.startsWith("with") && name.length() == 4) {
|
||||
x.add(new IdInterfaceException(id, m, "setter methods must have a property name following 'with' prefix"));
|
||||
}
|
||||
if (!void.class.equals(ret) && !id.equals(ret)) {
|
||||
x.add(new IdInterfaceException(id, m,
|
||||
"setter methods not returning void may only return the same type as their id interface"));
|
||||
}
|
||||
Class<?> arg = args[0];
|
||||
if (!Serializable.class.isAssignableFrom(arg)) {
|
||||
x.add(new IdInterfaceException(id, m, "setter methods must take exactly one Serializable type"));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
x.add(new IdInterfaceException(id, m,
|
||||
"id interface methods may only take zero parameters for a getter or one parameter for a setter; found "
|
||||
+ args.length));
|
||||
}
|
||||
}
|
||||
|
||||
if (x.getCount() > 0) {
|
||||
throw x;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,63 @@
|
||||
package org.springframework.data.cassandra.repository.support;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Proxy;
|
||||
|
||||
import org.springframework.data.cassandra.repository.MapId;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Factory class for producing implementations of given id interfaces. For restrictions on id interfaces definitions,
|
||||
* see {@link IdInterfaceValidator#validate(Class)}.
|
||||
*
|
||||
* @see IdInterfaceValidator#validate(Class)
|
||||
* @author Matthew T. Adams
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public class MapIdFactory {
|
||||
|
||||
public static <T extends MapId> T id(Class<T> idInterface) {
|
||||
/**
|
||||
* Produces an implementation of the given id interface type using the type's class loader. For restrictions on id
|
||||
* interfaces definitions, see {@link IdInterfaceValidator#validate(Class)}. Returns an implementation of the given
|
||||
* interface that also implements {@link MapId} and {@link Serializable}, so it can be cast as such if necessary.
|
||||
*
|
||||
* @param idInterface The type of the id interface.
|
||||
* @return An implementation of the given interface that also implements {@link MapId} and {@link Serializable}.
|
||||
* @see IdInterfaceValidator#validate(Class)
|
||||
*/
|
||||
public static <T> T id(Class<T> idInterface) {
|
||||
Assert.notNull(idInterface);
|
||||
return id(idInterface, idInterface.getClassLoader());
|
||||
}
|
||||
|
||||
public static <T extends MapId> T id(Class<T> idInterface, ClassLoader loader) {
|
||||
return (T) Proxy.newProxyInstance(loader, new Class<?>[] { idInterface }, new MapIdProxyDelegate(idInterface));
|
||||
/**
|
||||
* Produces an implementation of the given class loader. For restrictions on id interfaces definitions, see
|
||||
* {@link IdInterfaceValidator#validate(Class)}. Returns an implementation of the given interface that also implements
|
||||
* {@link MapId} and {@link Serializable}, so it can be cast as such if necessary.
|
||||
*
|
||||
* @param idInterface The type of the id interface.
|
||||
* @return An implementation of the given interface that also implements {@link MapId} and {@link Serializable}.
|
||||
* @see IdInterfaceValidator#validate(Class)
|
||||
*/
|
||||
public static <T> T id(Class<T> idInterface, ClassLoader loader) {
|
||||
if (MapId.class.equals(idInterface)) {
|
||||
return (T) new BasicMapId();
|
||||
}
|
||||
|
||||
IdInterfaceValidator.validate(idInterface);
|
||||
|
||||
Class<?>[] interfaces = idInterface.getInterfaces();
|
||||
switch (interfaces.length) {
|
||||
case 0:
|
||||
interfaces = new Class<?>[] { idInterface, MapId.class, Serializable.class };
|
||||
break;
|
||||
case 1:
|
||||
Class<?> other = interfaces[0].equals(Serializable.class) ? MapId.class : Serializable.class;
|
||||
interfaces = new Class<?>[] { idInterface, interfaces[0], other };
|
||||
break;
|
||||
default:
|
||||
interfaces = new Class<?>[] { idInterface, interfaces[0], interfaces[1] };
|
||||
}
|
||||
return (T) Proxy.newProxyInstance(loader, interfaces, new MapIdProxyDelegate(idInterface));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,77 +10,15 @@ import java.util.Map;
|
||||
import org.springframework.data.cassandra.repository.MapId;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Delegate class for dynamic proxies of id interfaces; delegates to {@link BasicMapId}.
|
||||
*
|
||||
* @see MapIdFactory#id(Class)
|
||||
* @see MapIdFactory#id(Class, ClassLoader)
|
||||
* @author Matthew T. Adams
|
||||
*/
|
||||
class MapIdProxyDelegate implements InvocationHandler {
|
||||
|
||||
static class Signature {
|
||||
String name;
|
||||
Class<?>[] argTypes;
|
||||
Class<?> returnType;
|
||||
|
||||
Signature(Method method, boolean includeReturnType) {
|
||||
this(method.getName(), method.getParameterTypes(), includeReturnType ? method.getReturnType() : null);
|
||||
}
|
||||
|
||||
Signature(String name, Class<?>[] argTypes, Class<?> returnType) {
|
||||
this.name = name;
|
||||
this.argTypes = argTypes;
|
||||
this.returnType = returnType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s %s(%s)", returnType, name, Arrays.toString(argTypes));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object that) {
|
||||
if (that == null) {
|
||||
return false;
|
||||
}
|
||||
if (this == that) {
|
||||
return true;
|
||||
}
|
||||
if (!(that instanceof Signature)) {
|
||||
return false;
|
||||
}
|
||||
Signature that_ = (Signature) that;
|
||||
if (!this.name.equals(that_.name)) {
|
||||
return false;
|
||||
}
|
||||
if ((this.argTypes == null && that_.argTypes != null) || (this.argTypes != null && that_.argTypes == null)) {
|
||||
return false;
|
||||
}
|
||||
if (this.argTypes != null) {
|
||||
if (this.argTypes.length != that_.argTypes.length) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < this.argTypes.length; i++) {
|
||||
if (!this.argTypes[i].equals(that_.argTypes[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.returnType == null) {
|
||||
return that_.returnType == null;
|
||||
}
|
||||
return this.returnType.equals(that_.returnType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 37 ^ name.hashCode();
|
||||
if (argTypes != null) {
|
||||
for (Class<?> c : argTypes) {
|
||||
hash ^= c.hashCode();
|
||||
}
|
||||
}
|
||||
if (returnType != null) {
|
||||
hash ^= returnType.hashCode();
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
private static final Map<Signature, Signature> MAP_ID_SIGNATURES;
|
||||
|
||||
static {
|
||||
@@ -92,10 +30,10 @@ class MapIdProxyDelegate implements InvocationHandler {
|
||||
}
|
||||
}
|
||||
|
||||
MapId delegate = new BasicMapId();
|
||||
Class<?> idInterface;
|
||||
private MapId delegate = new BasicMapId();
|
||||
private Class<?> idInterface;
|
||||
|
||||
MapIdProxyDelegate(Class<?> idInterface) {
|
||||
public MapIdProxyDelegate(Class<?> idInterface) {
|
||||
this.idInterface = idInterface;
|
||||
}
|
||||
|
||||
@@ -119,11 +57,11 @@ class MapIdProxyDelegate implements InvocationHandler {
|
||||
return invokeGetter(method);
|
||||
}
|
||||
|
||||
private boolean isMapIdMethod(Method method) {
|
||||
public boolean isMapIdMethod(Method method) {
|
||||
return MAP_ID_SIGNATURES.containsKey(new Signature(method, true));
|
||||
}
|
||||
|
||||
private Serializable invokeGetter(Method method) {
|
||||
public Serializable invokeGetter(Method method) {
|
||||
String name = method.getName();
|
||||
if (name.startsWith("get")) {
|
||||
if (name.length() == 3) {
|
||||
@@ -136,7 +74,7 @@ class MapIdProxyDelegate implements InvocationHandler {
|
||||
return delegate.get(name);
|
||||
}
|
||||
|
||||
private void invokeSetter(Method method, Object value) {
|
||||
public void invokeSetter(Method method, Object value) {
|
||||
String name = method.getName();
|
||||
int minLength = 1;
|
||||
boolean isSet = name.startsWith("set");
|
||||
@@ -164,3 +102,72 @@ class MapIdProxyDelegate implements InvocationHandler {
|
||||
delegate.put(name, (Serializable) value);
|
||||
}
|
||||
}
|
||||
|
||||
class Signature {
|
||||
String name;
|
||||
Class<?>[] argTypes;
|
||||
Class<?> returnType;
|
||||
|
||||
Signature(Method method, boolean includeReturnType) {
|
||||
this(method.getName(), method.getParameterTypes(), includeReturnType ? method.getReturnType() : null);
|
||||
}
|
||||
|
||||
Signature(String name, Class<?>[] argTypes, Class<?> returnType) {
|
||||
this.name = name;
|
||||
this.argTypes = argTypes;
|
||||
this.returnType = returnType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("%s %s(%s)", returnType, name, Arrays.toString(argTypes));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object that) {
|
||||
if (that == null) {
|
||||
return false;
|
||||
}
|
||||
if (this == that) {
|
||||
return true;
|
||||
}
|
||||
if (!(that instanceof Signature)) {
|
||||
return false;
|
||||
}
|
||||
Signature that_ = (Signature) that;
|
||||
if (!this.name.equals(that_.name)) {
|
||||
return false;
|
||||
}
|
||||
if ((this.argTypes == null && that_.argTypes != null) || (this.argTypes != null && that_.argTypes == null)) {
|
||||
return false;
|
||||
}
|
||||
if (this.argTypes != null) {
|
||||
if (this.argTypes.length != that_.argTypes.length) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < this.argTypes.length; i++) {
|
||||
if (!this.argTypes[i].equals(that_.argTypes[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.returnType == null) {
|
||||
return that_.returnType == null;
|
||||
}
|
||||
return this.returnType.equals(that_.returnType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 37 ^ name.hashCode();
|
||||
if (argTypes != null) {
|
||||
for (Class<?> c : argTypes) {
|
||||
hash ^= c.hashCode();
|
||||
}
|
||||
}
|
||||
if (returnType != null) {
|
||||
hash ^= returnType.hashCode();
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ public class CassandraTemplateMapIdProxyDelegateIntegrationTest extends
|
||||
assertNull(t.selectOneById(SinglePkc.class, id));
|
||||
}
|
||||
|
||||
public interface SinglePkcId extends MapId {
|
||||
public interface SinglePkcId {
|
||||
SinglePkcId key(String key);
|
||||
|
||||
String key();
|
||||
@@ -149,7 +149,7 @@ public class CassandraTemplateMapIdProxyDelegateIntegrationTest extends
|
||||
assertNull(t.selectOneById(MultiPkc.class, id));
|
||||
}
|
||||
|
||||
public interface MultiPkcId extends MapId {
|
||||
public interface MultiPkcId {
|
||||
MultiPkcId key0(String key0);
|
||||
|
||||
String key0();
|
||||
|
||||
@@ -3,27 +3,32 @@ package org.springframework.data.cassandra.test.unit.mapidfactory;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.springframework.data.cassandra.repository.support.IdInterfaceValidator.validate;
|
||||
import static org.springframework.data.cassandra.repository.support.MapIdFactory.id;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Random;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.cassandra.repository.MapId;
|
||||
import org.springframework.data.cassandra.repository.support.IdInterfaceExceptions;
|
||||
|
||||
public class MapIdFactoryTest {
|
||||
|
||||
static interface MyId extends MapId {
|
||||
MyId string(String s);
|
||||
interface HappyExtendingMapIdAndSerializable extends MapId, Serializable {
|
||||
HappyExtendingMapIdAndSerializable string(String s);
|
||||
|
||||
void setString(String s);
|
||||
|
||||
MyId withString(String s);
|
||||
HappyExtendingMapIdAndSerializable withString(String s);
|
||||
|
||||
String string();
|
||||
|
||||
String getString();
|
||||
|
||||
MyId number(Integer i);
|
||||
HappyExtendingMapIdAndSerializable number(Integer i);
|
||||
|
||||
void setNumber(Integer i);
|
||||
|
||||
@@ -33,12 +38,12 @@ public class MapIdFactoryTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
public void testHappyExtendingMapId() {
|
||||
Random r = new Random();
|
||||
String s = "" + r.nextInt();
|
||||
Integer i = new Integer(r.nextInt());
|
||||
|
||||
MyId id = id(MyId.class);
|
||||
HappyExtendingMapIdAndSerializable id = id(HappyExtendingMapIdAndSerializable.class);
|
||||
|
||||
assertNull(id.string());
|
||||
assertNull(id.number());
|
||||
@@ -50,7 +55,7 @@ public class MapIdFactoryTest {
|
||||
assertEquals(i, id.number());
|
||||
assertEquals(i, id.get("number"));
|
||||
|
||||
MyId returned = null;
|
||||
HappyExtendingMapIdAndSerializable returned = null;
|
||||
|
||||
returned = id.number(i = r.nextInt());
|
||||
assertSame(returned, id);
|
||||
@@ -95,4 +100,168 @@ public class MapIdFactoryTest {
|
||||
assertNull(id.number());
|
||||
assertNull(id.get("number"));
|
||||
}
|
||||
|
||||
interface HappyExtendingNothing {
|
||||
HappyExtendingNothing string(String s);
|
||||
|
||||
void setString(String s);
|
||||
|
||||
HappyExtendingNothing withString(String s);
|
||||
|
||||
String string();
|
||||
|
||||
String getString();
|
||||
|
||||
HappyExtendingNothing number(Integer i);
|
||||
|
||||
void setNumber(Integer i);
|
||||
|
||||
Integer number();
|
||||
|
||||
Integer getNumber();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHappyExtendingNothing() {
|
||||
Random r = new Random();
|
||||
String s = "" + r.nextInt();
|
||||
Integer i = new Integer(r.nextInt());
|
||||
|
||||
HappyExtendingNothing id = id(HappyExtendingNothing.class);
|
||||
|
||||
assertTrue(id instanceof Serializable);
|
||||
assertTrue(id instanceof MapId);
|
||||
MapId mapid = (MapId) id;
|
||||
|
||||
assertNull(id.string());
|
||||
assertNull(id.number());
|
||||
assertNull(id.getString());
|
||||
assertNull(id.getNumber());
|
||||
|
||||
id.setNumber(i);
|
||||
assertEquals(i, id.getNumber());
|
||||
assertEquals(i, id.number());
|
||||
assertEquals(i, mapid.get("number"));
|
||||
|
||||
HappyExtendingNothing returned = null;
|
||||
|
||||
returned = id.number(i = r.nextInt());
|
||||
assertSame(returned, id);
|
||||
assertEquals(i, id.getNumber());
|
||||
assertEquals(i, id.number());
|
||||
assertEquals(i, mapid.get("number"));
|
||||
|
||||
mapid.put("number", i = r.nextInt());
|
||||
assertEquals(i, id.getNumber());
|
||||
assertEquals(i, id.number());
|
||||
assertEquals(i, mapid.get("number"));
|
||||
|
||||
id.setString(s);
|
||||
assertEquals(s, id.getString());
|
||||
assertEquals(s, id.string());
|
||||
assertEquals(s, mapid.get("string"));
|
||||
|
||||
returned = id.string(s = "" + r.nextInt());
|
||||
assertSame(returned, id);
|
||||
assertEquals(s, id.getString());
|
||||
assertEquals(s, id.string());
|
||||
assertEquals(s, mapid.get("string"));
|
||||
|
||||
returned = id.withString(s = "" + r.nextInt());
|
||||
assertSame(returned, id);
|
||||
assertEquals(s, id.getString());
|
||||
assertEquals(s, id.string());
|
||||
assertEquals(s, mapid.get("string"));
|
||||
|
||||
mapid.put("string", s = "" + r.nextInt());
|
||||
assertEquals(s, id.getString());
|
||||
assertEquals(s, id.string());
|
||||
assertEquals(s, mapid.get("string"));
|
||||
|
||||
id.setString(null);
|
||||
assertNull(id.getString());
|
||||
assertNull(id.string());
|
||||
assertNull(mapid.get("string"));
|
||||
|
||||
id.setNumber(null);
|
||||
assertNull(id.getNumber());
|
||||
assertNull(id.number());
|
||||
assertNull(mapid.get("number"));
|
||||
}
|
||||
|
||||
class IdClass {}
|
||||
|
||||
interface Foo {}
|
||||
|
||||
interface IdExtendingNotMapId extends Foo {}
|
||||
|
||||
interface LiteralGet {
|
||||
String get();
|
||||
}
|
||||
|
||||
interface GetterReturningVoid {
|
||||
void getString();
|
||||
}
|
||||
|
||||
interface GetReturningVoid {
|
||||
void string();
|
||||
}
|
||||
|
||||
interface GetReturningNonSerializable {
|
||||
Object getFoo();
|
||||
}
|
||||
|
||||
interface MethodWithMoreThanOneArgument {
|
||||
void foo(Object a, Object b);
|
||||
}
|
||||
|
||||
interface LiteralSet {
|
||||
void set(String s);
|
||||
}
|
||||
|
||||
interface LiteralWith {
|
||||
void with(String s);
|
||||
}
|
||||
|
||||
interface SetterMethodNotReturningVoidOrThis {
|
||||
String string(String s);
|
||||
}
|
||||
|
||||
interface SetMethodNotReturningVoidOrThis {
|
||||
String setString(String s);
|
||||
}
|
||||
|
||||
interface WithMethodNotReturningVoidOrThis {
|
||||
String withString(String s);
|
||||
}
|
||||
|
||||
interface SetterMethodTakingNonSerializable {
|
||||
void string(Object o);
|
||||
}
|
||||
|
||||
interface SetMethodTakingNonSerializable {
|
||||
void string(Object o);
|
||||
}
|
||||
|
||||
interface WithMethodTakingNonSerializable {
|
||||
void string(Object o);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnhappies() {
|
||||
Class<?>[] interfaces = new Class<?>[] { IdClass.class, IdExtendingNotMapId.class, LiteralGet.class,
|
||||
GetterReturningVoid.class, GetReturningVoid.class, GetReturningNonSerializable.class,
|
||||
MethodWithMoreThanOneArgument.class, LiteralSet.class, LiteralWith.class,
|
||||
SetterMethodNotReturningVoidOrThis.class, SetMethodNotReturningVoidOrThis.class,
|
||||
WithMethodNotReturningVoidOrThis.class, SetterMethodTakingNonSerializable.class,
|
||||
SetMethodTakingNonSerializable.class, WithMethodTakingNonSerializable.class };
|
||||
for (Class<?> i : interfaces) {
|
||||
try {
|
||||
validate(i);
|
||||
fail("should've caught IdInterfaceException validating interface " + i);
|
||||
} catch (IdInterfaceExceptions e) {
|
||||
assertEquals(1, e.getCount());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user