improvements, more renaming and a textfix
This commit is contained in:
parent
e1530d076c
commit
bce8a4bcf5
16 changed files with 97 additions and 99 deletions
|
|
@ -2,9 +2,8 @@ package nl.sanderhautvast.contiguous;
|
|||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
|
||||
class BigDecimalHandler extends PrimitiveType<BigDecimal> {
|
||||
class BigDecimalHandler extends PrimitiveTypeHandler<BigDecimal> {
|
||||
public BigDecimalHandler(MethodHandle getter, MethodHandle setter) {
|
||||
super(BigDecimal.class, getter, setter);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ package nl.sanderhautvast.contiguous;
|
|||
import java.lang.invoke.MethodHandle;
|
||||
import java.math.BigInteger;
|
||||
|
||||
class BigIntegerHandler extends PrimitiveType<BigInteger> {
|
||||
class BigIntegerHandler extends PrimitiveTypeHandler<BigInteger> {
|
||||
public BigIntegerHandler(MethodHandle getter, MethodHandle setter) {
|
||||
super(BigInteger.class, getter, setter);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import java.lang.invoke.MethodHandle;
|
|||
/**
|
||||
* Stores a byte value.
|
||||
*/
|
||||
class ByteHandler extends PrimitiveType<Byte> {
|
||||
class ByteHandler extends PrimitiveTypeHandler<Byte> {
|
||||
|
||||
public ByteHandler(MethodHandle getter, MethodHandle setter) {
|
||||
super(Byte.class, getter, setter);
|
||||
|
|
|
|||
|
|
@ -1,51 +0,0 @@
|
|||
package nl.sanderhautvast.contiguous;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
|
||||
class CompoundType extends Type {
|
||||
private final Map<String, Type> properties = new LinkedHashMap<>();
|
||||
|
||||
private MethodHandle getter;
|
||||
private MethodHandle setter;
|
||||
|
||||
|
||||
CompoundType(Class<?> type) {
|
||||
super(type, null,null);
|
||||
}
|
||||
|
||||
void setGetter(MethodHandle getter) {
|
||||
this.getter = getter;
|
||||
}
|
||||
|
||||
public MethodHandle getGetter() {
|
||||
return getter;
|
||||
}
|
||||
|
||||
public MethodHandle getSetter() {
|
||||
return setter;
|
||||
}
|
||||
|
||||
void setSetter(MethodHandle setter) {
|
||||
this.setter = setter;
|
||||
}
|
||||
|
||||
public Class<?> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
Collection<Type> getProperties() {
|
||||
return properties.values();
|
||||
}
|
||||
|
||||
void addHandler(String propertyName, PrimitiveType<?> primitiveType) {
|
||||
properties.put(propertyName, primitiveType);
|
||||
}
|
||||
|
||||
void addChild(Field property, CompoundType childCompoundType) {
|
||||
this.properties.put(property.getName(), childCompoundType);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
package nl.sanderhautvast.contiguous;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
|
||||
class CompoundTypeHandler extends TypeHandler {
|
||||
private final Map<String, TypeHandler> properties = new LinkedHashMap<>();
|
||||
|
||||
|
||||
|
||||
CompoundTypeHandler(Class<?> type) {
|
||||
super(type, null,null);
|
||||
}
|
||||
|
||||
|
||||
Collection<TypeHandler> getProperties() {
|
||||
return properties.values();
|
||||
}
|
||||
|
||||
void addHandler(String propertyName, PrimitiveTypeHandler<?> primitiveType) {
|
||||
properties.put(propertyName, primitiveType);
|
||||
}
|
||||
|
||||
void addChild(Field property, CompoundTypeHandler childCompoundType) {
|
||||
this.properties.put(property.getName(), childCompoundType);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -52,7 +52,7 @@ public class ContiguousList<E> implements List<E> {
|
|||
|
||||
private int size;
|
||||
|
||||
private Type type;
|
||||
private TypeHandler type;
|
||||
|
||||
public ContiguousList(Class<E> type) {
|
||||
inspectType(type);
|
||||
|
|
@ -71,7 +71,7 @@ public class ContiguousList<E> implements List<E> {
|
|||
if (PropertyHandlerFactory.isKnownType(type)) {
|
||||
this.type = PropertyHandlerFactory.forType(type);
|
||||
} else {
|
||||
CompoundType compoundType = new CompoundType(type);
|
||||
CompoundTypeHandler compoundType = new CompoundTypeHandler(type);
|
||||
this.type = compoundType;
|
||||
try {
|
||||
addPropertyHandlersForCompoundType(type, compoundType);
|
||||
|
|
@ -81,7 +81,7 @@ public class ContiguousList<E> implements List<E> {
|
|||
}
|
||||
}
|
||||
|
||||
private void addPropertyHandlersForCompoundType(Class<?> type, CompoundType parentCompoundType) throws IllegalAccessException {
|
||||
private void addPropertyHandlersForCompoundType(Class<?> type, CompoundTypeHandler parentCompoundType) throws IllegalAccessException {
|
||||
final MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(type, MethodHandles.lookup());
|
||||
Arrays.stream(type.getDeclaredFields())
|
||||
.forEach(field -> {
|
||||
|
|
@ -91,11 +91,11 @@ public class ContiguousList<E> implements List<E> {
|
|||
MethodHandle setter = lookup.findSetter(type, field.getName(), fieldType);
|
||||
|
||||
if (PropertyHandlerFactory.isKnownType(fieldType)) {
|
||||
PrimitiveType<?> primitiveType = PropertyHandlerFactory.forType(fieldType, getter, setter);
|
||||
PrimitiveTypeHandler<?> primitiveType = PropertyHandlerFactory.forType(fieldType, getter, setter);
|
||||
|
||||
parentCompoundType.addHandler(field.getName(), primitiveType);
|
||||
} else {
|
||||
CompoundType newParent = new CompoundType(fieldType);
|
||||
CompoundTypeHandler newParent = new CompoundTypeHandler(fieldType);
|
||||
newParent.setGetter(getter);
|
||||
newParent.setSetter(setter);
|
||||
parentCompoundType.addChild(field, newParent);
|
||||
|
|
@ -126,18 +126,18 @@ public class ContiguousList<E> implements List<E> {
|
|||
return true;
|
||||
}
|
||||
|
||||
private void getProperties(Object element, Type type) {
|
||||
private void getProperties(Object element, TypeHandler type) {
|
||||
// passed type is primitive
|
||||
if (type instanceof PrimitiveType<?>) {
|
||||
((PrimitiveType<?>) type).storePropertyValue(element, this);
|
||||
if (type instanceof PrimitiveTypeHandler<?>) {
|
||||
((PrimitiveTypeHandler<?>) type).storePropertyValue(element, this);
|
||||
} else {
|
||||
// passed type is compund ie. has child properties
|
||||
((CompoundType)type).getProperties().forEach(property -> {
|
||||
if (property instanceof PrimitiveType<?>) {
|
||||
((CompoundTypeHandler)type).getProperties().forEach(property -> {
|
||||
if (property instanceof PrimitiveTypeHandler<?>) {
|
||||
// recurse once more -> property is stored
|
||||
getProperties(element, property);
|
||||
} else {
|
||||
CompoundType child = ((CompoundType) property);
|
||||
CompoundTypeHandler child = ((CompoundTypeHandler) property);
|
||||
try {
|
||||
Object result = child.getGetter().invoke(element);
|
||||
getProperties(result, child);
|
||||
|
|
@ -168,14 +168,14 @@ public class ContiguousList<E> implements List<E> {
|
|||
}
|
||||
data.position(elementIndices[index]);
|
||||
try {
|
||||
if (type instanceof PrimitiveType<?>) {
|
||||
return (E)((PrimitiveType<?>)type).transform(ValueReader.read(data));
|
||||
if (type instanceof PrimitiveTypeHandler<?>) {
|
||||
return (E)((PrimitiveTypeHandler<?>)type).transform(ValueReader.read(data));
|
||||
}
|
||||
// create a new instance of the list element type
|
||||
E newInstance = (E) type.type.getDeclaredConstructor().newInstance();
|
||||
E newInstance = (E) type.getType().getDeclaredConstructor().newInstance();
|
||||
|
||||
// set the data
|
||||
setProperties(newInstance, (CompoundType) type);
|
||||
setProperties(newInstance, (CompoundTypeHandler) type);
|
||||
|
||||
return newInstance;
|
||||
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
|
||||
|
|
@ -184,14 +184,14 @@ public class ContiguousList<E> implements List<E> {
|
|||
}
|
||||
}
|
||||
|
||||
private void setProperties(Object element, CompoundType compoundType) {
|
||||
private void setProperties(Object element, CompoundTypeHandler compoundType) {
|
||||
compoundType.getProperties().forEach(property -> {
|
||||
if (property instanceof PrimitiveType) {
|
||||
PrimitiveType<?> type =((PrimitiveType<?>) property);
|
||||
if (property instanceof PrimitiveTypeHandler) {
|
||||
PrimitiveTypeHandler<?> type =((PrimitiveTypeHandler<?>) property);
|
||||
type.setValue(element, ValueReader.read(data));
|
||||
} else {
|
||||
try {
|
||||
CompoundType p = (CompoundType) property;
|
||||
CompoundTypeHandler p = (CompoundTypeHandler) property;
|
||||
// create a new instance of the property
|
||||
Object newInstance = p.getType().getDeclaredConstructor().newInstance();
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import java.lang.invoke.MethodHandle;
|
|||
/**
|
||||
* Stores a double value.
|
||||
*/
|
||||
class DoubleHandler extends PrimitiveType<Double> {
|
||||
class DoubleHandler extends PrimitiveTypeHandler<Double> {
|
||||
public DoubleHandler(MethodHandle getter, MethodHandle setter) {
|
||||
super(Double.class, getter, setter);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package nl.sanderhautvast.contiguous;
|
|||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
|
||||
class FloatHandler extends PrimitiveType<Float> {
|
||||
class FloatHandler extends PrimitiveTypeHandler<Float> {
|
||||
public FloatHandler(MethodHandle getter, MethodHandle setter) {
|
||||
super(Float.class, getter, setter);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package nl.sanderhautvast.contiguous;
|
|||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
|
||||
class IntegerHandler extends PrimitiveType<Integer> {
|
||||
class IntegerHandler extends PrimitiveTypeHandler<Integer> {
|
||||
public IntegerHandler(MethodHandle getter, MethodHandle setter) {
|
||||
super(Integer.class, getter, setter);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package nl.sanderhautvast.contiguous;
|
|||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
|
||||
class LongHandler extends PrimitiveType<Long> {
|
||||
class LongHandler extends PrimitiveTypeHandler<Long> {
|
||||
public LongHandler(MethodHandle getter, MethodHandle setter) {
|
||||
super(Long.class, getter, setter);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,15 +4,15 @@ import java.lang.invoke.MethodHandle;
|
|||
|
||||
/**
|
||||
* Base class for handlers. Its responsibility is to read and write a property from the incoming object to the internal storage.
|
||||
*
|
||||
* <p>
|
||||
* Can be extended for types that you need to handle.
|
||||
*
|
||||
* <p>
|
||||
* A property handler is instantiated once per bean property and contains handles to the getter and setter methods
|
||||
* of the bean that it needs to call 'runtime' (after instantiation of the list),
|
||||
* ie. when a bean is added or retrieved from the list
|
||||
*/
|
||||
public abstract class PrimitiveType<T> extends Type {
|
||||
public PrimitiveType(Class<?> type, MethodHandle getter, MethodHandle setter) {
|
||||
public abstract class PrimitiveTypeHandler<T> extends TypeHandler {
|
||||
public PrimitiveTypeHandler(Class<?> type, MethodHandle getter, MethodHandle setter) {
|
||||
super(type, getter, setter);
|
||||
}
|
||||
|
||||
|
|
@ -63,14 +63,14 @@ public abstract class PrimitiveType<T> extends Type {
|
|||
/**
|
||||
* Certain types can easily be stored as another known type, for instance
|
||||
* a BigDecimal can be stored as a String.
|
||||
*
|
||||
* The {@link PrimitiveType} for BigDecimal would in that case be responsible for turning the String
|
||||
* <p>
|
||||
* The {@link PrimitiveTypeHandler} for BigDecimal would in that case be responsible for turning the String
|
||||
* into a BigDecimal. It can do that by overriding this method
|
||||
*
|
||||
* @param value raw value to transform to the desired output type
|
||||
* @return the transformed object
|
||||
*/
|
||||
public Object transform(Object value){
|
||||
public Object transform(Object value) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
|
@ -11,7 +11,7 @@ import java.util.Map;
|
|||
* Maps the propertyvalue type to a PropertyHandler
|
||||
*/
|
||||
final class PropertyHandlerFactory {
|
||||
private static final Map<Class<?>, Class<? extends PrimitiveType<?>>> STANDARD_HANDLERS = new HashMap<>();
|
||||
private static final Map<Class<?>, Class<? extends PrimitiveTypeHandler<?>>> TYPE_HANDLERS = new HashMap<>();
|
||||
|
||||
private PropertyHandlerFactory() {
|
||||
}
|
||||
|
|
@ -38,16 +38,16 @@ final class PropertyHandlerFactory {
|
|||
}
|
||||
|
||||
public static boolean isKnownType(Class<?> type) {
|
||||
return STANDARD_HANDLERS.containsKey(type);
|
||||
return TYPE_HANDLERS.containsKey(type);
|
||||
}
|
||||
|
||||
public static <T> PrimitiveType<T> forType(Class<T> type, MethodHandle getter, MethodHandle setter) {
|
||||
public static <T> PrimitiveTypeHandler<T> forType(Class<T> type, MethodHandle getter, MethodHandle setter) {
|
||||
try {
|
||||
Class<? extends PrimitiveType<?>> appenderClass = STANDARD_HANDLERS.get(type);
|
||||
Class<? extends PrimitiveTypeHandler<?>> appenderClass = TYPE_HANDLERS.get(type);
|
||||
if (appenderClass == null) {
|
||||
throw new IllegalStateException("No Handler for " + type.getName());
|
||||
}
|
||||
return (PrimitiveType<T>) appenderClass.getDeclaredConstructor(MethodHandle.class, MethodHandle.class)
|
||||
return (PrimitiveTypeHandler<T>) appenderClass.getDeclaredConstructor(MethodHandle.class, MethodHandle.class)
|
||||
.newInstance(getter, setter);
|
||||
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
|
||||
InvocationTargetException e) {
|
||||
|
|
@ -55,14 +55,14 @@ final class PropertyHandlerFactory {
|
|||
}
|
||||
}
|
||||
|
||||
public static <T> PrimitiveType<T> forType(Class<T> type) {
|
||||
public static <T> PrimitiveTypeHandler<T> forType(Class<T> type) {
|
||||
return forType(type, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* register a new TypeHandler that cannot be derived from bean properties
|
||||
*/
|
||||
public static void register(Class<?> type, Class<? extends PrimitiveType<?>> typehandler) {
|
||||
STANDARD_HANDLERS.put(type, typehandler);
|
||||
public static void register(Class<?> type, Class<? extends PrimitiveTypeHandler<?>> typehandler) {
|
||||
TYPE_HANDLERS.put(type, typehandler);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package nl.sanderhautvast.contiguous;
|
|||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
|
||||
class ShortHandler extends PrimitiveType<Short> {
|
||||
class ShortHandler extends PrimitiveTypeHandler<Short> {
|
||||
public ShortHandler(MethodHandle getter, MethodHandle setter) {
|
||||
super(Short.class, getter, setter);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package nl.sanderhautvast.contiguous;
|
|||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
|
||||
class StringHandler extends PrimitiveType<String> {
|
||||
class StringHandler extends PrimitiveTypeHandler<String> {
|
||||
public StringHandler(MethodHandle getter, MethodHandle setter) {
|
||||
super(String.class, getter, setter);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,15 +8,36 @@ import java.lang.invoke.MethodHandle;
|
|||
* I needed to abstract over handlers for 'primitives' (ie. long, but also Long, String..=> built-in types) and compound types (your own)
|
||||
* So this is the common ancestor. The respective functions are completely different.
|
||||
*/
|
||||
public abstract class Type {
|
||||
public abstract class TypeHandler {
|
||||
|
||||
protected MethodHandle getter; // both can be null, if it's for a known ('primitive') type
|
||||
protected MethodHandle setter;
|
||||
protected Class<?> type;
|
||||
private final Class<?> type;
|
||||
|
||||
public Type(Class<?> type, MethodHandle getter, MethodHandle setter) {
|
||||
public TypeHandler(Class<?> type, MethodHandle getter, MethodHandle setter) {
|
||||
this.type = type;
|
||||
this.getter = getter;
|
||||
this.setter = setter;
|
||||
}
|
||||
|
||||
void setGetter(MethodHandle getter) {
|
||||
this.getter = getter;
|
||||
}
|
||||
|
||||
public MethodHandle getGetter() {
|
||||
return getter;
|
||||
}
|
||||
|
||||
public MethodHandle getSetter() {
|
||||
return setter;
|
||||
}
|
||||
|
||||
void setSetter(MethodHandle setter) {
|
||||
this.setter = setter;
|
||||
}
|
||||
|
||||
public Class<?> getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -131,7 +131,7 @@ public class ContiguousListTest {
|
|||
}
|
||||
assertEquals(100, beanList.size());
|
||||
for (int i = 0; i < 100; i++) {
|
||||
assertNull(beanList.get(i));
|
||||
assertNull(beanList.get(i).getName());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue