WIP json.write
This commit is contained in:
parent
d59a9e1941
commit
db33d0fac8
11 changed files with 271 additions and 46 deletions
|
|
@ -32,6 +32,18 @@
|
||||||
<artifactId>jackson-databind</artifactId>
|
<artifactId>jackson-databind</artifactId>
|
||||||
<version>2.15.1</version>
|
<version>2.15.1</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-engine</artifactId>
|
||||||
|
<version>5.8.2</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.junit.jupiter</groupId>
|
||||||
|
<artifactId>junit-jupiter-api</artifactId>
|
||||||
|
<version>5.8.2</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
@ -7,24 +7,30 @@ import com.fasterxml.jackson.databind.ser.std.StdSerializer;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
public class ListSerializer<E> extends StdSerializer<ContiguousList<E>> {
|
public class ListSerializer<E> extends StdSerializer<ContiguousList> {
|
||||||
|
|
||||||
public ListSerializer(Class<ContiguousList<E>> t) {
|
public ListSerializer() {
|
||||||
super(t);
|
super(ContiguousList.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void serialize(
|
public void serialize(
|
||||||
ContiguousList<E> value, JsonGenerator jgen, SerializerProvider provider)
|
ContiguousList clist, JsonGenerator generator, SerializerProvider provider)
|
||||||
throws IOException, JsonProcessingException {
|
throws IOException, JsonProcessingException {
|
||||||
// value.
|
generator.writeStartArray();
|
||||||
|
|
||||||
// jgen.writeStartObject();
|
if (clist.isSimpleElementType()){
|
||||||
// jgen.writeNumberField("id", value.id);
|
Iterator<?> iterator = clist.valueIterator();
|
||||||
// jgen.writeStringField("itemName", value.itemName);
|
while (iterator.hasNext()){
|
||||||
// jgen.writeNumberField("owner", value.owner.id);
|
generator.writeString(iterator.next().toString());
|
||||||
// jgen.writeEndObject();
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
generator.writeEndArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package nl.sanderhautvast.contiguous;
|
||||||
|
|
||||||
|
public class AdamsObject {
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public AdamsObject() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public AdamsObject(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
package nl.sanderhautvast.contiguous;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.module.SimpleModule;
|
||||||
|
import org.junit.jupiter.api.Assertions;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
class ListSerializerTest {
|
||||||
|
|
||||||
|
|
||||||
|
private ObjectMapper mapper;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void setup(){
|
||||||
|
mapper = new ObjectMapper();
|
||||||
|
final SimpleModule module = new SimpleModule("mySerializers");
|
||||||
|
module.addSerializer(new ListSerializer<>());
|
||||||
|
mapper.registerModule(module);
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void testStringList() throws JsonProcessingException {
|
||||||
|
ContiguousList<String> strings = new ContiguousList<>(String.class);
|
||||||
|
strings.add("Vogon constructor fleet");
|
||||||
|
strings.add("Restaurant at the end of the Galaxy");
|
||||||
|
strings.add("Publishing houses of Ursa Minor");
|
||||||
|
|
||||||
|
String json = mapper.writeValueAsString(strings);
|
||||||
|
assertEquals("[\"Vogon constructor fleet\"," +
|
||||||
|
"\"Restaurant at the end of the Galaxy\"," +
|
||||||
|
"\"Publishing houses of Ursa Minor\"]",
|
||||||
|
json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testObjectList() throws JsonProcessingException {
|
||||||
|
ContiguousList<AdamsObject> strings = new ContiguousList<>(AdamsObject.class);
|
||||||
|
strings.add(new AdamsObject("Vogon constructor fleet"));
|
||||||
|
strings.add(new AdamsObject("Restaurant at the end of the Galaxy"));
|
||||||
|
strings.add(new AdamsObject("Publishing houses of Ursa Minor"));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
String json = mapper.writeValueAsString(strings);
|
||||||
|
assertEquals("[{\"name\":\"Vogon constructor fleet\"}," +
|
||||||
|
"{\"name\":\"Restaurant at the end of the Galaxy\"}," +
|
||||||
|
"{\"name\":\"Publishing houses of Ursa Minor\"}]",
|
||||||
|
json);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -39,7 +39,6 @@
|
||||||
<version>5.8.2</version>
|
<version>5.8.2</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-junit-jupiter -->
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.mockito</groupId>
|
<groupId>org.mockito</groupId>
|
||||||
<artifactId>mockito-junit-jupiter</artifactId>
|
<artifactId>mockito-junit-jupiter</artifactId>
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,11 @@ public abstract class BuiltinTypeHandler<T> extends TypeHandler {
|
||||||
*/
|
*/
|
||||||
public abstract void store(T value, ContiguousList<?> list);
|
public abstract void store(T value, ContiguousList<?> list);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBuiltin() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void storePropertyValue(Object instance, ContiguousList<?> typedList) {
|
void storePropertyValue(Object instance, ContiguousList<?> typedList) {
|
||||||
T propertyValue = getValue(instance);
|
T propertyValue = getValue(instance);
|
||||||
store(propertyValue, typedList);
|
store(propertyValue, typedList);
|
||||||
|
|
|
||||||
|
|
@ -26,4 +26,8 @@ class CompoundTypeHandler extends TypeHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isBuiltin() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import java.util.*;
|
||||||
//notes:
|
//notes:
|
||||||
// should find out growth factor of arraylist
|
// should find out growth factor of arraylist
|
||||||
// investigate data array reuse (pooling, SoftReferences etc)
|
// investigate data array reuse (pooling, SoftReferences etc)
|
||||||
|
// is all this inner class usage not wasteful? (references to this etc)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Short for Contiguous Layout List, an Experimental List implementation
|
* Short for Contiguous Layout List, an Experimental List implementation
|
||||||
|
|
@ -66,9 +67,16 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
|
||||||
|
|
||||||
private TypeHandler rootHandler;
|
private TypeHandler rootHandler;
|
||||||
|
|
||||||
|
private final Map<String, Integer> propertyNames;
|
||||||
|
|
||||||
public ContiguousList(Class<E> type) {
|
public ContiguousList(Class<E> type) {
|
||||||
inspectType(type);
|
inspectType(type);
|
||||||
elementIndices[0] = currentElementValueIndex; // index of first element
|
elementIndices[0] = 0; // index of first element
|
||||||
|
propertyNames = findPropertyNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Class<?> getElementType() {
|
||||||
|
return rootHandler.getType();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -80,7 +88,7 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
|
||||||
* object graph. It only knows the 'primitive' values.
|
* object graph. It only knows the 'primitive' values.
|
||||||
*/
|
*/
|
||||||
private void inspectType(Class<?> type) {
|
private void inspectType(Class<?> type) {
|
||||||
if (PropertyHandlerFactory.isKnownType(type)) {
|
if (PropertyHandlerFactory.isBuiltInType(type)) {
|
||||||
this.rootHandler = PropertyHandlerFactory.forType(type);
|
this.rootHandler = PropertyHandlerFactory.forType(type);
|
||||||
} else {
|
} else {
|
||||||
CompoundTypeHandler compoundType = new CompoundTypeHandler(type, null);//TODO revisit
|
CompoundTypeHandler compoundType = new CompoundTypeHandler(type, null);//TODO revisit
|
||||||
|
|
@ -93,6 +101,9 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* using reflection find all properties in the element, recursing down when the property is compound
|
||||||
|
*/
|
||||||
private void addPropertyHandlersForCompoundType(Class<?> type, CompoundTypeHandler parentCompoundType) throws IllegalAccessException {
|
private void addPropertyHandlersForCompoundType(Class<?> type, CompoundTypeHandler parentCompoundType) throws IllegalAccessException {
|
||||||
final MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(type, MethodHandles.lookup());
|
final MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(type, MethodHandles.lookup());
|
||||||
Arrays.stream(type.getDeclaredFields())
|
Arrays.stream(type.getDeclaredFields())
|
||||||
|
|
@ -102,7 +113,7 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
|
||||||
MethodHandle getter = lookup.findGetter(type, field.getName(), fieldType);
|
MethodHandle getter = lookup.findGetter(type, field.getName(), fieldType);
|
||||||
MethodHandle setter = lookup.findSetter(type, field.getName(), fieldType);
|
MethodHandle setter = lookup.findSetter(type, field.getName(), fieldType);
|
||||||
|
|
||||||
if (PropertyHandlerFactory.isKnownType(fieldType)) {
|
if (PropertyHandlerFactory.isBuiltInType(fieldType)) {
|
||||||
BuiltinTypeHandler<?> primitiveType = PropertyHandlerFactory.forType(fieldType, field.getName(), getter, setter);
|
BuiltinTypeHandler<?> primitiveType = PropertyHandlerFactory.forType(fieldType, field.getName(), getter, setter);
|
||||||
|
|
||||||
parentCompoundType.addHandler(field.getName(), primitiveType);
|
parentCompoundType.addHandler(field.getName(), primitiveType);
|
||||||
|
|
@ -126,7 +137,7 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
|
||||||
if (element == null) {
|
if (element == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
getProperties(element, rootHandler);
|
storePropertyData(element, rootHandler);
|
||||||
size += 1;
|
size += 1;
|
||||||
|
|
||||||
// keep track of where the objects are stored
|
// keep track of where the objects are stored
|
||||||
|
|
@ -137,7 +148,13 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void getProperties(Object element, TypeHandler typeHandler) {
|
/*
|
||||||
|
* Stores the properties
|
||||||
|
*
|
||||||
|
* walks the object graph depth-first. The order of the stored data is crucial, because only
|
||||||
|
* leaf elements are stored and all information on what object owns what is implicit.
|
||||||
|
*/
|
||||||
|
private void storePropertyData(Object element, TypeHandler typeHandler) {
|
||||||
if (typeHandler instanceof BuiltinTypeHandler<?>) {
|
if (typeHandler instanceof BuiltinTypeHandler<?>) {
|
||||||
((BuiltinTypeHandler<?>) typeHandler).storePropertyValue(element, this);
|
((BuiltinTypeHandler<?>) typeHandler).storePropertyValue(element, this);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -149,7 +166,7 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
|
||||||
CompoundTypeHandler child = ((CompoundTypeHandler) property);
|
CompoundTypeHandler child = ((CompoundTypeHandler) property);
|
||||||
try {
|
try {
|
||||||
Object result = child.getGetter().invoke(element);
|
Object result = child.getGetter().invoke(element);
|
||||||
getProperties(result, child);
|
storePropertyData(result, child);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
@ -184,7 +201,7 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
|
||||||
E newInstance = (E) rootHandler.getType().getDeclaredConstructor().newInstance();
|
E newInstance = (E) rootHandler.getType().getDeclaredConstructor().newInstance();
|
||||||
|
|
||||||
// set the data
|
// set the data
|
||||||
setProperties(newInstance, (CompoundTypeHandler) rootHandler);
|
copyDataIntoNewObjects(newInstance, (CompoundTypeHandler) rootHandler);
|
||||||
|
|
||||||
return newInstance;
|
return newInstance;
|
||||||
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
|
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
|
||||||
|
|
@ -193,7 +210,10 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setProperties(Object element, CompoundTypeHandler compoundType) {
|
/*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private void copyDataIntoNewObjects(Object element, CompoundTypeHandler compoundType) {
|
||||||
compoundType.getProperties().forEach(property -> {
|
compoundType.getProperties().forEach(property -> {
|
||||||
if (property instanceof BuiltinTypeHandler) {
|
if (property instanceof BuiltinTypeHandler) {
|
||||||
BuiltinTypeHandler<?> type = ((BuiltinTypeHandler<?>) property);
|
BuiltinTypeHandler<?> type = ((BuiltinTypeHandler<?>) property);
|
||||||
|
|
@ -208,7 +228,7 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
|
||||||
p.getSetter().invokeWithArguments(element, newInstance);
|
p.getSetter().invokeWithArguments(element, newInstance);
|
||||||
|
|
||||||
// recurse down
|
// recurse down
|
||||||
setProperties(newInstance, p);
|
copyDataIntoNewObjects(newInstance, p);
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|
@ -231,16 +251,37 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
|
||||||
return new ValueIterator();
|
return new ValueIterator();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Iterator<Property> propertyIterator() {
|
||||||
|
return new PropertyIterator();
|
||||||
|
}
|
||||||
|
|
||||||
|
static class Property {
|
||||||
|
String name;
|
||||||
|
String value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static class PropertyIterator implements Iterator<Property> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Property next() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return a list of types in the Object(graph). So the element type and all (nested) properties
|
* @return a list of types in the Object(graph). So the element type and all (nested) properties
|
||||||
*/
|
*/
|
||||||
public List<Class<?>> getTypes() {
|
List<Class<?>> getTypes() {
|
||||||
final List<Class<?>> types = new ArrayList<>();
|
final List<Class<?>> types = new ArrayList<>();
|
||||||
getTypes(rootHandler, types);
|
getTypes(rootHandler, types);
|
||||||
return types;
|
return types;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void getTypes(TypeHandler handler, List<Class<?>> types) {
|
private void getTypes(TypeHandler handler, List<Class<?>> types) {
|
||||||
if (handler instanceof BuiltinTypeHandler<?>) {
|
if (handler instanceof BuiltinTypeHandler<?>) {
|
||||||
types.add(handler.getType());
|
types.add(handler.getType());
|
||||||
|
|
@ -251,6 +292,62 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<String> getPropertyNames() {
|
||||||
|
return new ArrayList<>(this.propertyNames.keySet());//TODO should be SET!
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* walk the tree of typehandlers to find the names
|
||||||
|
* adds an index to know what index a property has
|
||||||
|
* this in turn is needed to find where the data of the property is in the byte array
|
||||||
|
*
|
||||||
|
* could also store property data indices, but that would incur more memory overhead
|
||||||
|
* the way it is now, we have to iterate all properties in an element. ie. a tradeoff
|
||||||
|
*/
|
||||||
|
private Map<String, Integer> findPropertyNames() {
|
||||||
|
// no name for the root property
|
||||||
|
final Map<String, Integer> names = new HashMap<>();
|
||||||
|
if (rootHandler instanceof CompoundTypeHandler) {
|
||||||
|
((CompoundTypeHandler) rootHandler).getProperties()
|
||||||
|
.forEach(propertyHandler -> findPropertyNames(propertyHandler, names, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.unmodifiableMap(names);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TODO
|
||||||
|
* // oopsie: the properties are not guaranteed to be unique
|
||||||
|
*/
|
||||||
|
private void findPropertyNames(TypeHandler handler, Map<String, Integer> names, int index) {
|
||||||
|
if (handler instanceof BuiltinTypeHandler<?>) {
|
||||||
|
names.put(handler.getName(), index);
|
||||||
|
} else {
|
||||||
|
names.put(handler.getName(), index);
|
||||||
|
for (TypeHandler propertyHandler : ((CompoundTypeHandler) handler).getProperties()) {
|
||||||
|
findPropertyNames(propertyHandler, names, index++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gets a named property of element at index
|
||||||
|
*
|
||||||
|
* @param index elementIndex
|
||||||
|
* @param propertyName the name of the property
|
||||||
|
* @return the property value
|
||||||
|
*/
|
||||||
|
public Object getValue(int index, String propertyName) {
|
||||||
|
if (rootHandler.isBuiltin() || propertyName == null) {
|
||||||
|
data.position(elementIndices[index]);
|
||||||
|
return ValueReader.read(data);
|
||||||
|
} else {
|
||||||
|
return null; //TODO implement
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
List<BuiltinTypeHandler<?>> getBuiltinTypeHandlers() {
|
List<BuiltinTypeHandler<?>> getBuiltinTypeHandlers() {
|
||||||
final List<BuiltinTypeHandler<?>> types = new ArrayList<>();
|
final List<BuiltinTypeHandler<?>> types = new ArrayList<>();
|
||||||
getStoredTypes(rootHandler, types);
|
getStoredTypes(rootHandler, types);
|
||||||
|
|
@ -307,6 +404,10 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isSimpleElementType() {
|
||||||
|
return PropertyHandlerFactory.isBuiltInType(rootHandler.getType());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows 'iterating insertion of data'. Returns an iterator of Setter
|
* Allows 'iterating insertion of data'. Returns an iterator of Setter
|
||||||
* Does not work for compound types yet
|
* Does not work for compound types yet
|
||||||
|
|
@ -334,8 +435,6 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO proper naming
|
|
||||||
// BTW do we even need this as a class??
|
|
||||||
public class SetterIterator implements Iterator<Setter> {
|
public class SetterIterator implements Iterator<Setter> {
|
||||||
private final List<Setter> properties = new ArrayList<>();
|
private final List<Setter> properties = new ArrayList<>();
|
||||||
private Iterator<Setter> currentSetterIterator;
|
private Iterator<Setter> currentSetterIterator;
|
||||||
|
|
@ -397,12 +496,6 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return size == 0;
|
return size == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Iterator<E> iterator() {
|
|
||||||
return new ElementIterator<>();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object[] toArray() {
|
public Object[] toArray() {
|
||||||
Object[] objects = new Object[size];
|
Object[] objects = new Object[size];
|
||||||
|
|
@ -424,16 +517,24 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
|
||||||
return ts;
|
return ts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Standard Iterator that conforms to the protocol of java.util.List.
|
||||||
|
* Although it's convenient to use, it's not the best way to read from the list because it
|
||||||
|
* needs the Reflection API to instantiate new objects of the element type.
|
||||||
|
* <p/>.
|
||||||
|
* @return An Iterator over the elements in the List
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Iterator<E> iterator() {
|
||||||
|
return new StandardElementIterator<>();
|
||||||
|
}
|
||||||
|
|
||||||
class ElementIterator<F> implements Iterator<F> {
|
/*
|
||||||
|
* Iterator used by the standard Iterator() method
|
||||||
|
*/
|
||||||
|
class StandardElementIterator<F> implements Iterator<F> {
|
||||||
|
|
||||||
private int curIndex = 0;
|
private int curIndex = 0;
|
||||||
private final int originalSize;
|
|
||||||
|
|
||||||
ElementIterator() {
|
|
||||||
this.originalSize = size;
|
|
||||||
data.position(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasNext() {
|
public boolean hasNext() {
|
||||||
|
|
@ -470,12 +571,6 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// to be called by framework to force element count
|
|
||||||
// used by SetterIterator
|
|
||||||
void extend() {
|
|
||||||
size += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void storeLong(Long value) {
|
void storeLong(Long value) {
|
||||||
if (value == null) {
|
if (value == null) {
|
||||||
store0();
|
store0();
|
||||||
|
|
@ -534,6 +629,12 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// to be called by framework to force element count
|
||||||
|
// used by SetterIterator
|
||||||
|
void extend() {
|
||||||
|
size += 1;
|
||||||
|
}
|
||||||
|
|
||||||
byte[] getData() {
|
byte[] getData() {
|
||||||
return Arrays.copyOfRange(data.array(), 0, currentElementValueIndex);
|
return Arrays.copyOfRange(data.array(), 0, currentElementValueIndex);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ final class PropertyHandlerFactory {
|
||||||
//LocalDate/time
|
//LocalDate/time
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isKnownType(Class<?> type) {
|
public static boolean isBuiltInType(Class<?> type) {
|
||||||
return TYPE_HANDLERS.containsKey(type);
|
return TYPE_HANDLERS.containsKey(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,8 @@ public abstract class TypeHandler {
|
||||||
this.setter = setter;
|
this.setter = setter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public abstract boolean isBuiltin();
|
||||||
|
|
||||||
void setGetter(MethodHandle getter) {
|
void setGetter(MethodHandle getter) {
|
||||||
this.getter = getter;
|
this.getter = getter;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -217,7 +217,7 @@ public class ContiguousListTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetStoredTypesDeepCompound() {
|
public void testGetStoredTypesDeepCompound() {
|
||||||
ContiguousList<DeepBean> beans = new ContiguousList<>(DeepBean.class);
|
final ContiguousList<DeepBean> beans = new ContiguousList<>(DeepBean.class);
|
||||||
Iterator<Class<?>> typeIterator = beans.getTypes().iterator();
|
Iterator<Class<?>> typeIterator = beans.getTypes().iterator();
|
||||||
assertTrue(typeIterator.hasNext());
|
assertTrue(typeIterator.hasNext());
|
||||||
assertEquals(DeepBean.class, typeIterator.next());
|
assertEquals(DeepBean.class, typeIterator.next());
|
||||||
|
|
@ -256,4 +256,27 @@ public class ContiguousListTest {
|
||||||
assertEquals(Integer.class, typeIterator.next());
|
assertEquals(Integer.class, typeIterator.next());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetPropertyNamesForBuiltinElementType(){
|
||||||
|
ContiguousList<Integer> integers = new ContiguousList<>(Integer.class);
|
||||||
|
assertTrue(integers.getPropertyNames().isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetPropertyNames(){
|
||||||
|
ContiguousList<IntBean> integers = new ContiguousList<>(IntBean.class);
|
||||||
|
assertFalse(integers.getPropertyNames().isEmpty());
|
||||||
|
assertEquals("value", integers.getPropertyNames().get(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetMorePropertyNames(){
|
||||||
|
ContiguousList<NestedBean> integers = new ContiguousList<>(NestedBean.class);
|
||||||
|
assertFalse(integers.getPropertyNames().isEmpty());
|
||||||
|
assertEquals("stringBean", integers.getPropertyNames().get(0));
|
||||||
|
assertEquals("name", integers.getPropertyNames().get(1));
|
||||||
|
assertEquals("intBean", integers.getPropertyNames().get(2));
|
||||||
|
assertEquals("value", integers.getPropertyNames().get(3));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue