added iterators
This commit is contained in:
parent
90ccb1015f
commit
610ce0ce41
16 changed files with 329 additions and 147 deletions
|
|
@ -3,7 +3,7 @@ package nl.sanderhautvast.contiguous;
|
|||
import java.lang.invoke.MethodHandle;
|
||||
import java.math.BigDecimal;
|
||||
|
||||
class BigDecimalHandler extends PrimitiveTypeHandler<BigDecimal> {
|
||||
class BigDecimalHandler extends BuiltinTypeHandler<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 PrimitiveTypeHandler<BigInteger> {
|
||||
class BigIntegerHandler extends BuiltinTypeHandler<BigInteger> {
|
||||
public BigIntegerHandler(MethodHandle getter, MethodHandle setter) {
|
||||
super(BigInteger.class, getter, setter);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ import java.lang.invoke.MethodHandle;
|
|||
* 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 PrimitiveTypeHandler<T> extends TypeHandler {
|
||||
public PrimitiveTypeHandler(Class<?> type, MethodHandle getter, MethodHandle setter) {
|
||||
public abstract class BuiltinTypeHandler<T> extends TypeHandler {
|
||||
public BuiltinTypeHandler(Class<?> type, MethodHandle getter, MethodHandle setter) {
|
||||
super(type, getter, setter);
|
||||
}
|
||||
|
||||
|
|
@ -64,7 +64,7 @@ public abstract class PrimitiveTypeHandler<T> extends TypeHandler {
|
|||
* Certain types can easily be stored as another known type, for instance
|
||||
* a BigDecimal can be stored as a String.
|
||||
* <p>
|
||||
* The {@link PrimitiveTypeHandler} for BigDecimal would in that case be responsible for turning the String
|
||||
* The {@link BuiltinTypeHandler} 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
|
||||
|
|
@ -5,7 +5,7 @@ import java.lang.invoke.MethodHandle;
|
|||
/**
|
||||
* Stores a byte value.
|
||||
*/
|
||||
class ByteHandler extends PrimitiveTypeHandler<Byte> {
|
||||
class ByteHandler extends BuiltinTypeHandler<Byte> {
|
||||
|
||||
public ByteHandler(MethodHandle getter, MethodHandle setter) {
|
||||
super(Byte.class, getter, setter);
|
||||
|
|
@ -20,4 +20,12 @@ class ByteHandler extends PrimitiveTypeHandler<Byte> {
|
|||
public void setValue(Object instance, Object value) {
|
||||
super.setValue(instance, ((Long) value).byteValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object transform(Object value) {
|
||||
if (value instanceof Long) {
|
||||
return ((Long) value).byteValue();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class CompoundTypeHandler extends TypeHandler {
|
|||
return properties.values();
|
||||
}
|
||||
|
||||
void addHandler(String propertyName, PrimitiveTypeHandler<?> primitiveType) {
|
||||
void addHandler(String propertyName, BuiltinTypeHandler<?> primitiveType) {
|
||||
properties.put(propertyName, primitiveType);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import java.lang.reflect.InvocationTargetException;
|
|||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
//notes:
|
||||
//1. should find out growth factor of arraylist
|
||||
|
|
@ -25,7 +24,9 @@ import java.util.function.UnaryOperator;
|
|||
* <p>
|
||||
* Employs the SQLite style of data storage, most notably integer numbers are stored with variable byte length
|
||||
* <p>
|
||||
* The classes stored in {@link ContiguousList} MUST have a no-args constructor.
|
||||
* The classes stored in {@link ContiguousList} MUST have a no-args constructor. (so sorry)
|
||||
* // There is (was?) a way to create instances without a no-args constructor. I have used it somewhere in the past...
|
||||
* // I think {@link java.io.ObjectInputStream} uses it.
|
||||
* <p>
|
||||
* Like ArrayList, mutating operations are not synchronized.
|
||||
* <p>
|
||||
|
|
@ -35,7 +36,7 @@ import java.util.function.UnaryOperator;
|
|||
* performance-wise, like the indexed add and set methods. They mess with the memory layout. The list is meant to
|
||||
* be appended at the tail.
|
||||
*/
|
||||
public class ContiguousList<E> implements List<E> {
|
||||
public class ContiguousList<E> extends NotImplementedList<E> implements List<E> {
|
||||
|
||||
private static final byte[] DOUBLE_TYPE = {7};
|
||||
private static final byte[] FLOAT_TYPE = {10}; // not in line with SQLite anymore
|
||||
|
|
@ -49,17 +50,17 @@ public class ContiguousList<E> implements List<E> {
|
|||
*/
|
||||
private ByteBuffer data = ByteBuffer.allocate(32);
|
||||
|
||||
private int currentElementIndex;
|
||||
private int currentElementValueIndex;
|
||||
|
||||
private int[] elementIndices = new int[10];
|
||||
|
||||
private int size;
|
||||
|
||||
private TypeHandler type;
|
||||
private TypeHandler rootHandler;
|
||||
|
||||
public ContiguousList(Class<E> type) {
|
||||
inspectType(type);
|
||||
elementIndices[0] = currentElementIndex; // index of first element
|
||||
elementIndices[0] = currentElementValueIndex; // index of first element
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -72,10 +73,10 @@ public class ContiguousList<E> implements List<E> {
|
|||
*/
|
||||
private void inspectType(Class<?> type) {
|
||||
if (PropertyHandlerFactory.isKnownType(type)) {
|
||||
this.type = PropertyHandlerFactory.forType(type);
|
||||
this.rootHandler = PropertyHandlerFactory.forType(type);
|
||||
} else {
|
||||
CompoundTypeHandler compoundType = new CompoundTypeHandler(type);
|
||||
this.type = compoundType;
|
||||
this.rootHandler = compoundType;
|
||||
try {
|
||||
addPropertyHandlersForCompoundType(type, compoundType);
|
||||
} catch (IllegalAccessException e) {
|
||||
|
|
@ -94,7 +95,7 @@ public class ContiguousList<E> implements List<E> {
|
|||
MethodHandle setter = lookup.findSetter(type, field.getName(), fieldType);
|
||||
|
||||
if (PropertyHandlerFactory.isKnownType(fieldType)) {
|
||||
PrimitiveTypeHandler<?> primitiveType = PropertyHandlerFactory.forType(fieldType, getter, setter);
|
||||
BuiltinTypeHandler<?> primitiveType = PropertyHandlerFactory.forType(fieldType, getter, setter);
|
||||
|
||||
parentCompoundType.addHandler(field.getName(), primitiveType);
|
||||
} else {
|
||||
|
|
@ -111,36 +112,31 @@ public class ContiguousList<E> implements List<E> {
|
|||
});
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("Contract")
|
||||
public boolean add(E element) {
|
||||
if (element == null) {
|
||||
return false;
|
||||
}
|
||||
getProperties(element, type);
|
||||
getProperties(element, rootHandler);
|
||||
size += 1;
|
||||
|
||||
// keep track of where the objects are stored
|
||||
if (elementIndices.length < size + 1) {
|
||||
this.elementIndices = Arrays.copyOf(this.elementIndices, this.elementIndices.length * 2);
|
||||
}
|
||||
elementIndices[size] = currentElementIndex;
|
||||
elementIndices[size] = currentElementValueIndex;
|
||||
return true;
|
||||
}
|
||||
|
||||
private void getProperties(Object element, TypeHandler type) {
|
||||
// passed type is primitive
|
||||
//TODO rename primitive to builtin
|
||||
if (type instanceof PrimitiveTypeHandler<?>) {
|
||||
((PrimitiveTypeHandler<?>) type).storePropertyValue(element, this);
|
||||
private void getProperties(Object element, TypeHandler typeHandler) {
|
||||
if (typeHandler instanceof BuiltinTypeHandler<?>) {
|
||||
((BuiltinTypeHandler<?>) typeHandler).storePropertyValue(element, this);
|
||||
} else {
|
||||
// passed type is compund ie. has child properties
|
||||
((CompoundTypeHandler)type).getProperties().forEach(property -> {
|
||||
if (property instanceof PrimitiveTypeHandler<?>) {
|
||||
// recurse once more -> property is stored
|
||||
getProperties(element, property);
|
||||
//could easily inline this
|
||||
// passed type is compound ie. has child properties
|
||||
((CompoundTypeHandler) typeHandler).getProperties().forEach(property -> {
|
||||
if (property instanceof BuiltinTypeHandler<?>) {
|
||||
((BuiltinTypeHandler<?>) property).storePropertyValue(element, this);
|
||||
} else {
|
||||
CompoundTypeHandler child = ((CompoundTypeHandler) property);
|
||||
try {
|
||||
|
|
@ -154,17 +150,16 @@ public class ContiguousList<E> implements List<E> {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
throw new RuntimeException("Not yet implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("NullableProblems")
|
||||
public boolean containsAll(Collection<?> collection) {
|
||||
throw new RuntimeException("Not yet implemented");
|
||||
}
|
||||
|
||||
/**
|
||||
* Get element at specified index.
|
||||
* <p>
|
||||
* Please note that this creates a new instance using the stored element data and is therefore
|
||||
* not the recommended usecase because of the performance penalty. It's implemented for convenience, but
|
||||
* there are alternatives such as the propertyIterator and getXX...[implement]
|
||||
*
|
||||
* @param index The index of the element data
|
||||
* @return a new element instance
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public E get(int index) {
|
||||
|
|
@ -173,14 +168,15 @@ public class ContiguousList<E> implements List<E> {
|
|||
}
|
||||
data.position(elementIndices[index]);
|
||||
try {
|
||||
if (type instanceof PrimitiveTypeHandler<?>) {
|
||||
return (E)((PrimitiveTypeHandler<?>)type).transform(ValueReader.read(data));
|
||||
if (rootHandler instanceof BuiltinTypeHandler<?>) {
|
||||
Object read = ValueReader.read(data);
|
||||
return (E) ((BuiltinTypeHandler<?>) rootHandler).transform(read);
|
||||
}
|
||||
// create a new instance of the list element type
|
||||
E newInstance = (E) type.getType().getDeclaredConstructor().newInstance();
|
||||
E newInstance = (E) rootHandler.getType().getDeclaredConstructor().newInstance();
|
||||
|
||||
// set the data
|
||||
setProperties(newInstance, (CompoundTypeHandler) type);
|
||||
setProperties(newInstance, (CompoundTypeHandler) rootHandler);
|
||||
|
||||
return newInstance;
|
||||
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
|
||||
|
|
@ -191,8 +187,8 @@ public class ContiguousList<E> implements List<E> {
|
|||
|
||||
private void setProperties(Object element, CompoundTypeHandler compoundType) {
|
||||
compoundType.getProperties().forEach(property -> {
|
||||
if (property instanceof PrimitiveTypeHandler) {
|
||||
PrimitiveTypeHandler<?> type =((PrimitiveTypeHandler<?>) property);
|
||||
if (property instanceof BuiltinTypeHandler) {
|
||||
BuiltinTypeHandler<?> type = ((BuiltinTypeHandler<?>) property);
|
||||
type.setValue(element, ValueReader.read(data));
|
||||
} else {
|
||||
try {
|
||||
|
|
@ -212,6 +208,65 @@ public class ContiguousList<E> implements List<E> {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@link Iterator} over the property values in the List. That is, it iterates all
|
||||
* bean property values in a fixed order for all elements.
|
||||
* <p>
|
||||
* Because the values differ in type the output type is Object
|
||||
*
|
||||
* NB the actual type (right now) is the `raw` value: all integers are of type Long, BigInteger is String
|
||||
* // That is unfortunate (or must I say: annoying!), but for something like JSON not a problem (I think).
|
||||
* // So maybe keep this in (say 'rawValueIterator') and also create a typesafe iterator.
|
||||
* <p>
|
||||
* It detects {@link ConcurrentModificationException} if the underlying list was updated while iterating.
|
||||
* <p>
|
||||
* // I should probably include a type so that the caller could cast to the correct type
|
||||
* // not sure yet
|
||||
*
|
||||
* @return an Iterator<?>
|
||||
*/
|
||||
public Iterator<?> valueIterator() {
|
||||
return new ValueIterator();
|
||||
}
|
||||
|
||||
class ValueIterator implements Iterator<Object> {
|
||||
private final int originalSize;
|
||||
private final int originalPosition;
|
||||
|
||||
ValueIterator() {
|
||||
this.originalSize = size;
|
||||
this.originalPosition = data.position();
|
||||
data.position(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return data.position() < originalPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object next() {
|
||||
if (originalSize != size) {
|
||||
throw new ConcurrentModificationException("Modifications detected while iterating.");
|
||||
}
|
||||
/* The following depends on the bytebuffer position. Calling add(..) would mess it up
|
||||
* so that's why we first check for modifications (me and the computer)
|
||||
*
|
||||
* I could also maintain the position here. But you main want to fail ... dunno */
|
||||
return ValueReader.read(data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@link Iterator} over the property values of the specified element in the List.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public Iterator<Object> valueIterator(int index) {
|
||||
//TODO
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean addAll(Collection<? extends E> collection) {
|
||||
for (E element : collection) {
|
||||
add(element);
|
||||
|
|
@ -219,84 +274,11 @@ public class ContiguousList<E> implements List<E> {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("NullableProblems")
|
||||
public boolean addAll(int i, Collection<? extends E> collection) {
|
||||
throw new RuntimeException("Not yet implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("NullableProblems")
|
||||
public boolean removeAll(Collection<?> collection) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("NullableProblems")
|
||||
public boolean retainAll(Collection<?> collection) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replaceAll(UnaryOperator<E> operator) {
|
||||
throw new RuntimeException("Not yet implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sort(Comparator<? super E> c) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
this.currentElementIndex = 0;
|
||||
this.currentElementValueIndex = 0;
|
||||
this.size = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public E set(int i, E e) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(int i, E e) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public E remove(int i) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int indexOf(Object o) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int lastIndexOf(Object o) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListIterator<E> listIterator() {
|
||||
throw new RuntimeException("Not yet implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListIterator<E> listIterator(int i) {
|
||||
throw new RuntimeException("Not yet implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<E> subList(int i, int i1) {
|
||||
throw new RuntimeException("Not yet implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spliterator<E> spliterator() {
|
||||
return List.super.spliterator();
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
|
@ -306,14 +288,9 @@ public class ContiguousList<E> implements List<E> {
|
|||
return size == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<E> iterator() {
|
||||
return new Iter<>();
|
||||
return new ElementIterator<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -338,9 +315,15 @@ public class ContiguousList<E> implements List<E> {
|
|||
}
|
||||
|
||||
|
||||
class Iter<F> implements Iterator<F> {
|
||||
class ElementIterator<F> implements Iterator<F> {
|
||||
|
||||
private int curIndex = 0;
|
||||
private final int originalSize;
|
||||
|
||||
ElementIterator() {
|
||||
this.originalSize = size;
|
||||
data.position(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
|
|
@ -356,15 +339,15 @@ public class ContiguousList<E> implements List<E> {
|
|||
|
||||
private void store(byte[] bytes) {
|
||||
ensureFree(bytes.length);
|
||||
data.position(currentElementIndex); // ensures intermittent reads/writes
|
||||
data.position(currentElementValueIndex); // ensures intermittent reads/writes are safe
|
||||
data.put(bytes);
|
||||
currentElementIndex += bytes.length;
|
||||
currentElementValueIndex += bytes.length;
|
||||
}
|
||||
|
||||
private void store0() {
|
||||
ensureFree(1);
|
||||
data.put((byte) 0);
|
||||
currentElementIndex += 1;
|
||||
currentElementValueIndex += 1;
|
||||
}
|
||||
|
||||
void storeString(String value) {
|
||||
|
|
@ -436,7 +419,7 @@ public class ContiguousList<E> implements List<E> {
|
|||
}
|
||||
|
||||
byte[] getData() {
|
||||
return Arrays.copyOfRange(data.array(), 0, currentElementIndex);
|
||||
return Arrays.copyOfRange(data.array(), 0, currentElementValueIndex);
|
||||
}
|
||||
|
||||
int[] getElementIndices() {
|
||||
|
|
@ -444,7 +427,7 @@ public class ContiguousList<E> implements List<E> {
|
|||
}
|
||||
|
||||
private void ensureFree(int length) {
|
||||
while (currentElementIndex + length > data.capacity()) {
|
||||
while (currentElementValueIndex + length > data.capacity()) {
|
||||
byte[] bytes = this.data.array();
|
||||
this.data = ByteBuffer.allocate(this.data.capacity() * 2);
|
||||
this.data.put(bytes);
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import java.lang.invoke.MethodHandle;
|
|||
/**
|
||||
* Stores a double value.
|
||||
*/
|
||||
class DoubleHandler extends PrimitiveTypeHandler<Double> {
|
||||
class DoubleHandler extends BuiltinTypeHandler<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 PrimitiveTypeHandler<Float> {
|
||||
class FloatHandler extends BuiltinTypeHandler<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 PrimitiveTypeHandler<Integer> {
|
||||
class IntegerHandler extends BuiltinTypeHandler<Integer> {
|
||||
public IntegerHandler(MethodHandle getter, MethodHandle setter) {
|
||||
super(Integer.class, getter, setter);
|
||||
}
|
||||
|
|
@ -20,4 +20,14 @@ class IntegerHandler extends PrimitiveTypeHandler<Integer> {
|
|||
public void setValue(Object instance, Object value) {
|
||||
super.setValue(instance, ((Long) value).intValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object transform(Object value) {
|
||||
// could be Long (raw value)
|
||||
// or Integer when it's a property with known type
|
||||
if (value instanceof Long) {
|
||||
return ((Long) value).intValue();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package nl.sanderhautvast.contiguous;
|
|||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
|
||||
class LongHandler extends PrimitiveTypeHandler<Long> {
|
||||
class LongHandler extends BuiltinTypeHandler<Long> {
|
||||
public LongHandler(MethodHandle getter, MethodHandle setter) {
|
||||
super(Long.class, getter, setter);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,117 @@
|
|||
package nl.sanderhautvast.contiguous;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.UnaryOperator;
|
||||
|
||||
/**
|
||||
* Base class that is a list of all the methods live that will likely not be implemented (pun intended)
|
||||
* Only purpose: reduce linecount in the subclass.
|
||||
*
|
||||
* @param <E>
|
||||
*/
|
||||
public abstract class NotImplementedList<E> implements List<E> {
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
// is possible, but not feasible: iterate, create instance, then compare ??
|
||||
}
|
||||
|
||||
@Override
|
||||
public Spliterator<E> spliterator() {
|
||||
return List.super.spliterator();
|
||||
// not sure about this yet
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
throw new RuntimeException("Not yet implemented");
|
||||
// is possible, but not feasible: iterate, create instance, then compare ??
|
||||
// and then removing, which requires moving a lot of bytes
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("NullableProblems")
|
||||
public boolean containsAll(Collection<?> collection) {
|
||||
throw new RuntimeException("Not yet implemented");
|
||||
// is possible, but not feasible: iterate, create instance, then compare ??
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(int i, Collection<? extends E> collection) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
// is possible, but not feasible because it would require moving a lot of bytes
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replaceAll(UnaryOperator<E> operator) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
// is possible, but not feasible because it would require moving a lot of bytes
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> collection) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
// is possible, but not feasible because it would require moving a lot of bytes
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(Collection<?> collection) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
// is possible, but not feasible because it would require moving a lot of bytes
|
||||
}
|
||||
|
||||
@Override
|
||||
public E set(int i, E e) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
// is possible, but not feasible because it would require moving a lot of bytes
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(int i, E e) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
// is possible, but not feasible because it would require moving a lot of bytes
|
||||
}
|
||||
|
||||
@Override
|
||||
public E remove(int i) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
// is possible, but not feasible because it would require moving a lot of bytes
|
||||
}
|
||||
|
||||
@Override
|
||||
public int indexOf(Object o) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
// is possible, but not feasible: iterate, create instance, then compare ??
|
||||
}
|
||||
|
||||
@Override
|
||||
public int lastIndexOf(Object o) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
// is possible, but not feasible
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListIterator<E> listIterator() {
|
||||
throw new RuntimeException("Not implemented");
|
||||
// ListIterator contains remove, so not possible
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListIterator<E> listIterator(int i) {
|
||||
throw new RuntimeException("Not yet implemented");
|
||||
// ListIterator contains remove, so not possible
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sort(Comparator<? super E> c) {
|
||||
throw new RuntimeException("Not implemented");
|
||||
// an immutable sort would be an option
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<E> subList(int i, int i1) {
|
||||
throw new RuntimeException("Not yet implemented");
|
||||
// possible
|
||||
}
|
||||
}
|
||||
|
|
@ -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 PrimitiveTypeHandler<?>>> TYPE_HANDLERS = new HashMap<>();
|
||||
private static final Map<Class<?>, Class<? extends BuiltinTypeHandler<?>>> TYPE_HANDLERS = new HashMap<>();
|
||||
|
||||
private PropertyHandlerFactory() {
|
||||
}
|
||||
|
|
@ -41,13 +41,13 @@ final class PropertyHandlerFactory {
|
|||
return TYPE_HANDLERS.containsKey(type);
|
||||
}
|
||||
|
||||
public static <T> PrimitiveTypeHandler<T> forType(Class<T> type, MethodHandle getter, MethodHandle setter) {
|
||||
public static <T> BuiltinTypeHandler<T> forType(Class<T> type, MethodHandle getter, MethodHandle setter) {
|
||||
try {
|
||||
Class<? extends PrimitiveTypeHandler<?>> appenderClass = TYPE_HANDLERS.get(type);
|
||||
Class<? extends BuiltinTypeHandler<?>> appenderClass = TYPE_HANDLERS.get(type);
|
||||
if (appenderClass == null) {
|
||||
throw new IllegalStateException("No Handler for " + type.getName());
|
||||
}
|
||||
return (PrimitiveTypeHandler<T>) appenderClass.getDeclaredConstructor(MethodHandle.class, MethodHandle.class)
|
||||
return (BuiltinTypeHandler<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> PrimitiveTypeHandler<T> forType(Class<T> type) {
|
||||
public static <T> BuiltinTypeHandler<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 PrimitiveTypeHandler<?>> typehandler) {
|
||||
public static void register(Class<?> type, Class<? extends BuiltinTypeHandler<?>> typehandler) {
|
||||
TYPE_HANDLERS.put(type, typehandler);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package nl.sanderhautvast.contiguous;
|
|||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
|
||||
class ShortHandler extends PrimitiveTypeHandler<Short> {
|
||||
class ShortHandler extends BuiltinTypeHandler<Short> {
|
||||
public ShortHandler(MethodHandle getter, MethodHandle setter) {
|
||||
super(Short.class, getter, setter);
|
||||
}
|
||||
|
|
@ -16,4 +16,12 @@ class ShortHandler extends PrimitiveTypeHandler<Short> {
|
|||
public void setValue(Object instance, Object value) {
|
||||
super.setValue(instance, ((Long) value).shortValue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object transform(Object value) {
|
||||
if (value instanceof Long) {
|
||||
return ((Long) value).shortValue();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package nl.sanderhautvast.contiguous;
|
|||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
|
||||
class StringHandler extends PrimitiveTypeHandler<String> {
|
||||
class StringHandler extends BuiltinTypeHandler<String> {
|
||||
public StringHandler(MethodHandle getter, MethodHandle setter) {
|
||||
super(String.class, getter, setter);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,9 +40,9 @@ class ValueReader {
|
|||
} else if (columnType == 7) {
|
||||
return buffer.getDouble();
|
||||
} else if (columnType == 8) {
|
||||
return 0;
|
||||
return 0L; //has to be long!
|
||||
} else if (columnType == 9) {
|
||||
return 1;
|
||||
return 1L;
|
||||
} else if (columnType == 10) {
|
||||
return buffer.getFloat();
|
||||
} else if (columnType >= 12 && columnType % 2 == 0) {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package nl.sanderhautvast.contiguous;
|
|||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
|
@ -141,4 +142,59 @@ public class ContiguousListTest {
|
|||
bigIntegers.add(new BigInteger("1000000000"));
|
||||
assertEquals(1_000_000_000L, bigIntegers.get(0).longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIterator() {
|
||||
ContiguousList<Integer> integers = new ContiguousList<>(Integer.class);
|
||||
for (int i = 0; i < 100; i++) {
|
||||
integers.add(i);
|
||||
}
|
||||
int prevValue = -1;
|
||||
for (int value : integers) {
|
||||
assertEquals(prevValue, value - 1);
|
||||
prevValue = value;
|
||||
}
|
||||
|
||||
integers.add(100);
|
||||
|
||||
assertEquals(100, integers.get(100));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrimitiveIterator() {
|
||||
ContiguousList<Integer> integers = new ContiguousList<>(Integer.class);
|
||||
for (int i = 0; i < 100; i++) {
|
||||
integers.add(i);
|
||||
}
|
||||
long prevValue = -1;
|
||||
for (Iterator<?> intIter = integers.valueIterator(); intIter.hasNext(); ) {
|
||||
long value = (long) intIter.next();
|
||||
assertEquals(prevValue, value - 1);
|
||||
prevValue = value;
|
||||
}
|
||||
|
||||
|
||||
integers.add(100);
|
||||
|
||||
assertEquals(100, integers.get(100));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompoundValueIterator() {
|
||||
ContiguousList<IntBean> integers = new ContiguousList<>(IntBean.class);
|
||||
for (int i = 0; i < 100; i++) {
|
||||
integers.add(new IntBean(i));
|
||||
}
|
||||
long prevValue = -1;
|
||||
for (Iterator<?> intIter = integers.valueIterator(); intIter.hasNext(); ) {
|
||||
long value = (long) intIter.next(); // here a value (IntBean.value)
|
||||
assertEquals(prevValue, value - 1);
|
||||
prevValue = value;
|
||||
}
|
||||
|
||||
|
||||
integers.add(new IntBean(100));
|
||||
|
||||
assertEquals(new IntBean(100), integers.get(100)); // here an instance
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue