json output directly from the list...may not remain there

This commit is contained in:
Shautvast 2023-05-31 09:09:53 +02:00
parent db33d0fac8
commit dd6b9c2281
8 changed files with 127 additions and 223 deletions

View file

@ -1,33 +1,28 @@
package nl.sanderhautvast.contiguous; package nl.sanderhautvast.contiguous;
import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.SerializerProvider; import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer; import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
public class ListSerializer<E> extends StdSerializer<ContiguousList> { public class ListSerializer<E> extends StdSerializer<ContiguousList<?>> {
@SuppressWarnings("unchecked")
public ListSerializer() { public ListSerializer() {
super(ContiguousList.class); super((Class) ContiguousList.class); // ?
} }
@Override @Override
public void serialize( public void serialize(
ContiguousList clist, JsonGenerator generator, SerializerProvider provider) ContiguousList<?> clist, JsonGenerator generator, SerializerProvider provider)
throws IOException, JsonProcessingException { throws IOException {
generator.writeStartArray(); generator.writeStartArray();
if (clist.isSimpleElementType()){ Iterator<String> jsons = clist.jsonIterator();
Iterator<?> iterator = clist.valueIterator(); while (jsons.hasNext()) {
while (iterator.hasNext()){ generator.writeRawValue(jsons.next());
generator.writeString(iterator.next().toString());
}
} else {
} }
generator.writeEndArray(); generator.writeEndArray();

View file

@ -3,7 +3,6 @@ package nl.sanderhautvast.contiguous;
import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.module.SimpleModule;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -45,9 +44,9 @@ class ListSerializerTest {
String json = mapper.writeValueAsString(strings); String json = mapper.writeValueAsString(strings);
assertEquals("[{\"name\":\"Vogon constructor fleet\"}," + assertEquals("[{\"name\": \"Vogon constructor fleet\"}," +
"{\"name\":\"Restaurant at the end of the Galaxy\"}," + "{\"name\": \"Restaurant at the end of the Galaxy\"}," +
"{\"name\":\"Publishing houses of Ursa Minor\"}]", "{\"name\": \"Publishing houses of Ursa Minor\"}]",
json); json);
} }
} }

View file

@ -57,7 +57,7 @@ public class JdbcResults {
} }
next.set(fieldValue); next.set(fieldValue);
} }
setterIterator.nextRecord(); setterIterator.finishObject();
} }
} }
@ -69,7 +69,6 @@ public class JdbcResults {
* @throws SQLException when db throws error.. * @throws SQLException when db throws error..
*/ */
public static <E> ContiguousList<E> toList(ResultSet result, Class<E> elementType) throws SQLException { public static <E> ContiguousList<E> toList(ResultSet result, Class<E> elementType) throws SQLException {
ContiguousList<E> list = new ContiguousList<>(elementType);
return toList(result, elementType, Function.identity()); return toList(result, elementType, Function.identity());
} }

View file

@ -24,18 +24,13 @@ 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);
} }
void storeValue(Object value, ContiguousList<?> contiguousList) { void storeValue(Object value, ContiguousList<?> contiguousList) {
store((T)value, contiguousList); store((T) value, contiguousList);
} }
private T getValue(Object propertyValue) { private T getValue(Object propertyValue) {

View file

@ -6,7 +6,9 @@ import java.util.*;
class CompoundTypeHandler extends TypeHandler { class CompoundTypeHandler extends TypeHandler {
private final Map<String, TypeHandler> properties = new LinkedHashMap<>(); private final Map<String, TypeHandler> properties = new LinkedHashMap<>();
CompoundTypeHandler(Class<?> type) {
super(type, null,null, null);
}
CompoundTypeHandler(Class<?> type, String propertyName) { CompoundTypeHandler(Class<?> type, String propertyName) {
super(type, propertyName, null,null); super(type, propertyName, null,null);
@ -24,10 +26,4 @@ class CompoundTypeHandler extends TypeHandler {
void addChild(Field property, CompoundTypeHandler childCompoundType) { void addChild(Field property, CompoundTypeHandler childCompoundType) {
this.properties.put(property.getName(), childCompoundType); this.properties.put(property.getName(), childCompoundType);
} }
@Override
public boolean isBuiltin() {
return false;
}
} }

View file

@ -58,7 +58,7 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
*/ */
private ByteBuffer data = ByteBuffer.allocate(32); private ByteBuffer data = ByteBuffer.allocate(32);
private int currentElementValueIndex; private int bufferPosition;
private int[] elementIndices = new int[10]; // avoids autoboxing. Could also use standard ArrayList though private int[] elementIndices = new int[10]; // avoids autoboxing. Could also use standard ArrayList though
// is there a standard lib IntList?? // is there a standard lib IntList??
@ -67,12 +67,9 @@ 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] = 0; // index of first element elementIndices[0] = 0; // index of first element
propertyNames = findPropertyNames();
} }
public Class<?> getElementType() { public Class<?> getElementType() {
@ -87,14 +84,14 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
* The advantage of the current implementation is that the binary data is not aware of the actual * The advantage of the current implementation is that the binary data is not aware of the actual
* 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<?> elementClass) {
if (PropertyHandlerFactory.isBuiltInType(type)) { if (PropertyHandlerFactory.isBuiltInType(elementClass)) {
this.rootHandler = PropertyHandlerFactory.forType(type); this.rootHandler = PropertyHandlerFactory.forType(elementClass);
} else { } else {
CompoundTypeHandler compoundType = new CompoundTypeHandler(type, null);//TODO revisit CompoundTypeHandler compoundType = new CompoundTypeHandler(elementClass);
this.rootHandler = compoundType; this.rootHandler = compoundType;
try { try {
addPropertyHandlersForCompoundType(type, compoundType); addPropertyHandlersForCompoundType(elementClass, compoundType);
} catch (IllegalAccessException e) { } catch (IllegalAccessException e) {
throw new IllegalStateException(e); throw new IllegalStateException(e);
} }
@ -114,7 +111,8 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
MethodHandle setter = lookup.findSetter(type, field.getName(), fieldType); MethodHandle setter = lookup.findSetter(type, field.getName(), fieldType);
if (PropertyHandlerFactory.isBuiltInType(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);
} else { } else {
@ -144,7 +142,7 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
if (elementIndices.length < size + 1) { if (elementIndices.length < size + 1) {
this.elementIndices = Arrays.copyOf(this.elementIndices, this.elementIndices.length * 2); this.elementIndices = Arrays.copyOf(this.elementIndices, this.elementIndices.length * 2);
} }
elementIndices[size] = currentElementValueIndex; elementIndices[size] = bufferPosition;
return true; return true;
} }
@ -201,7 +199,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
copyDataIntoNewObjects(newInstance, (CompoundTypeHandler) rootHandler); copyDataIntoNewObject(newInstance, (CompoundTypeHandler) rootHandler);
return newInstance; return newInstance;
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | } catch (NoSuchMethodException | InstantiationException | IllegalAccessException |
@ -213,7 +211,7 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
/* /*
* *
*/ */
private void copyDataIntoNewObjects(Object element, CompoundTypeHandler compoundType) { private void copyDataIntoNewObject(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);
@ -228,7 +226,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
copyDataIntoNewObjects(newInstance, p); copyDataIntoNewObject(newInstance, p);
} catch (Throwable e) { } catch (Throwable e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
@ -251,103 +249,87 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
return new ValueIterator(); return new ValueIterator();
} }
public Iterator<Property> propertyIterator() { public Iterator<String> jsonIterator() {
return new PropertyIterator(); return new JsonIterator();
} }
static class Property { class JsonIterator implements Iterator<String> {
String name;
String value;
}
static class PropertyIterator implements Iterator<Property> { private int index;
@Override @Override
public boolean hasNext() { public boolean hasNext() {
return false; return index < size;
} }
@Override @Override
public Property next() { public String next() {
return null; return getAsJson(index++);
} }
} }
/** /**
* @return a list of types in the Object(graph). So the element type and all (nested) properties * For now the simplest thing I can think of to get this to work
*/
List<Class<?>> getTypes() {
final List<Class<?>> types = new ArrayList<>();
getTypes(rootHandler, types);
return types;
}
private void getTypes(TypeHandler handler, List<Class<?>> types) {
if (handler instanceof BuiltinTypeHandler<?>) {
types.add(handler.getType());
} else {
types.add(handler.getType());
((CompoundTypeHandler) handler).getProperties()
.forEach(propertyHandler -> getTypes(propertyHandler, types));
}
}
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 * @param index
* the way it is now, we have to iterate all properties in an element. ie. a tradeoff * @return
*/ */
private Map<String, Integer> findPropertyNames() { public String getAsJson(int index) {
// no name for the root property if (index < 0 || index >= size) {
final Map<String, Integer> names = new HashMap<>(); throw new IndexOutOfBoundsException("index <0 or >" + size);
if (rootHandler instanceof CompoundTypeHandler) {
((CompoundTypeHandler) rootHandler).getProperties()
.forEach(propertyHandler -> findPropertyNames(propertyHandler, names, 0));
} }
data.position(elementIndices[index]);
if (rootHandler instanceof BuiltinTypeHandler<?>) {
BuiltinTypeHandler<?> handler = (BuiltinTypeHandler<?>) rootHandler;
return getValue(handler);
}
// create a new instance of the list element type
StringBuilder s = new StringBuilder();
s.append("{");
copyDataIntoStringBuilder(s, (CompoundTypeHandler) rootHandler);
s.append("}");
return s.toString();
return Collections.unmodifiableMap(names);
} }
private String getValue(BuiltinTypeHandler<?> handler) {
Object read = ValueReader.read(data);
String out = handler.cast(read).toString();
if (handler instanceof StringHandler) {
out = quote(out);
}
return out;
}
private static String quote(String out) {
StringBuilder s = new StringBuilder();
out = s.append("\"").append(out).append("\"").toString();
return out;
}
/* /*
* TODO *
* // oopsie: the properties are not guaranteed to be unique
*/ */
private void findPropertyNames(TypeHandler handler, Map<String, Integer> names, int index) { private void copyDataIntoStringBuilder(StringBuilder s, CompoundTypeHandler compoundType) {
if (handler instanceof BuiltinTypeHandler<?>) { compoundType.getProperties().forEach(property -> {
names.put(handler.getName(), index); if (property instanceof BuiltinTypeHandler) {
} else { BuiltinTypeHandler<?> typeHandler = (BuiltinTypeHandler<?>) property;
names.put(handler.getName(), index); String name = typeHandler.getName();
for (TypeHandler propertyHandler : ((CompoundTypeHandler) handler).getProperties()) { String value = getValue(typeHandler);
findPropertyNames(propertyHandler, names, index++); s.append(quote(name)).append(": ").append(value);
} else {
CompoundTypeHandler p = (CompoundTypeHandler) property;
s.append(p.getName()).append(":{");
// recurse down
copyDataIntoStringBuilder(s, p);
s.append("}");
} }
} s.append(", ");
});
s.setLength(s.length() - 2);
} }
/**
* 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);
@ -404,15 +386,13 @@ 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 // (check if still valid)
* *
* @return A Reusable iterator * @return an Iterator over bean property setters. Once an object is completely written,
* call finishObject, to increase the element count and to continue with the next element.
*/ */
public SetterIterator setterIterator() { public SetterIterator setterIterator() {
return new SetterIterator(); return new SetterIterator();
@ -450,11 +430,7 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
@Override @Override
public boolean hasNext() { public boolean hasNext() {
boolean hasNext = currentSetterIterator.hasNext(); return currentSetterIterator.hasNext();
if (!hasNext) {
extend(); // marks the end of an object
}
return hasNext;
} }
@Override @Override
@ -462,18 +438,15 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
return currentSetterIterator.next(); return currentSetterIterator.next();
} }
public void nextRecord() { /**
* Indicates that writing of the current object is complete, so
* that it will increment the element count and start a new property iterator
* for the next object (or none it was the last).
*/
public void finishObject() {
extend();
currentSetterIterator = properties.iterator(); currentSetterIterator = properties.iterator();
} }
}
/**
* @return an {@link Iterator} over the property values of the specified element in the List.
*/
public Iterator<Object> valueIterator(int index) {
//TODO
return null;
} }
public boolean addAll(Collection<? extends E> collection) { public boolean addAll(Collection<? extends E> collection) {
@ -484,7 +457,7 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
} }
public void clear() { public void clear() {
this.currentElementValueIndex = 0; this.bufferPosition = 0;
this.size = 0; this.size = 0;
} }
@ -496,6 +469,7 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
public boolean isEmpty() { public boolean isEmpty() {
return size == 0; return size == 0;
} }
@Override @Override
public Object[] toArray() { public Object[] toArray() {
Object[] objects = new Object[size]; Object[] objects = new Object[size];
@ -522,6 +496,7 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
* Although it's convenient to use, it's not the best way to read from the list because it * 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. * needs the Reflection API to instantiate new objects of the element type.
* <p/>. * <p/>.
*
* @return An Iterator over the elements in the List * @return An Iterator over the elements in the List
*/ */
@Override @Override
@ -550,15 +525,15 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
private void store(byte[] bytes) { private void store(byte[] bytes) {
ensureFree(bytes.length); ensureFree(bytes.length);
data.position(currentElementValueIndex); // ensures intermittent reads/writes are safe data.position(bufferPosition); // ensures intermittent reads/writes are safe
data.put(bytes); data.put(bytes);
currentElementValueIndex += bytes.length; bufferPosition += bytes.length;
} }
private void store0() { private void store0() {
ensureFree(1); ensureFree(1);
data.put((byte) 0); data.put((byte) 0);
currentElementValueIndex += 1; bufferPosition += 1;
} }
void storeString(String value) { void storeString(String value) {
@ -636,7 +611,7 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
} }
byte[] getData() { byte[] getData() {
return Arrays.copyOfRange(data.array(), 0, currentElementValueIndex); return Arrays.copyOfRange(data.array(), 0, bufferPosition);
} }
int[] getElementIndices() { int[] getElementIndices() {
@ -644,7 +619,7 @@ public class ContiguousList<E> extends NotImplementedList<E> implements List<E>
} }
private void ensureFree(int length) { private void ensureFree(int length) {
while (currentElementValueIndex + length > data.capacity()) { while (bufferPosition + length > data.capacity()) {
byte[] bytes = this.data.array(); byte[] bytes = this.data.array();
this.data = ByteBuffer.allocate(this.data.capacity() * 2); this.data = ByteBuffer.allocate(this.data.capacity() * 2);
this.data.put(bytes); this.data.put(bytes);

View file

@ -14,6 +14,10 @@ public abstract class TypeHandler {
protected MethodHandle getter; // both can be null, if it's for a known ('primitive') type protected MethodHandle getter; // both can be null, if it's for a known ('primitive') type
protected MethodHandle setter; protected MethodHandle setter;
private final Class<?> type; private final Class<?> type;
/**
* full name, prepended by all parent property names
*/
private final String name; private final String name;
public TypeHandler(Class<?> type, String name, MethodHandle getter, MethodHandle setter) { public TypeHandler(Class<?> type, String name, MethodHandle getter, MethodHandle setter) {
@ -23,8 +27,6 @@ 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;
} }

View file

@ -4,7 +4,6 @@ import org.junit.jupiter.api.Test;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
@ -12,7 +11,7 @@ public class ContiguousListTest {
@Test @Test
public void testAddAndGetString() { public void testAddAndGetString() {
List<String> list = new ContiguousList<>(String.class); ContiguousList<String> list = new ContiguousList<>(String.class);
assertTrue(list.isEmpty()); assertTrue(list.isEmpty());
list.add("hitchhikersguide to the galaxy"); list.add("hitchhikersguide to the galaxy");
@ -21,6 +20,9 @@ public class ContiguousListTest {
String title = list.get(0); String title = list.get(0);
assertEquals("hitchhikersguide to the galaxy", title); assertEquals("hitchhikersguide to the galaxy", title);
String titleJson = list.getAsJson(0);
assertEquals("\"hitchhikersguide to the galaxy\"", titleJson);
} }
@Test @Test
@ -33,6 +35,9 @@ public class ContiguousListTest {
StringBean douglas = beanList.get(0); StringBean douglas = beanList.get(0);
assertEquals("Douglas Adams", douglas.getName()); assertEquals("Douglas Adams", douglas.getName());
String douglasJson = beanList.getAsJson(0);
assertEquals("{\"name\": \"Douglas Adams\"}", douglasJson);
// now add new data to see if existing data remains intact // now add new data to see if existing data remains intact
beanList.add(new StringBean("Ford Prefect")); beanList.add(new StringBean("Ford Prefect"));
@ -198,85 +203,23 @@ public class ContiguousListTest {
assertEquals(new IntBean(100), integers.get(100)); // here an instance assertEquals(new IntBean(100), integers.get(100)); // here an instance
} }
@Test @Test
public void testGetTypesWhenCompound() { public void testSetterIterator() {
ContiguousList<NestedBean> integers = new ContiguousList<>(NestedBean.class); ContiguousList<NestedBean> integers = new ContiguousList<>(NestedBean.class);
Iterator<Class<?>> typeIterator = integers.getTypes().iterator(); ContiguousList<NestedBean>.SetterIterator iterator = integers.setterIterator();
assertTrue(typeIterator.hasNext());
assertEquals(NestedBean.class, typeIterator.next());
assertTrue(typeIterator.hasNext());
assertEquals(StringBean.class, typeIterator.next());
assertTrue(typeIterator.hasNext());
assertEquals(String.class, typeIterator.next());
assertTrue(typeIterator.hasNext());
assertEquals(IntBean.class, typeIterator.next());
assertTrue(typeIterator.hasNext());
assertEquals(Integer.class, typeIterator.next());
} if (iterator.hasNext()) {
iterator.next().set("Magrathea");
@Test
public void testGetStoredTypesDeepCompound() {
final ContiguousList<DeepBean> beans = new ContiguousList<>(DeepBean.class);
Iterator<Class<?>> typeIterator = beans.getTypes().iterator();
assertTrue(typeIterator.hasNext());
assertEquals(DeepBean.class, typeIterator.next());
assertTrue(typeIterator.hasNext());
assertEquals(NestedBean.class, typeIterator.next());
assertTrue(typeIterator.hasNext());
assertEquals(StringBean.class, typeIterator.next());
assertTrue(typeIterator.hasNext());
assertEquals(String.class, typeIterator.next());
assertTrue(typeIterator.hasNext());
assertEquals(IntBean.class, typeIterator.next());
assertTrue(typeIterator.hasNext());
assertEquals(Integer.class, typeIterator.next());
assertTrue(typeIterator.hasNext());
assertEquals(Long.class, typeIterator.next());
assertTrue(typeIterator.hasNext());
assertEquals(StringBean.class, typeIterator.next());
assertTrue(typeIterator.hasNext());
assertEquals(String.class, typeIterator.next());
}
@Test
public void testTypeIteratorBuiltin() {
ContiguousList<Integer> integers = new ContiguousList<>(Integer.class);
Iterator<Class<?>> typeIterator = integers.getTypes().iterator();
if (typeIterator.hasNext()) {
assertEquals(Integer.class, typeIterator.next());
} }
} if (iterator.hasNext()) {
iterator.next().set(42);
}
iterator.finishObject();
@Test NestedBean nestedBean = integers.get(0);
public void testGetPropertyNamesForBuiltinElementType(){ assertEquals("Magrathea", nestedBean.getStringBean().getName());
ContiguousList<Integer> integers = new ContiguousList<>(Integer.class); assertEquals(42, nestedBean.getIntBean().getValue());
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));
} }
} }