improvements
This commit is contained in:
parent
5619f8c2ae
commit
e1530d076c
7 changed files with 101 additions and 38 deletions
|
|
@ -0,0 +1,21 @@
|
||||||
|
package nl.sanderhautvast.contiguous;
|
||||||
|
|
||||||
|
import java.lang.invoke.MethodHandle;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
class BigDecimalHandler extends PrimitiveType<BigDecimal> {
|
||||||
|
public BigDecimalHandler(MethodHandle getter, MethodHandle setter) {
|
||||||
|
super(BigDecimal.class, getter, setter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void store(BigDecimal value, ContiguousList<?> list) {
|
||||||
|
list.storeString(value.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object transform(Object value) {
|
||||||
|
return new BigDecimal((String) value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package nl.sanderhautvast.contiguous;
|
||||||
|
|
||||||
|
import java.lang.invoke.MethodHandle;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
class BigIntegerHandler extends PrimitiveType<BigInteger> {
|
||||||
|
public BigIntegerHandler(MethodHandle getter, MethodHandle setter) {
|
||||||
|
super(BigInteger.class, getter, setter);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void store(BigInteger value, ContiguousList<?> list) {
|
||||||
|
list.storeString(value.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object transform(Object value) {
|
||||||
|
return new BigInteger((String) value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -22,9 +22,9 @@ import java.util.function.UnaryOperator;
|
||||||
* <p>
|
* <p>
|
||||||
* Employs the SQLite style of data storage, most notably integer numbers are stored with variable byte length
|
* Employs the SQLite style of data storage, most notably integer numbers are stored with variable byte length
|
||||||
* <p>
|
* <p>
|
||||||
* The classes stored in DehydrateList MUST have a no-args constructor.
|
* The classes stored in {@link ContiguousList} MUST have a no-args constructor.
|
||||||
* <p>
|
* <p>
|
||||||
* Like ArrayList mutating operations are not synchronized.
|
* Like ArrayList, mutating operations are not synchronized.
|
||||||
* <p>
|
* <p>
|
||||||
* Does not allow null elements.
|
* Does not allow null elements.
|
||||||
* <p>
|
* <p>
|
||||||
|
|
@ -169,7 +169,7 @@ public class ContiguousList<E> implements List<E> {
|
||||||
data.position(elementIndices[index]);
|
data.position(elementIndices[index]);
|
||||||
try {
|
try {
|
||||||
if (type instanceof PrimitiveType<?>) {
|
if (type instanceof PrimitiveType<?>) {
|
||||||
return (E) ValueReader.read(data);
|
return (E)((PrimitiveType<?>)type).transform(ValueReader.read(data));
|
||||||
}
|
}
|
||||||
// create a new instance of the list element type
|
// create a new instance of the list element type
|
||||||
E newInstance = (E) type.type.getDeclaredConstructor().newInstance();
|
E newInstance = (E) type.type.getDeclaredConstructor().newInstance();
|
||||||
|
|
@ -187,7 +187,8 @@ public class ContiguousList<E> implements List<E> {
|
||||||
private void setProperties(Object element, CompoundType compoundType) {
|
private void setProperties(Object element, CompoundType compoundType) {
|
||||||
compoundType.getProperties().forEach(property -> {
|
compoundType.getProperties().forEach(property -> {
|
||||||
if (property instanceof PrimitiveType) {
|
if (property instanceof PrimitiveType) {
|
||||||
((PrimitiveType<?>) property).setValue(element, ValueReader.read(data));
|
PrimitiveType<?> type =((PrimitiveType<?>) property);
|
||||||
|
type.setValue(element, ValueReader.read(data));
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
CompoundType p = (CompoundType) property;
|
CompoundType p = (CompoundType) property;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package nl.sanderhautvast.contiguous;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
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.
|
* Base class for handlers. Its responsibility is to read and write a property from the incoming object to the internal storage.
|
||||||
*
|
*
|
||||||
* Can be extended for types that you need to handle.
|
* Can be extended for types that you need to handle.
|
||||||
|
|
@ -12,22 +12,6 @@ import java.lang.invoke.MethodHandle;
|
||||||
* ie. when a bean is added or retrieved from the list
|
* ie. when a bean is added or retrieved from the list
|
||||||
*/
|
*/
|
||||||
public abstract class PrimitiveType<T> extends Type {
|
public abstract class PrimitiveType<T> extends Type {
|
||||||
|
|
||||||
/*
|
|
||||||
* Apology:
|
|
||||||
* This was the simplest thing I could think of when trying to accomodate for nested types.
|
|
||||||
*
|
|
||||||
* What you end up with after inspection in the DehydrateList is a flat list of getters and setters
|
|
||||||
* of properties that are in a tree-like structure (primitive properties within (nested) compound types)
|
|
||||||
* So to read or write a property in a 'root object' (element type in list) with compound property types
|
|
||||||
* you first have to traverse to the bean graph to the right container (bean) of the property you set/get
|
|
||||||
* (that is what the childGetters are for)
|
|
||||||
*
|
|
||||||
* Ideally you'd do this only once per containing class. In the current implementation it's once per
|
|
||||||
* property in the containing class.
|
|
||||||
*/
|
|
||||||
// private final List<MethodHandle> childGetters = new ArrayList<>();
|
|
||||||
|
|
||||||
public PrimitiveType(Class<?> type, MethodHandle getter, MethodHandle setter) {
|
public PrimitiveType(Class<?> type, MethodHandle getter, MethodHandle setter) {
|
||||||
super(type, getter, setter);
|
super(type, getter, setter);
|
||||||
}
|
}
|
||||||
|
|
@ -70,10 +54,23 @@ public abstract class PrimitiveType<T> extends Type {
|
||||||
*/
|
*/
|
||||||
public void setValue(Object instance, Object value) {
|
public void setValue(Object instance, Object value) {
|
||||||
try {
|
try {
|
||||||
setter.invokeWithArguments(instance, value);
|
setter.invokeWithArguments(instance, transform(value));
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
throw new IllegalStateException(e);
|
throw new IllegalStateException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* 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){
|
||||||
|
return value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ package nl.sanderhautvast.contiguous;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.math.BigInteger;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
@ -15,23 +17,24 @@ final class PropertyHandlerFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
STANDARD_HANDLERS.put(String.class, StringHandler.class);
|
register(String.class, StringHandler.class);
|
||||||
STANDARD_HANDLERS.put(byte.class, ByteHandler.class);
|
register(byte.class, ByteHandler.class);
|
||||||
STANDARD_HANDLERS.put(Byte.class, ByteHandler.class);
|
register(Byte.class, ByteHandler.class);
|
||||||
STANDARD_HANDLERS.put(int.class, IntegerHandler.class);
|
register(int.class, IntegerHandler.class);
|
||||||
STANDARD_HANDLERS.put(Integer.class, IntegerHandler.class);
|
register(Integer.class, IntegerHandler.class);
|
||||||
STANDARD_HANDLERS.put(short.class, ShortHandler.class);
|
register(short.class, ShortHandler.class);
|
||||||
STANDARD_HANDLERS.put(Short.class, ShortHandler.class);
|
register(Short.class, ShortHandler.class);
|
||||||
STANDARD_HANDLERS.put(long.class, LongHandler.class);
|
register(long.class, LongHandler.class);
|
||||||
STANDARD_HANDLERS.put(Long.class, LongHandler.class);
|
register(Long.class, LongHandler.class);
|
||||||
STANDARD_HANDLERS.put(float.class, FloatHandler.class);
|
register(float.class, FloatHandler.class);
|
||||||
STANDARD_HANDLERS.put(Float.class, FloatHandler.class);
|
register(Float.class, FloatHandler.class);
|
||||||
STANDARD_HANDLERS.put(double.class, DoubleHandler.class);
|
register(double.class, DoubleHandler.class);
|
||||||
STANDARD_HANDLERS.put(Double.class, DoubleHandler.class);
|
register(Double.class, DoubleHandler.class);
|
||||||
|
register(BigDecimal.class, StringHandler.class);
|
||||||
|
register(BigInteger.class, BigIntegerHandler.class);
|
||||||
|
register(BigDecimal.class, BigDecimalHandler.class);
|
||||||
//Date/Timestamp
|
//Date/Timestamp
|
||||||
//LocalDate/time
|
//LocalDate/time
|
||||||
//BigDecimal
|
|
||||||
//BigInteger
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isKnownType(Class<?> type) {
|
public static boolean isKnownType(Class<?> type) {
|
||||||
|
|
@ -55,4 +58,11 @@ final class PropertyHandlerFactory {
|
||||||
public static <T> PrimitiveType<T> forType(Class<T> type) {
|
public static <T> PrimitiveType<T> forType(Class<T> type) {
|
||||||
return forType(type, null, null);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,11 @@ package nl.sanderhautvast.contiguous;
|
||||||
|
|
||||||
import java.lang.invoke.MethodHandle;
|
import java.lang.invoke.MethodHandle;
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* ok, sorry
|
* ok, sorry
|
||||||
|
*
|
||||||
|
* 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 Type {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ package nl.sanderhautvast.contiguous;
|
||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
@ -129,5 +130,15 @@ public class ContiguousListTest {
|
||||||
beanList.add(new StringBean(null));
|
beanList.add(new StringBean(null));
|
||||||
}
|
}
|
||||||
assertEquals(100, beanList.size());
|
assertEquals(100, beanList.size());
|
||||||
|
for (int i = 0; i < 100; i++) {
|
||||||
|
assertNull(beanList.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBigInteger() {
|
||||||
|
ContiguousList<BigInteger> bigIntegers = new ContiguousList<>(BigInteger.class);
|
||||||
|
bigIntegers.add(new BigInteger("1000000000"));
|
||||||
|
assertEquals(1_000_000_000L, bigIntegers.get(0).longValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue