Provide the Transformer with the field's Type rather than it's Class. The Type

contains generic type information which would allow a transformer to do the
right thing with a field of, say, type Set<Integer>.

If we had unit tests for StringIterable, I'd know that I didn't just break it.
I'd also know that it worked in the first place. :)
This commit is contained in:
Michael Bayne
2010-07-05 21:43:10 +00:00
parent a5fee01354
commit 0e82904696
4 changed files with 19 additions and 11 deletions
@@ -20,6 +20,8 @@
package com.samskivert.depot; package com.samskivert.depot;
import java.lang.reflect.Type;
/** /**
* Transforms a persistent record field into a format that can be read and written by the * Transforms a persistent record field into a format that can be read and written by the
* underlying database. For example, one might transform an enum into a byte, short or integer. Or * underlying database. For example, one might transform an enum into a byte, short or integer. Or
@@ -48,5 +50,5 @@ public interface Transformer<F,T>
* *
* @return the transformed value, which will be stored in a field of the persistent record. * @return the transformed value, which will be stored in a field of the persistent record.
*/ */
F fromPersistent (Class<?> fieldType, T value); F fromPersistent (Type fieldType, T value);
} }
@@ -20,6 +20,9 @@
package com.samskivert.depot; package com.samskivert.depot;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collection; import java.util.Collection;
@@ -65,7 +68,7 @@ public class Transformers
} }
return buf.toString(); return buf.toString();
} }
public String[] fromPersistent (Class<?> ftype, String value) { public String[] fromPersistent (Type ftype, String value) {
String[] values = value.replace("\\\t", "%%ESCTAB%%").split("\t"); String[] values = value.replace("\\\t", "%%ESCTAB%%").split("\t");
for (int ii = 0; ii < values.length; ii++) { for (int ii = 0; ii < values.length; ii++) {
values[ii] = values[ii].replace("%%ESCTAB%%", "\t"); values[ii] = values[ii].replace("%%ESCTAB%%", "\t");
@@ -85,7 +88,7 @@ public class Transformers
return StringIterable.toPersistent0(Arrays.asList(value)); return StringIterable.toPersistent0(Arrays.asList(value));
} }
public String[] fromPersistent (Class<?> ftype, String encoded) public String[] fromPersistent (Type ftype, String encoded)
{ {
if (encoded == null) { if (encoded == null) {
return null; return null;
@@ -102,18 +105,20 @@ public class Transformers
return toPersistent0(value); return toPersistent0(value);
} }
public Iterable<String> fromPersistent (Class<?> ftype, String encoded) public Iterable<String> fromPersistent (Type ftype, String encoded)
{ {
ArrayList<String> value = fromPersistent0(encoded); ArrayList<String> value = fromPersistent0(encoded);
Type fclass = (ftype instanceof ParameterizedType) ?
((ParameterizedType)ftype).getRawType() : ftype;
if (value == null || if (value == null ||
ftype == ArrayList.class || ftype == List.class || ftype == Collection.class || fclass == ArrayList.class || fclass == List.class ||
ftype == Iterable.class) { fclass == Collection.class || fclass == Iterable.class) {
return value; return value;
} }
if (ftype == LinkedList.class) { if (fclass == LinkedList.class) {
return Lists.newLinkedList(value); return Lists.newLinkedList(value);
} }
if (ftype == HashSet.class || ftype == Set.class) { if (fclass == HashSet.class || fclass == Set.class) {
return Sets.newHashSet(value); return Sets.newHashSet(value);
} }
// else: reflection? See if it's a collection, call the 0-arg constructor, add all // else: reflection? See if it's a collection, call the 0-arg constructor, add all
@@ -705,7 +705,7 @@ public abstract class FieldMarshaller<T>
} }
@Override public void writeToObject (Object po, T value) @Override public void writeToObject (Object po, T value)
throws IllegalArgumentException, IllegalAccessException { throws IllegalArgumentException, IllegalAccessException {
_field.set(po, _xformer.fromPersistent(_field.getType(), value)); _field.set(po, _xformer.fromPersistent(_field.getGenericType(), value));
} }
@Override public void writeToStatement (PreparedStatement ps, int column, T value) @Override public void writeToStatement (PreparedStatement ps, int column, T value)
throws SQLException { throws SQLException {
@@ -21,6 +21,7 @@
package com.samskivert.depot.tests; package com.samskivert.depot.tests;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.util.Set; import java.util.Set;
import org.junit.Test; import org.junit.Test;
@@ -92,7 +93,7 @@ public class TransformTest extends TestBase
return value.value; return value.value;
} }
public CustomType fromPersistent (Class<?> ftype, String value) { public CustomType fromPersistent (Type ftype, String value) {
return new CustomType(value); return new CustomType(value);
} }
} }
@@ -102,7 +103,7 @@ public class TransformTest extends TestBase
public Short toPersistent (ShortEnum value) { public Short toPersistent (ShortEnum value) {
return value.toShort(); return value.toShort();
} }
public ShortEnum fromPersistent (Class<?> ftype, Short value) { public ShortEnum fromPersistent (Type ftype, Short value) {
@SuppressWarnings("unchecked") Class<Dummy> eclass = (Class<Dummy>)ftype; @SuppressWarnings("unchecked") Class<Dummy> eclass = (Class<Dummy>)ftype;
return fromShort(eclass, value); return fromShort(eclass, value);
} }