*/
public static Tuple deepCopy(ITuple tuple, Map<String, FieldClonator> customClonators) {
Schema schema = tuple.getSchema();
Tuple newTuple = new Tuple(schema);
for (int i = 0; i < schema.getFields().size(); i++) {
Field field = schema.getField(i);
Object value = tuple.get(i);
if (value == null) {
continue;
}
if (customClonators != null && customClonators.containsKey(field.getName())) {
// There is a custom clonator
newTuple.set(i, customClonators.get(field.getName()).giveMeACopy(value));
continue;
}
switch (field.getType()) {
case BYTES:
if (value instanceof ByteBuffer) {
newTuple.set(i, cloneByteBuffer((ByteBuffer) value));
} else if (value instanceof byte[]) {
newTuple.set(i, Arrays.copyOf((byte[]) value, ((byte[]) value).length));
} else {
throw new IllegalArgumentException("Field " + field.getName() + " of type " + field.getType()
+ " cannot contains values of class " + value.getClass().getCanonicalName());
}
break;
case OBJECT:
if (value instanceof ITuple) {
throw new IDontKnowHowToCopyThisStuff("Tuples inside tuples requires a custom FieldClonator" +
"to perform the copy. Please, provide a custom FieldClonator for field " + field.getName()
+ ". It usually is as simple as create one that calls the deepCopy method for the " +
"inner tuple");
} else {
throw new IDontKnowHowToCopyThisStuff("I don't know how to copy the field " + field.getName()
+ " with type " + value.getClass().getCanonicalName() + ". Please, provide a custom " +
"FieldClonator for this field in order to be able to perform deep copies");
}
case STRING:
if (value instanceof String) {
newTuple.set(i, tuple.get(i));
} else if (value instanceof Utf8 || value instanceof Text) {
newTuple.set(i, new Utf8(value.toString()));
} else {
throw new IllegalArgumentException("Field " + field.getName() + " of type " + field.getType()
+ " cannot contains values of class " + value.getClass().getCanonicalName());
}
break;
default:
newTuple.set(i, tuple.get(i));