package org.mapdb.tuple;
import org.jetbrains.annotations.NotNull;
import org.mapdb.DB;
import org.mapdb.DataInput2;
import org.mapdb.DataOutput2;
import org.mapdb.Serializer;
import org.mapdb.serializer.GroupSerializerObjectArray;
import java.io.IOException;
import java.io.Serializable;
import java.util.Comparator;
import static org.mapdb.tuple.Tuple.compare2;
import static org.mapdb.tuple.Tuple.hiIfNull;
/**
* Applies delta compression on array of tuple. First, second and third tuple value may be shared between consequential tuples,
* so only first occurrence is serialized. An example:
*
* <pre>
* Value Serialized as
* ----------------------------------
* Tuple(1, 2, 1, 1) 1, 2, 1, 1
* Tuple(1, 2, 1, 2) 2
* Tuple(1, 3, 3, 3) 3, 3, 3
* Tuple(1, 3, 4, 4) 4, 4
* </pre>
*
* @param <A> first tuple value
* @param <B> second tuple value
* @param <C> third tuple value
*/
public class Tuple6Serializer<A,B,C,D,E,F> extends GroupSerializerObjectArray<Tuple6<A,B,C,D,E,F>>
implements Serializable, DB.DBAware {
private static final long serialVersionUID = 3666600849149868404L;
protected Comparator<A> aComparator;
protected Comparator<B> bComparator;
protected Comparator<C> cComparator;
protected Comparator<D> dComparator;
protected Comparator<E> eComparator;
protected Comparator<F> fComparator;
protected Serializer<A> aSerializer;
protected Serializer<B> bSerializer;
protected Serializer<C> cSerializer;
protected Serializer<D> dSerializer;
protected Serializer<E> eSerializer;
protected Serializer<F> fSerializer;
public Tuple6Serializer(){
this(null, null, null, null, null, null, null, null, null, null, null, null);
}
public Tuple6Serializer(Serializer serializer){
this(serializer, serializer, serializer, serializer, serializer, serializer);
}
public Tuple6Serializer(
Serializer<A> aSerializer, Serializer<B> bSerializer, Serializer<C> cSerializer, Serializer<D> dSerializer, Serializer<E> eSerializer,Serializer<F> fSerializer){
this(
aSerializer, bSerializer, cSerializer, dSerializer, eSerializer, fSerializer,
aSerializer, bSerializer, cSerializer, dSerializer, eSerializer, fSerializer
);
}
/**
* Construct new TupleSerializer. You may pass null for some value,
* In that case 'default' value will be used, Comparable comparator and Default Serializer from DB.
*
*/
public Tuple6Serializer(
Serializer<A> aSerializer, Serializer<B> bSerializer, Serializer<C> cSerializer, Serializer<D> dSerializer, Serializer<E> eSerializer,Serializer<F> fSerializer,
Comparator<A> aComparator, Comparator<B> bComparator, Comparator<C> cComparator, Comparator<D> dComparator,Comparator<E> eComparator,Comparator<F> fComparator){
this.aComparator = aComparator;
this.bComparator = bComparator;
this.cComparator = cComparator;
this.dComparator = dComparator;
this.eComparator = eComparator;
this.fComparator = fComparator;
this.aSerializer = aSerializer;
this.bSerializer = bSerializer;
this.cSerializer = cSerializer;
this.dSerializer = dSerializer;
this.eSerializer = eSerializer;
this.fSerializer = fSerializer;
}
@Override
public void valueArraySerialize(DataOutput2 out, Object vals) throws IOException {
Object[] keys = (Object[]) vals;
int end = keys.length;
int acount=0;
int bcount=0;
int ccount=0;
int dcount=0;
int ecount=0;
for(int i=0;i<end;i++){
Tuple6<A,B,C,D,E,F> t = (Tuple6<A, B,C,D,E,F>) keys[i];
if(acount==0){
//write new A
aSerializer.serialize(out,t.a);
//count how many A are following
acount=1;
while(i+acount<end && aComparator.compare(t.a, ((Tuple6<A, B, C,D, E,F>) keys[i+acount]).a)==0){
acount++;
}
out.packInt(acount);
}
if(bcount==0){
//write new B
bSerializer.serialize(out,t.b);
//count how many B are following
bcount=1;
while(i+bcount<end && bComparator.compare(t.b, ((Tuple6<A, B,C,D, E,F>) keys[i+bcount]).b)==0){
bcount++;
}
out.packInt(bcount);
}
if(ccount==0){
//write new C
cSerializer.serialize(out,t.c);
//count how many C are following
ccount=1;
while(i+ccount<end && cComparator.compare(t.c, ((Tuple6<A, B,C,D, E,F>) keys[i+ccount]).c)==0){
ccount++;
}
out.packInt(ccount);
}
if(dcount==0){
//write new C
dSerializer.serialize(out,t.d);
//count how many D are following
dcount=1;
while(i+dcount<end && dComparator.compare(t.d, ((Tuple6<A, B,C,D,E,F>) keys[i+dcount]).d)==0){
dcount++;
}
out.packInt(dcount);
}
if(ecount==0){
//write new C
eSerializer.serialize(out,t.e);
//count how many E are following
ecount=1;
while(i+ecount<end && eComparator.compare(t.e, ((Tuple6<A, B,C,D,E,F>) keys[i+ecount]).e)==0){
ecount++;
}
out.packInt(ecount);
}
fSerializer.serialize(out,t.f);
acount--;
bcount--;
ccount--;
dcount--;
ecount--;
}
}
@Override
public Object[] valueArrayDeserialize(DataInput2 in, int size) throws IOException {
Object[] ret = new Object[size];
A a = null;
int acount = 0;
B b = null;
int bcount = 0;
C c = null;
int ccount = 0;
D d = null;
int dcount = 0;
E e = null;
int ecount = 0;
for(int i=0;i<size;i++){
if(acount==0){
//read new A
a = aSerializer.deserialize(in,-1);
acount = in.unpackInt();
}
if(bcount==0){
//read new B
b = bSerializer.deserialize(in,-1);
bcount = in.unpackInt();
}
if(ccount==0){
//read new C
c = cSerializer.deserialize(in,-1);
ccount = in.unpackInt();
}
if(dcount==0){
//read new D
d = dSerializer.deserialize(in,-1);
dcount = in.unpackInt();
}
if(ecount==0){
//read new E
e = eSerializer.deserialize(in,-1);
ecount = in.unpackInt();
}
F f = fSerializer.deserialize(in,-1);
ret[i]= Tuple.t6(a, b, c, d, e, f);
acount--;
bcount--;
ccount--;
dcount--;
ecount--;
}
assert(acount==0);
assert(bcount==0);
assert(ccount==0);
assert(dcount==0);
assert(ecount==0);
return ret;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Tuple6Serializer t = (Tuple6Serializer) o;
return
Tuple.eq(aComparator, t.aComparator) &&
Tuple.eq(bComparator, t.bComparator) &&
Tuple.eq(cComparator, t.cComparator) &&
Tuple.eq(dComparator, t.dComparator) &&
Tuple.eq(eComparator, t.eComparator) &&
Tuple.eq(aSerializer, t.aSerializer) &&
Tuple.eq(bSerializer, t.bSerializer) &&
Tuple.eq(cSerializer, t.cSerializer) &&
Tuple.eq(dSerializer, t.dSerializer) &&
Tuple.eq(eSerializer, t.eSerializer) &&
Tuple.eq(fSerializer, t.fSerializer);
}
@Override
public int hashCode() {
int result = aComparator != null ? aComparator.hashCode() : 0;
result = -1640531527 * result + (bComparator != null ? bComparator.hashCode() : 0);
result = -1640531527 * result + (cComparator != null ? cComparator.hashCode() : 0);
result = -1640531527 * result + (dComparator != null ? dComparator.hashCode() : 0);
result = -1640531527 * result + (eComparator != null ? eComparator.hashCode() : 0);
result = -1640531527 * result + (aSerializer != null ? aSerializer.hashCode() : 0);
result = -1640531527 * result + (bSerializer != null ? bSerializer.hashCode() : 0);
result = -1640531527 * result + (cSerializer != null ? cSerializer.hashCode() : 0);
result = -1640531527 * result + (dSerializer != null ? dSerializer.hashCode() : 0);
result = -1640531527 * result + (eSerializer != null ? eSerializer.hashCode() : 0);
result = -1640531527 * result + (fSerializer != null ? fSerializer.hashCode() : 0);
return result;
}
@Override
public void serialize(@NotNull DataOutput2 out, @NotNull Tuple6<A, B, C, D, E, F> value) throws IOException {
aSerializer.serialize(out, value.a);
bSerializer.serialize(out, value.b);
cSerializer.serialize(out, value.c);
dSerializer.serialize(out, value.d);
eSerializer.serialize(out, value.e);
fSerializer.serialize(out, value.f);
}
@Override
public Tuple6<A, B, C, D, E, F> deserialize(@NotNull DataInput2 input, int available) throws IOException {
return new Tuple6(
aSerializer.deserialize(input, -1),
bSerializer.deserialize(input, -1),
cSerializer.deserialize(input, -1),
dSerializer.deserialize(input, -1),
eSerializer.deserialize(input, -1),
fSerializer.deserialize(input, -1)
);
}
@Override
public int compare(final Tuple6<A,B,C,D,E,F> o1, final Tuple6<A,B,C,D,E,F> o2) {
int i = compare2(aComparator,o1.a, o2.a);
if (i != 0) return i;
i = compare2(bComparator,o1.b, o2.b);
if (i != 0) return i;
i = compare2(cComparator,o1.c, o2.c);
if (i != 0) return i;
i = compare2(dComparator,o1.d, o2.d);
if (i != 0) return i;
i = compare2(eComparator,o1.e, o2.e);
if (i != 0) return i;
return compare2(fComparator,o1.f, o2.f);
}
@Override
public boolean equals(Tuple6<A, B, C, D, E, F> first, Tuple6<A, B, C, D, E, F> second) {
return 0==compare(first, second);
}
@Override
public int hashCode(@NotNull Tuple6<A, B, C, D, E, F> o, int seed) {
seed = -1640531527 * seed + aSerializer.hashCode(o.a, seed);
seed = -1640531527 * seed + bSerializer.hashCode(o.b, seed);
seed = -1640531527 * seed + cSerializer.hashCode(o.c, seed);
seed = -1640531527 * seed + dSerializer.hashCode(o.d, seed);
seed = -1640531527 * seed + eSerializer.hashCode(o.e, seed);
seed = -1640531527 * seed + fSerializer.hashCode(o.f, seed);
return seed;
}
@Override
public void callbackDB(@NotNull DB db) {
if(aComparator==null) aComparator = (Comparator<A>) db.getDefaultSerializer();
if(bComparator==null) bComparator = (Comparator<B>) db.getDefaultSerializer();
if(cComparator==null) cComparator = (Comparator<C>) db.getDefaultSerializer();
if(dComparator==null) dComparator = (Comparator<D>) db.getDefaultSerializer();
if(eComparator==null) eComparator = (Comparator<E>) db.getDefaultSerializer();
if(fComparator==null) fComparator = (Comparator<F>) db.getDefaultSerializer();
if(aSerializer==null) aSerializer = (Serializer<A>) db.getDefaultSerializer();
if(bSerializer==null) bSerializer = (Serializer<B>) db.getDefaultSerializer();
if(cSerializer==null) cSerializer = (Serializer<C>) db.getDefaultSerializer();
if(dSerializer==null) dSerializer = (Serializer<D>) db.getDefaultSerializer();
if(eSerializer==null) eSerializer = (Serializer<E>) db.getDefaultSerializer();
if(fSerializer==null) fSerializer = (Serializer<F>) db.getDefaultSerializer();
}
@Override
public Tuple6<A, B, C, D, E, F> nextValue(Tuple6<A, B, C, D, E, F> v) {
return new Tuple6(hiIfNull(v.a), hiIfNull(v.b), hiIfNull(v.c), hiIfNull(v.d), hiIfNull(v.e), hiIfNull(v.f));
}
}