/*
* ModeShape (http://www.modeshape.org)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.modeshape.jcr.query;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import org.mapdb.Serializer;
import org.modeshape.common.util.ObjectUtil;
import org.modeshape.jcr.query.model.TypeSystem.TypeFactory;
import org.modeshape.jcr.value.ValueFormatException;
import org.modeshape.schematic.internal.HashCode;
/**
* A simple set of classes for working with tuples of data.
*
* @author Randall Hauch (rhauch@redhat.com)
*/
public class Tuples {
private Tuples() {
}
/**
* Create a tuple with the given two values.
*
* @param v1 the first value
* @param v2 the second value
* @return the tuple; never null
*/
public static <T1, T2> Tuple2<T1, T2> tuple( T1 v1,
T2 v2 ) {
return new Tuple2<>(v1, v2);
}
/**
* Create a tuple with the given three values.
*
* @param v1 the first value
* @param v2 the second value
* @param v3 the third value
* @return the tuple; never null
*/
public static <T1, T2, T3> Tuple3<T1, T2, T3> tuple( T1 v1,
T2 v2,
T3 v3 ) {
return new Tuple3<>(v1, v2, v3);
}
/**
* Create a tuple with the given four values.
*
* @param v1 the first value
* @param v2 the second value
* @param v3 the third value
* @param v4 the fourth value
* @return the tuple; never null
*/
public static <T1, T2, T3, T4> Tuple4<T1, T2, T3, T4> tuple( T1 v1,
T2 v2,
T3 v3,
T4 v4 ) {
return new Tuple4<>(v1, v2, v3, v4);
}
/**
* Create a tuple with the given values. Note that this always creates a n-ary tuple, so use {@link #tuple(Object, Object)},
* {@link #tuple(Object, Object, Object)} or {@link #tuple(Object, Object, Object, Object)} for tuples smaller than 5.
*
* @param values the values
* @return the tuple; never null
*/
public static TupleN tuple( Object[] values ) {
return new TupleN(values);
}
/**
* Create a type factory for tuples of size 2.
*
* @param type1 the first type; may not be null
* @param type2 the second type; may not be null
* @return the type factory; never null
*/
public static <T1, T2> TypeFactory<Tuple2<T1, T2>> typeFactory( TypeFactory<T1> type1,
TypeFactory<T2> type2 ) {
return new Tuple2TypeFactory<>(type1, type2);
}
/**
* Create a type factory for tuples of size 3.
*
* @param type1 the first type; may not be null
* @param type2 the second type; may not be null
* @param type3 the third type; may not be null
* @return the type factory; never null
*/
public static <T1, T2, T3> TypeFactory<Tuple3<T1, T2, T3>> typeFactory( TypeFactory<T1> type1,
TypeFactory<T2> type2,
TypeFactory<T3> type3 ) {
return new Tuple3TypeFactory<>(type1, type2, type3);
}
/**
* Create a type factory for tuples of size 4.
*
* @param type1 the first type; may not be null
* @param type2 the second type; may not be null
* @param type3 the third type; may not be null
* @param type4 the fourth type; may not be null
* @return the type factory; never null
*/
public static <T1, T2, T3, T4> TypeFactory<Tuple4<T1, T2, T3, T4>> typeFactory( TypeFactory<T1> type1,
TypeFactory<T2> type2,
TypeFactory<T3> type3,
TypeFactory<T4> type4 ) {
return new Tuple4TypeFactory<>(type1, type2, type3, type4);
}
/**
* Create a type factory for n-ary tuples.
*
* @param types the collection of types for each slot in the tuple
* @return the type factory; never null
*/
public static TypeFactory<?> typeFactory( Collection<TypeFactory<?>> types ) {
return new TupleNTypeFactory(types);
}
/**
* Create a type factory for uniform tuples.
*
* @param type the type of each/every slot in the tuples
* @param tupleSize the size of the tuples
* @return the type factory; never null
*/
public static TypeFactory<?> typeFactory( TypeFactory<?> type,
int tupleSize ) {
if (tupleSize <= 1) return type;
if (tupleSize == 2) return typeFactory(type, type);
if (tupleSize == 3) return typeFactory(type, type, type);
if (tupleSize == 4) return typeFactory(type, type, type, type);
Collection<TypeFactory<?>> types = new ArrayList<>(tupleSize);
for (int i = 0; i != tupleSize; ++i) {
types.add(type);
}
return new TupleNTypeFactory(types);
}
/**
* Create a {@link Serializer} for tuples of size 2.
*
* @param first the serializer for the first slot
* @param second the serializer for the second slot
* @return the serializer; never null
*/
public static <T1, T2> Serializer<Tuple2<T1, T2>> serializer( Serializer<T1> first,
Serializer<T2> second ) {
return new Tuple2Serializer<>(first, second);
}
/**
* Create a {@link Serializer} for tuples of size 3.
*
* @param first the serializer for the first slot
* @param second the serializer for the second slot
* @param third the serializer for the third slot
* @return the serializer; never null
*/
public static <T1, T2, T3> Serializer<Tuple3<T1, T2, T3>> serializer( Serializer<T1> first,
Serializer<T2> second,
Serializer<T3> third ) {
return new Tuple3Serializer<>(first, second, third);
}
/**
* Create a {@link Serializer} for tuples of size 4.
*
* @param first the serializer for the first slot
* @param second the serializer for the second slot
* @param third the serializer for the third slot
* @param fourth the serializer for the fourth slot
* @return the serializer; never null
*/
public static <T1, T2, T3, T4> Serializer<Tuple4<T1, T2, T3, T4>> serializer( Serializer<T1> first,
Serializer<T2> second,
Serializer<T3> third,
Serializer<T4> fourth ) {
return new Tuple4Serializer<>(first, second, third, fourth);
}
/**
* Create a {@link Serializer} for n-ary tuples
*
* @param serializers the serializers for each slot in the tuples
* @return the serializer; never null
*/
public static Serializer<TupleN> serializer( Serializer<?>[] serializers ) {
return new TupleNSerializer(serializers);
}
/**
* Create a {@link Serializer} for uniform tuples.
*
* @param serializer the serializer of each/every slot in the tuples
* @param tupleSize the size of the tuples
* @return the type factory; never null
*/
public static Serializer<?> serializer( Serializer<?> serializer,
int tupleSize ) {
if (tupleSize <= 1) return serializer;
if (tupleSize == 2) return serializer(serializer, serializer);
if (tupleSize == 3) return serializer(serializer, serializer, serializer);
if (tupleSize == 4) return serializer(serializer, serializer, serializer, serializer);
Serializer<?>[] serializers = new Serializer<?>[tupleSize];
Arrays.fill(serializers, serializer);
return new TupleNSerializer(serializers);
}
public static final class Tuple2Serializer<T1, T2> implements Serializer<Tuple2<T1, T2>>, Serializable {
private static final long serialVersionUID = 1L;
private final Serializer<T1> serializer1;
private final Serializer<T2> serializer2;
public Tuple2Serializer( Serializer<T1> serializer1,
Serializer<T2> serializer2 ) {
this.serializer1 = serializer1;
this.serializer2 = serializer2;
}
@Override
public int fixedSize() {
return 1; // not fixed size
}
@Override
public void serialize( DataOutput out,
Tuple2<T1, T2> value ) throws IOException {
serializer1.serialize(out, value.v1);
serializer2.serialize(out, value.v2);
}
@Override
public Tuple2<T1, T2> deserialize( DataInput in,
int available ) throws IOException {
T1 v1 = serializer1.deserialize(in, available);
T2 v2 = serializer2.deserialize(in, available);
return tuple(v1, v2);
}
}
public static final class Tuple3Serializer<T1, T2, T3> implements Serializer<Tuple3<T1, T2, T3>>, Serializable {
private static final long serialVersionUID = 1L;
private final Serializer<T1> serializer1;
private final Serializer<T2> serializer2;
private final Serializer<T3> serializer3;
public Tuple3Serializer( Serializer<T1> serializer1,
Serializer<T2> serializer2,
Serializer<T3> serializer3 ) {
this.serializer1 = serializer1;
this.serializer2 = serializer2;
this.serializer3 = serializer3;
}
@Override
public int fixedSize() {
return 1; // not fixed size
}
@Override
public void serialize( DataOutput out,
Tuple3<T1, T2, T3> value ) throws IOException {
serializer1.serialize(out, value.v1);
serializer2.serialize(out, value.v2);
serializer3.serialize(out, value.v3);
}
@Override
public Tuple3<T1, T2, T3> deserialize( DataInput in,
int available ) throws IOException {
T1 v1 = serializer1.deserialize(in, available);
T2 v2 = serializer2.deserialize(in, available);
T3 v3 = serializer3.deserialize(in, available);
return tuple(v1, v2, v3);
}
}
public static final class Tuple4Serializer<T1, T2, T3, T4> implements Serializer<Tuple4<T1, T2, T3, T4>>, Serializable {
private static final long serialVersionUID = 1L;
private final Serializer<T1> serializer1;
private final Serializer<T2> serializer2;
private final Serializer<T3> serializer3;
private final Serializer<T4> serializer4;
public Tuple4Serializer( Serializer<T1> serializer1,
Serializer<T2> serializer2,
Serializer<T3> serializer3,
Serializer<T4> serializer4 ) {
this.serializer1 = serializer1;
this.serializer2 = serializer2;
this.serializer3 = serializer3;
this.serializer4 = serializer4;
}
@Override
public int fixedSize() {
return 1; // not fixed size
}
@Override
public void serialize( DataOutput out,
Tuple4<T1, T2, T3, T4> value ) throws IOException {
serializer1.serialize(out, value.v1);
serializer2.serialize(out, value.v2);
serializer3.serialize(out, value.v3);
serializer4.serialize(out, value.v4);
}
@Override
public Tuple4<T1, T2, T3, T4> deserialize( DataInput in,
int available ) throws IOException {
T1 v1 = serializer1.deserialize(in, available);
T2 v2 = serializer2.deserialize(in, available);
T3 v3 = serializer3.deserialize(in, available);
T4 v4 = serializer4.deserialize(in, available);
return tuple(v1, v2, v3, v4);
}
}
public static final class TupleNSerializer implements Serializer<TupleN>, Serializable {
private static final long serialVersionUID = 1L;
private final Serializer<Object>[] serializers;
private final int size;
@SuppressWarnings( "unchecked" )
public TupleNSerializer( Serializer<?>[] serializers ) {
this.serializers = (Serializer<Object>[])serializers;
this.size = serializers.length;
}
@Override
public int fixedSize() {
return 1; // not fixed size
}
@Override
public void serialize( DataOutput out,
TupleN value ) throws IOException {
for (int i = 0; i != size; ++i) {
serializers[i].serialize(out, value.values[i]);
}
}
@Override
public TupleN deserialize( DataInput in,
int available ) throws IOException {
Object[] values = new Object[size];
for (int i = 0; i != size; ++i) {
values[i] = serializers[i].deserialize(in, available);
}
return tuple(values);
}
}
@SuppressWarnings( "unchecked" )
protected static int compareValues( Object value1,
Object value2 ) {
if (value1 == null) {
return value2 == null ? 0 : -1;
}
return value2 == null ? 1 : ((Comparable<Object>)value1).compareTo(value2);
}
public static final class Tuple2<T1, T2> implements Comparable<Tuple2<T1, T2>> {
public final T1 v1;
public final T2 v2;
private final int hc;
public Tuple2( T1 v1,
T2 v2 ) {
this.v1 = v1;
this.v2 = v2;
this.hc = HashCode.compute(v1, v2);
}
@Override
public int compareTo( Tuple2<T1, T2> that ) {
if (that == this) return 0;
int diff = compareValues(this.v1, that.v1);
if (diff != 0) return diff;
return compareValues(this.v2, that.v2);
}
@Override
public int hashCode() {
return hc;
}
@Override
public boolean equals( Object obj ) {
if (obj == this) return true;
if (obj instanceof Tuple2) {
Tuple2<?, ?> that = (Tuple2<?, ?>)obj;
return ObjectUtil.isEqualWithNulls(this.v1, that.v1) && ObjectUtil.isEqualWithNulls(this.v2, that.v2);
}
return false;
}
@Override
public String toString() {
return "<" + v1 + "," + v2 + ">";
}
}
public static final class Tuple3<T1, T2, T3> implements Comparable<Tuple3<T1, T2, T3>> {
public final T1 v1;
public final T2 v2;
public final T3 v3;
private final int hc;
public Tuple3( T1 v1,
T2 v2,
T3 v3 ) {
this.v1 = v1;
this.v2 = v2;
this.v3 = v3;
this.hc = HashCode.compute(v1, v2, v3);
}
@Override
public int compareTo( Tuple3<T1, T2, T3> that ) {
if (that == this) return 0;
int diff = compareValues(this.v1, that.v1);
if (diff != 0) return diff;
diff = compareValues(this.v2, that.v2);
if (diff != 0) return diff;
return compareValues(this.v3, that.v3);
}
@Override
public int hashCode() {
return hc;
}
@Override
public boolean equals( Object obj ) {
if (obj == this) return true;
if (obj instanceof Tuple3) {
Tuple3<?, ?, ?> that = (Tuple3<?, ?, ?>)obj;
return ObjectUtil.isEqualWithNulls(this.v1, that.v1) && ObjectUtil.isEqualWithNulls(this.v2, that.v2)
&& ObjectUtil.isEqualWithNulls(this.v3, that.v3);
}
return false;
}
@Override
public String toString() {
return "<" + v1 + "," + v2 + "," + v3 + ">";
}
}
public static final class Tuple4<T1, T2, T3, T4> implements Comparable<Tuple4<T1, T2, T3, T4>> {
public final T1 v1;
public final T2 v2;
public final T3 v3;
public final T4 v4;
private final int hc;
public Tuple4( T1 v1,
T2 v2,
T3 v3,
T4 v4 ) {
this.v1 = v1;
this.v2 = v2;
this.v3 = v3;
this.v4 = v4;
this.hc = HashCode.compute(v1, v2, v3, v4);
}
@Override
public int compareTo( Tuple4<T1, T2, T3, T4> that ) {
if (that == this) return 0;
int diff = compareValues(this.v1, that.v1);
if (diff != 0) return diff;
diff = compareValues(this.v2, that.v2);
if (diff != 0) return diff;
diff = compareValues(this.v3, that.v3);
if (diff != 0) return diff;
return compareValues(this.v4, that.v4);
}
@Override
public int hashCode() {
return hc;
}
@Override
public boolean equals( Object obj ) {
if (obj == this) return true;
if (obj instanceof Tuple4) {
Tuple4<?, ?, ?, ?> that = (Tuple4<?, ?, ?, ?>)obj;
return ObjectUtil.isEqualWithNulls(this.v1, that.v1) && ObjectUtil.isEqualWithNulls(this.v2, that.v2)
&& ObjectUtil.isEqualWithNulls(this.v3, that.v3) && ObjectUtil.isEqualWithNulls(this.v4, that.v4);
}
return false;
}
@Override
public String toString() {
return "<" + v1 + "," + v2 + "," + v3 + "," + v4 + ">";
}
}
public static final class TupleN implements Comparable<TupleN> {
protected final Object[] values;
private final int hc;
public TupleN( Object[] values ) {
this.values = values;
this.hc = HashCode.compute(values);
}
@Override
public int compareTo( TupleN that ) {
if (that == this) return 0;
int diff = this.values.length - that.values.length;
if (diff != 0) return diff;
for (int i = 0; i != values.length; ++i) {
diff = compareValues(this.values[i], that.values[i]);
if (diff != 0) return diff;
}
return 0;
}
@Override
public int hashCode() {
return hc;
}
@Override
public boolean equals( Object obj ) {
if (obj == this) return true;
if (obj instanceof TupleN) {
TupleN that = (TupleN)obj;
if (this.values.length == that.values.length) {
for (int i = 0; i != values.length; ++i) {
if (ObjectUtil.isEqualWithNulls(this.values[i], that.values[i])) return false;
}
return true;
}
}
return false;
}
@Override
public String toString() {
return Arrays.toString(values);
}
}
public interface TupleFactory<T> {
Serializer<T> getSerializer( BufferManager bufferMgr );
}
protected static final class Tuple2Comparator<T1, T2> implements Comparator<Tuple2<T1, T2>>, Serializable {
private static final long serialVersionUID = 1L;
private final Comparator<T1> comparator1;
private final Comparator<T2> comparator2;
protected Tuple2Comparator( Comparator<T1> comparator1,
Comparator<T2> comparator2 ) {
this.comparator1 = comparator1;
this.comparator2 = comparator2;
}
@Override
public int compare( Tuple2<T1, T2> arg0,
Tuple2<T1, T2> arg1 ) {
int diff = comparator1.compare(arg0.v1, arg1.v1);
if (diff != 0) return diff;
return comparator2.compare(arg0.v2, arg1.v2);
}
@Override
public boolean equals( Object obj ) {
if (obj == this) return true;
if (obj instanceof Tuple2Comparator) {
@SuppressWarnings( "unchecked" )
Tuple2Comparator<T1, T2> that = (Tuple2Comparator<T1, T2>)obj;
return comparator1.equals(that.comparator1) && comparator2.equals(that.comparator2);
}
return false;
}
@Override
public int hashCode() {
return 1;
}
}
@SuppressWarnings( "unchecked" )
protected static final class Tuple2TypeFactory<T1, T2> implements TypeFactory<Tuple2<T1, T2>>, TupleFactory<Tuple2<T1, T2>> {
private final TypeFactory<T1> type1;
private final TypeFactory<T2> type2;
private final Class<Tuple2<T1, T2>> type;
private final Comparator<Tuple2<T1, T2>> comparator;
private final String typeName;
protected Tuple2TypeFactory( TypeFactory<T1> type1,
TypeFactory<T2> type2 ) {
this.type1 = type1;
this.type2 = type2;
Class<?> clazz = Tuple2.class;
this.type = (Class<Tuple2<T1, T2>>)clazz;
this.comparator = new Tuple2Comparator<>(type1.getComparator(), type2.getComparator());
this.typeName = "Tuple2<" + type1.getTypeName() + "," + type2.getTypeName() + ">";
}
@Override
public Serializer<Tuple2<T1, T2>> getSerializer( BufferManager bufferMgr ) {
Serializer<T1> ser1 = (Serializer<T1>)bufferMgr.nullSafeSerializerFor(type1);
Serializer<T2> ser2 = (Serializer<T2>)bufferMgr.nullSafeSerializerFor(type2);
return new Tuple2Serializer<>(ser1, ser2);
}
@Override
public Class<Tuple2<T1, T2>> getType() {
return this.type;
}
@Override
public Comparator<Tuple2<T1, T2>> getComparator() {
return comparator;
}
@Override
public String getTypeName() {
return typeName;
}
@Override
public Tuple2<T1, T2> create( String value ) throws ValueFormatException {
throw new UnsupportedOperationException();
}
@Override
public Tuple2<T1, T2> create( Object value ) throws ValueFormatException {
throw new UnsupportedOperationException();
}
@Override
public String asString( Object value ) {
return value.toString();
}
@Override
public long length( Object value ) {
if (value instanceof Tuple2) {
Tuple2<?, ?> tuple = (Tuple2<?, ?>)value;
return type1.length(tuple.v1) + type2.length(tuple.v2);
}
return asString(value).length();
}
@Override
public String asReadableString( Object value ) {
return asString(value);
}
}
@SuppressWarnings( "unchecked" )
protected static final class Tuple3TypeFactory<T1, T2, T3>
implements TypeFactory<Tuple3<T1, T2, T3>>, TupleFactory<Tuple3<T1, T2, T3>> {
private final TypeFactory<T1> type1;
private final TypeFactory<T2> type2;
private final TypeFactory<T3> type3;
private final Class<Tuple3<T1, T2, T3>> type;
private final Comparator<Tuple3<T1, T2, T3>> comparator;
private final String typeName;
protected Tuple3TypeFactory( TypeFactory<T1> type1,
TypeFactory<T2> type2,
TypeFactory<T3> type3 ) {
this.type1 = type1;
this.type2 = type2;
this.type3 = type3;
Class<?> clazz = Tuple3.class;
this.type = (Class<Tuple3<T1, T2, T3>>)clazz;
final Comparator<T1> comparator1 = type1.getComparator();
final Comparator<T2> comparator2 = type2.getComparator();
final Comparator<T3> comparator3 = type3.getComparator();
this.comparator = (Comparator<Tuple3<T1, T2, T3>> & Serializable) (arg0, arg1) -> {
int diff = comparator1.compare(arg0.v1, arg1.v1);
if (diff != 0) return diff;
diff = comparator2.compare(arg0.v2, arg1.v2);
if (diff != 0) return diff;
return comparator3.compare(arg0.v3, arg1.v3);
};
this.typeName = "Tuple3<" + type1.getTypeName() + "," + type2.getTypeName() + "," + type3.getTypeName() + ">";
}
@Override
public Serializer<Tuple3<T1, T2, T3>> getSerializer( BufferManager bufferMgr ) {
Serializer<T1> ser1 = (Serializer<T1>)bufferMgr.nullSafeSerializerFor(type1);
Serializer<T2> ser2 = (Serializer<T2>)bufferMgr.nullSafeSerializerFor(type2);
Serializer<T3> ser3 = (Serializer<T3>)bufferMgr.nullSafeSerializerFor(type3);
return new Tuple3Serializer<>(ser1, ser2, ser3);
}
@Override
public Class<Tuple3<T1, T2, T3>> getType() {
return this.type;
}
@Override
public Comparator<Tuple3<T1, T2, T3>> getComparator() {
return comparator;
}
@Override
public String getTypeName() {
return typeName;
}
@Override
public Tuple3<T1, T2, T3> create( String value ) throws ValueFormatException {
throw new UnsupportedOperationException();
}
@Override
public Tuple3<T1, T2, T3> create( Object value ) throws ValueFormatException {
throw new UnsupportedOperationException();
}
@Override
public String asString( Object value ) {
return value.toString();
}
@Override
public long length( Object value ) {
if (value instanceof Tuple3) {
Tuple3<?, ?, ?> tuple = (Tuple3<?, ?, ?>)value;
return type1.length(tuple.v1) + type2.length(tuple.v2) + type3.length(tuple.v3);
}
return asString(value).length();
}
@Override
public String asReadableString( Object value ) {
return asString(value);
}
}
@SuppressWarnings( "unchecked" )
protected static final class Tuple4TypeFactory<T1, T2, T3, T4>
implements TypeFactory<Tuple4<T1, T2, T3, T4>>, TupleFactory<Tuple4<T1, T2, T3, T4>> {
private final TypeFactory<T1> type1;
private final TypeFactory<T2> type2;
private final TypeFactory<T3> type3;
private final TypeFactory<T4> type4;
private final Class<Tuple4<T1, T2, T3, T4>> type;
private final Comparator<Tuple4<T1, T2, T3, T4>> comparator;
private final String typeName;
protected Tuple4TypeFactory( TypeFactory<T1> type1,
TypeFactory<T2> type2,
TypeFactory<T3> type3,
TypeFactory<T4> type4 ) {
this.type1 = type1;
this.type2 = type2;
this.type3 = type3;
this.type4 = type4;
Class<?> clazz = Tuple4.class;
this.type = (Class<Tuple4<T1, T2, T3, T4>>)clazz;
final Comparator<T1> comparator1 = type1.getComparator();
final Comparator<T2> comparator2 = type2.getComparator();
final Comparator<T3> comparator3 = type3.getComparator();
final Comparator<T4> comparator4 = type4.getComparator();
this.comparator = (Comparator<Tuple4<T1, T2, T3, T4>> & Serializable) (arg0, arg1) -> {
int diff = comparator1.compare(arg0.v1, arg1.v1);
if (diff != 0) return diff;
diff = comparator2.compare(arg0.v2, arg1.v2);
if (diff != 0) return diff;
diff = comparator3.compare(arg0.v3, arg1.v3);
if (diff != 0) return diff;
return comparator4.compare(arg0.v4, arg1.v4);
};
this.typeName = "Tuple4<" + type1.getTypeName() + "," + type2.getTypeName() + "," + type3.getTypeName() + ","
+ type4.getTypeName() + ">";
}
@Override
public Serializer<Tuple4<T1, T2, T3, T4>> getSerializer( BufferManager bufferMgr ) {
Serializer<T1> ser1 = (Serializer<T1>)bufferMgr.nullSafeSerializerFor(type1);
Serializer<T2> ser2 = (Serializer<T2>)bufferMgr.nullSafeSerializerFor(type2);
Serializer<T3> ser3 = (Serializer<T3>)bufferMgr.nullSafeSerializerFor(type3);
Serializer<T4> ser4 = (Serializer<T4>)bufferMgr.nullSafeSerializerFor(type4);
return new Tuple4Serializer<>(ser1, ser2, ser3, ser4);
}
@Override
public Class<Tuple4<T1, T2, T3, T4>> getType() {
return this.type;
}
@Override
public Comparator<Tuple4<T1, T2, T3, T4>> getComparator() {
return comparator;
}
@Override
public String getTypeName() {
return typeName;
}
@Override
public Tuple4<T1, T2, T3, T4> create( String value ) throws ValueFormatException {
throw new UnsupportedOperationException();
}
@Override
public Tuple4<T1, T2, T3, T4> create( Object value ) throws ValueFormatException {
throw new UnsupportedOperationException();
}
@Override
public String asString( Object value ) {
return value.toString();
}
@Override
public long length( Object value ) {
if (value instanceof Tuple4) {
Tuple4<?, ?, ?, ?> tuple = (Tuple4<?, ?, ?, ?>)value;
return type1.length(tuple.v1) + type2.length(tuple.v2) + type3.length(tuple.v3) + type4.length(tuple.v4);
}
return asString(value).length();
}
@Override
public String asReadableString( Object value ) {
return asString(value);
}
}
@SuppressWarnings( "unchecked" )
protected static final class TupleNTypeFactory implements TypeFactory<TupleN>, TupleFactory<TupleN> {
protected final TypeFactory<?>[] types;
private final Comparator<TupleN> comparator;
private final String typeName;
protected TupleNTypeFactory( Collection<TypeFactory<?>> typeFactories ) {
this.types = new TypeFactory<?>[typeFactories.size()];
final Comparator<Object>[] comparators = new Comparator[types.length];
Iterator<TypeFactory<?>> typeIter = typeFactories.iterator();
for (int i = 0; i != this.types.length; ++i) {
TypeFactory<?> typeFactory = typeIter.next();
this.types[i] = typeFactory;
comparators[i] = (Comparator<Object>)typeFactory.getComparator();
}
this.comparator = (Comparator<TupleN> & Serializable) (arg0, arg1) -> {
int diff = 0;
for (int i = 0; i != types.length; ++i) {
diff = comparators[i].compare(arg0.values[i], arg1.values[i]);
if (diff != 0) return diff;
}
return diff;
};
StringBuilder sb = new StringBuilder("TupleN<");
for (int i = 0; i != types.length; ++i) {
if (i != 0) sb.append(',');
sb.append(types[i].getTypeName());
}
sb.append(">");
this.typeName = sb.toString();
}
@Override
public Serializer<TupleN> getSerializer( BufferManager bufferMgr ) {
Serializer<?>[] serializers = new Serializer<?>[types.length];
for (int i = 0; i != types.length; ++i) {
serializers[i] = bufferMgr.nullSafeSerializerFor(types[i]);
}
return new TupleNSerializer(serializers);
}
@Override
public Class<TupleN> getType() {
return TupleN.class;
}
@Override
public Comparator<TupleN> getComparator() {
return comparator;
}
@Override
public String getTypeName() {
return this.typeName;
}
@Override
public TupleN create( String value ) throws ValueFormatException {
throw new UnsupportedOperationException();
}
@Override
public TupleN create( Object value ) throws ValueFormatException {
throw new UnsupportedOperationException();
}
@Override
public String asString( Object value ) {
return value.toString();
}
@Override
public long length( Object value ) {
if (value instanceof TupleN) {
TupleN tuple = (TupleN)value;
int len = 0;
for (int i = 0; i != types.length; ++i) {
len += types[i].length(tuple.values[i]);
}
return len;
}
return asString(value).length();
}
@Override
public String asReadableString( Object value ) {
return asString(value);
}
}
}