diff --git a/lib/src/main/java/nl/sanderhautvast/contiguous/BigDecimalHandler.java b/lib/src/main/java/nl/sanderhautvast/contiguous/BigDecimalHandler.java index 4b69eba..f9ef444 100644 --- a/lib/src/main/java/nl/sanderhautvast/contiguous/BigDecimalHandler.java +++ b/lib/src/main/java/nl/sanderhautvast/contiguous/BigDecimalHandler.java @@ -3,7 +3,7 @@ package nl.sanderhautvast.contiguous; import java.lang.invoke.MethodHandle; import java.math.BigDecimal; -class BigDecimalHandler extends PrimitiveTypeHandler { +class BigDecimalHandler extends BuiltinTypeHandler { public BigDecimalHandler(MethodHandle getter, MethodHandle setter) { super(BigDecimal.class, getter, setter); } diff --git a/lib/src/main/java/nl/sanderhautvast/contiguous/BigIntegerHandler.java b/lib/src/main/java/nl/sanderhautvast/contiguous/BigIntegerHandler.java index 28f2012..1d19d74 100644 --- a/lib/src/main/java/nl/sanderhautvast/contiguous/BigIntegerHandler.java +++ b/lib/src/main/java/nl/sanderhautvast/contiguous/BigIntegerHandler.java @@ -3,7 +3,7 @@ package nl.sanderhautvast.contiguous; import java.lang.invoke.MethodHandle; import java.math.BigInteger; -class BigIntegerHandler extends PrimitiveTypeHandler { +class BigIntegerHandler extends BuiltinTypeHandler { public BigIntegerHandler(MethodHandle getter, MethodHandle setter) { super(BigInteger.class, getter, setter); } diff --git a/lib/src/main/java/nl/sanderhautvast/contiguous/PrimitiveTypeHandler.java b/lib/src/main/java/nl/sanderhautvast/contiguous/BuiltinTypeHandler.java similarity index 89% rename from lib/src/main/java/nl/sanderhautvast/contiguous/PrimitiveTypeHandler.java rename to lib/src/main/java/nl/sanderhautvast/contiguous/BuiltinTypeHandler.java index bf7d13d..12e847d 100644 --- a/lib/src/main/java/nl/sanderhautvast/contiguous/PrimitiveTypeHandler.java +++ b/lib/src/main/java/nl/sanderhautvast/contiguous/BuiltinTypeHandler.java @@ -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 extends TypeHandler { - public PrimitiveTypeHandler(Class type, MethodHandle getter, MethodHandle setter) { +public abstract class BuiltinTypeHandler extends TypeHandler { + public BuiltinTypeHandler(Class type, MethodHandle getter, MethodHandle setter) { super(type, getter, setter); } @@ -64,7 +64,7 @@ public abstract class PrimitiveTypeHandler extends TypeHandler { * Certain types can easily be stored as another known type, for instance * a BigDecimal can be stored as a String. *

- * 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 diff --git a/lib/src/main/java/nl/sanderhautvast/contiguous/ByteHandler.java b/lib/src/main/java/nl/sanderhautvast/contiguous/ByteHandler.java index aa4769f..0ad0afe 100644 --- a/lib/src/main/java/nl/sanderhautvast/contiguous/ByteHandler.java +++ b/lib/src/main/java/nl/sanderhautvast/contiguous/ByteHandler.java @@ -5,7 +5,7 @@ import java.lang.invoke.MethodHandle; /** * Stores a byte value. */ -class ByteHandler extends PrimitiveTypeHandler { +class ByteHandler extends BuiltinTypeHandler { public ByteHandler(MethodHandle getter, MethodHandle setter) { super(Byte.class, getter, setter); @@ -20,4 +20,12 @@ class ByteHandler extends PrimitiveTypeHandler { 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; + } } diff --git a/lib/src/main/java/nl/sanderhautvast/contiguous/CompoundTypeHandler.java b/lib/src/main/java/nl/sanderhautvast/contiguous/CompoundTypeHandler.java index 36447da..5e2fea9 100644 --- a/lib/src/main/java/nl/sanderhautvast/contiguous/CompoundTypeHandler.java +++ b/lib/src/main/java/nl/sanderhautvast/contiguous/CompoundTypeHandler.java @@ -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); } diff --git a/lib/src/main/java/nl/sanderhautvast/contiguous/ContiguousList.java b/lib/src/main/java/nl/sanderhautvast/contiguous/ContiguousList.java index 48778ce..40345e5 100644 --- a/lib/src/main/java/nl/sanderhautvast/contiguous/ContiguousList.java +++ b/lib/src/main/java/nl/sanderhautvast/contiguous/ContiguousList.java @@ -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; *

* Employs the SQLite style of data storage, most notably integer numbers are stored with variable byte length *

- * 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. *

* Like ArrayList, mutating operations are not synchronized. *

@@ -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 implements List { +public class ContiguousList extends NotImplementedList implements List { 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 implements List { */ 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 type) { inspectType(type); - elementIndices[0] = currentElementIndex; // index of first element + elementIndices[0] = currentElementValueIndex; // index of first element } /* @@ -72,10 +73,10 @@ public class ContiguousList implements List { */ 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 implements List { 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 implements List { }); } - @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 implements List { } } - @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. + *

+ * 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 implements List { } 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 implements List { 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 implements List { }); } + /** + * 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. + *

+ * 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. + *

+ * It detects {@link ConcurrentModificationException} if the underlying list was updated while iterating. + *

+ * // 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 { + 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 valueIterator(int index) { + //TODO + return null; + } + public boolean addAll(Collection collection) { for (E element : collection) { add(element); @@ -219,84 +274,11 @@ public class ContiguousList implements List { return true; } - @Override - @SuppressWarnings("NullableProblems") - public boolean addAll(int i, Collection 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 operator) { - throw new RuntimeException("Not yet implemented"); - } - - @Override - public void sort(Comparator 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 listIterator() { - throw new RuntimeException("Not yet implemented"); - } - - @Override - public ListIterator listIterator(int i) { - throw new RuntimeException("Not yet implemented"); - } - - @Override - public List subList(int i, int i1) { - throw new RuntimeException("Not yet implemented"); - } - - @Override - public Spliterator spliterator() { - return List.super.spliterator(); - } - public int size() { return size; } @@ -306,14 +288,9 @@ public class ContiguousList implements List { return size == 0; } - @Override - public boolean contains(Object o) { - throw new RuntimeException("Not implemented"); - } - @Override public Iterator iterator() { - return new Iter<>(); + return new ElementIterator<>(); } @Override @@ -338,9 +315,15 @@ public class ContiguousList implements List { } - class Iter implements Iterator { + class ElementIterator implements Iterator { 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 implements List { 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 implements List { } 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 implements List { } 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); diff --git a/lib/src/main/java/nl/sanderhautvast/contiguous/DoubleHandler.java b/lib/src/main/java/nl/sanderhautvast/contiguous/DoubleHandler.java index 74b169b..04b2002 100644 --- a/lib/src/main/java/nl/sanderhautvast/contiguous/DoubleHandler.java +++ b/lib/src/main/java/nl/sanderhautvast/contiguous/DoubleHandler.java @@ -5,7 +5,7 @@ import java.lang.invoke.MethodHandle; /** * Stores a double value. */ -class DoubleHandler extends PrimitiveTypeHandler { +class DoubleHandler extends BuiltinTypeHandler { public DoubleHandler(MethodHandle getter, MethodHandle setter) { super(Double.class, getter, setter); } diff --git a/lib/src/main/java/nl/sanderhautvast/contiguous/FloatHandler.java b/lib/src/main/java/nl/sanderhautvast/contiguous/FloatHandler.java index ba2dedc..cc0ab38 100644 --- a/lib/src/main/java/nl/sanderhautvast/contiguous/FloatHandler.java +++ b/lib/src/main/java/nl/sanderhautvast/contiguous/FloatHandler.java @@ -2,7 +2,7 @@ package nl.sanderhautvast.contiguous; import java.lang.invoke.MethodHandle; -class FloatHandler extends PrimitiveTypeHandler { +class FloatHandler extends BuiltinTypeHandler { public FloatHandler(MethodHandle getter, MethodHandle setter) { super(Float.class, getter, setter); } diff --git a/lib/src/main/java/nl/sanderhautvast/contiguous/IntegerHandler.java b/lib/src/main/java/nl/sanderhautvast/contiguous/IntegerHandler.java index 2082cfd..1481605 100644 --- a/lib/src/main/java/nl/sanderhautvast/contiguous/IntegerHandler.java +++ b/lib/src/main/java/nl/sanderhautvast/contiguous/IntegerHandler.java @@ -2,7 +2,7 @@ package nl.sanderhautvast.contiguous; import java.lang.invoke.MethodHandle; -class IntegerHandler extends PrimitiveTypeHandler { +class IntegerHandler extends BuiltinTypeHandler { public IntegerHandler(MethodHandle getter, MethodHandle setter) { super(Integer.class, getter, setter); } @@ -20,4 +20,14 @@ class IntegerHandler extends PrimitiveTypeHandler { 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; + } } diff --git a/lib/src/main/java/nl/sanderhautvast/contiguous/LongHandler.java b/lib/src/main/java/nl/sanderhautvast/contiguous/LongHandler.java index c04de80..69dfaec 100644 --- a/lib/src/main/java/nl/sanderhautvast/contiguous/LongHandler.java +++ b/lib/src/main/java/nl/sanderhautvast/contiguous/LongHandler.java @@ -2,7 +2,7 @@ package nl.sanderhautvast.contiguous; import java.lang.invoke.MethodHandle; -class LongHandler extends PrimitiveTypeHandler { +class LongHandler extends BuiltinTypeHandler { public LongHandler(MethodHandle getter, MethodHandle setter) { super(Long.class, getter, setter); } diff --git a/lib/src/main/java/nl/sanderhautvast/contiguous/NotImplementedList.java b/lib/src/main/java/nl/sanderhautvast/contiguous/NotImplementedList.java new file mode 100644 index 0000000..051c708 --- /dev/null +++ b/lib/src/main/java/nl/sanderhautvast/contiguous/NotImplementedList.java @@ -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 + */ +public abstract class NotImplementedList implements List { + + @Override + public boolean contains(Object o) { + throw new RuntimeException("Not implemented"); + // is possible, but not feasible: iterate, create instance, then compare ?? + } + + @Override + public Spliterator 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 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 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 listIterator() { + throw new RuntimeException("Not implemented"); + // ListIterator contains remove, so not possible + } + + @Override + public ListIterator listIterator(int i) { + throw new RuntimeException("Not yet implemented"); + // ListIterator contains remove, so not possible + } + + @Override + public void sort(Comparator c) { + throw new RuntimeException("Not implemented"); + // an immutable sort would be an option + } + + @Override + public List subList(int i, int i1) { + throw new RuntimeException("Not yet implemented"); + // possible + } +} diff --git a/lib/src/main/java/nl/sanderhautvast/contiguous/PropertyHandlerFactory.java b/lib/src/main/java/nl/sanderhautvast/contiguous/PropertyHandlerFactory.java index 0100923..c89bed1 100644 --- a/lib/src/main/java/nl/sanderhautvast/contiguous/PropertyHandlerFactory.java +++ b/lib/src/main/java/nl/sanderhautvast/contiguous/PropertyHandlerFactory.java @@ -11,7 +11,7 @@ import java.util.Map; * Maps the propertyvalue type to a PropertyHandler */ final class PropertyHandlerFactory { - private static final Map, Class>> TYPE_HANDLERS = new HashMap<>(); + private static final Map, Class>> TYPE_HANDLERS = new HashMap<>(); private PropertyHandlerFactory() { } @@ -41,13 +41,13 @@ final class PropertyHandlerFactory { return TYPE_HANDLERS.containsKey(type); } - public static PrimitiveTypeHandler forType(Class type, MethodHandle getter, MethodHandle setter) { + public static BuiltinTypeHandler forType(Class type, MethodHandle getter, MethodHandle setter) { try { - Class> appenderClass = TYPE_HANDLERS.get(type); + Class> appenderClass = TYPE_HANDLERS.get(type); if (appenderClass == null) { throw new IllegalStateException("No Handler for " + type.getName()); } - return (PrimitiveTypeHandler) appenderClass.getDeclaredConstructor(MethodHandle.class, MethodHandle.class) + return (BuiltinTypeHandler) appenderClass.getDeclaredConstructor(MethodHandle.class, MethodHandle.class) .newInstance(getter, setter); } catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) { @@ -55,14 +55,14 @@ final class PropertyHandlerFactory { } } - public static PrimitiveTypeHandler forType(Class type) { + public static BuiltinTypeHandler forType(Class type) { return forType(type, null, null); } /** * register a new TypeHandler that cannot be derived from bean properties */ - public static void register(Class type, Class> typehandler) { + public static void register(Class type, Class> typehandler) { TYPE_HANDLERS.put(type, typehandler); } } diff --git a/lib/src/main/java/nl/sanderhautvast/contiguous/ShortHandler.java b/lib/src/main/java/nl/sanderhautvast/contiguous/ShortHandler.java index 95b5393..d81d20b 100644 --- a/lib/src/main/java/nl/sanderhautvast/contiguous/ShortHandler.java +++ b/lib/src/main/java/nl/sanderhautvast/contiguous/ShortHandler.java @@ -2,7 +2,7 @@ package nl.sanderhautvast.contiguous; import java.lang.invoke.MethodHandle; -class ShortHandler extends PrimitiveTypeHandler { +class ShortHandler extends BuiltinTypeHandler { public ShortHandler(MethodHandle getter, MethodHandle setter) { super(Short.class, getter, setter); } @@ -16,4 +16,12 @@ class ShortHandler extends PrimitiveTypeHandler { 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; + } } diff --git a/lib/src/main/java/nl/sanderhautvast/contiguous/StringHandler.java b/lib/src/main/java/nl/sanderhautvast/contiguous/StringHandler.java index 6bd837d..3c6550c 100644 --- a/lib/src/main/java/nl/sanderhautvast/contiguous/StringHandler.java +++ b/lib/src/main/java/nl/sanderhautvast/contiguous/StringHandler.java @@ -2,7 +2,7 @@ package nl.sanderhautvast.contiguous; import java.lang.invoke.MethodHandle; -class StringHandler extends PrimitiveTypeHandler { +class StringHandler extends BuiltinTypeHandler { public StringHandler(MethodHandle getter, MethodHandle setter) { super(String.class, getter, setter); } diff --git a/lib/src/main/java/nl/sanderhautvast/contiguous/ValueReader.java b/lib/src/main/java/nl/sanderhautvast/contiguous/ValueReader.java index 9d051a7..e9e3862 100644 --- a/lib/src/main/java/nl/sanderhautvast/contiguous/ValueReader.java +++ b/lib/src/main/java/nl/sanderhautvast/contiguous/ValueReader.java @@ -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) { diff --git a/lib/src/test/java/nl/sanderhautvast/contiguous/ContiguousListTest.java b/lib/src/test/java/nl/sanderhautvast/contiguous/ContiguousListTest.java index dc09728..de6c473 100644 --- a/lib/src/test/java/nl/sanderhautvast/contiguous/ContiguousListTest.java +++ b/lib/src/test/java/nl/sanderhautvast/contiguous/ContiguousListTest.java @@ -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 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 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 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 + } }