package org.mapdb.serializer;
import org.jetbrains.annotations.NotNull;
import org.mapdb.DB;
import org.mapdb.DataInput2;
import org.mapdb.DataOutput2;
import org.mapdb.Serializer;
import java.io.IOException;
import java.lang.reflect.Array;
/**
* Serializes an object array of non-primitive objects.
* This serializer takes two parameters:
*
* - serializer used for each component
*
* - componentType is class used to instantiate arrays. Generics are erased at runtime,
* this class controls what type of array will be instantiated.
* See {@link java.lang.reflect.Array#newInstance(Class, int)}
*
*/
public class SerializerArray<T> extends GroupSerializerObjectArray<T[]> implements DB.DBAware {
private static final long serialVersionUID = -982394293898234253L;
protected Serializer<T> serializer;
protected final Class<T> componentType;
public SerializerArray(){
this.serializer = null;
this.componentType = (Class<T>)Object.class;
}
/**
* Wraps given serializer and produces Object[] serializer.
* To produce array with different component type, specify extra class.
*/
public SerializerArray(Serializer<T> serializer) {
this(serializer, null);
}
/**
* Wraps given serializer and produces array serializer.
*
* @param serializer
* @param componentType type of array which will be created on deserialization
*/
public SerializerArray(Serializer<T> serializer, Class<T> componentType) {
if (serializer == null)
throw new NullPointerException("null serializer");
this.serializer = serializer;
this.componentType = componentType!=null
? componentType
: (Class<T>)Object.class;
}
// /** used for deserialization */
// @SuppressWarnings("unchecked")
// protected Array(SerializerBase serializerBase, DataInput2 is, SerializerBase.FastArrayList<Object> objectStack) throws IOException {
// objectStack.add(this);
// this.serializer = (Serializer<T>) serializerBase.deserialize(is,objectStack);
// }
@Override
public void serialize(DataOutput2 out, T[] value) throws IOException {
out.packInt(value.length);
for (T a : value) {
serializer.serialize(out, a);
}
}
@Override
public T[] deserialize(DataInput2 in, int available) throws IOException {
int size = in.unpackInt();
T[] ret = (T[]) Array.newInstance(componentType, size);
for (int i = 0; i < size; i++) {
ret[i] = serializer.deserialize(in, -1);
}
return ret;
}
@Override
public boolean isTrusted() {
return serializer.isTrusted();
}
@Override
public boolean equals(T[] a1, T[] a2) {
if (a1 == a2)
return true;
if (a1 == null || a1.length != a2.length)
return false;
for (int i = 0; i < a1.length; i++) {
if (!serializer.equals(a1[i], a2[i]))
return false;
}
return true;
}
@Override
public int hashCode(T[] objects, int seed) {
seed += objects.length;
for (T a : objects) {
seed = (-1640531527) * seed + serializer.hashCode(a, seed);
}
return seed;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
return serializer.equals(((SerializerArray<?>) o).serializer);
}
@Override
public int hashCode() {
return serializer.hashCode();
}
@Override
public int compare(Object[] o1, Object[] o2) {
int len = Math.min(o1.length, o2.length);
int r;
for (int i = 0; i < len; i++) {
Object a1 = o1[i];
Object a2 = o2[i];
if (a1 == a2) { //this case handles both nulls
r = 0;
} else if (a1 == null) {
r = 1; //null is positive infinity, always greater than anything else
} else if (a2 == null) {
r = -1;
} else {
r = serializer.compare((T) a1, (T) a2);
;
}
if (r != 0)
return r;
}
return SerializerUtils.compareInt(o1.length, o2.length);
}
@Override
public void callbackDB(@NotNull DB db) {
if(this.serializer==null)
this.serializer = (Serializer<T>) db.getDefaultSerializer();
}
}