From 52adf34e447720270b6cdcda19c8b61fda9a29c6 Mon Sep 17 00:00:00 2001 From: Ghislain Fourny Date: Tue, 5 Mar 2024 14:23:10 +0100 Subject: [PATCH] Fix test. --- .../org/rumbledb/context/DynamicContext.java | 8 + .../context/RuntimeStaticContext.java | 30 +- .../exceptions/ExceptionMetadata.java | 42 +- .../java/org/rumbledb/items/FunctionItem.java | 35 +- .../AtMostOneItemLocalRuntimeIterator.java | 19 + .../runtime/HybridRuntimeIterator.java | 6 + .../org/rumbledb/runtime/RuntimeIterator.java | 11 + .../AdditiveOperationIterator.java | 808 ++++++++---------- .../AtMostOneItemIfRuntimeIterator.java | 15 + .../runtime/flwor/FlworDataFrameUtils.java | 10 +- .../primary/VariableReferenceIterator.java | 23 + .../org/rumbledb/types/AtomicItemType.java | 26 + .../java/org/rumbledb/types/SequenceType.java | 1 - 13 files changed, 552 insertions(+), 482 deletions(-) diff --git a/src/main/java/org/rumbledb/context/DynamicContext.java b/src/main/java/org/rumbledb/context/DynamicContext.java index a7850a4076..a1075bf94a 100644 --- a/src/main/java/org/rumbledb/context/DynamicContext.java +++ b/src/main/java/org/rumbledb/context/DynamicContext.java @@ -121,13 +121,21 @@ public VariableValues getVariableValues() { @Override public void write(Kryo kryo, Output output) { kryo.writeObjectOrNull(output, this.parent, DynamicContext.class); + kryo.writeObject(output, this.conf); kryo.writeObject(output, this.variableValues); + // kryo.writeObject(output, this.namedFunctions); + kryo.writeObject(output, this.inScopeSchemaTypes); + kryo.writeObject(output, this.currentDateTime.getMillis()); } @Override public void read(Kryo kryo, Input input) { this.parent = kryo.readObjectOrNull(input, DynamicContext.class); + this.conf = kryo.readObject(input, RumbleRuntimeConfiguration.class); this.variableValues = kryo.readObject(input, VariableValues.class); + this.namedFunctions = new NamedFunctions(this.conf); + this.inScopeSchemaTypes= kryo.readObject(input, InScopeSchemaTypes.class); + this.currentDateTime = new DateTime(kryo.readObject(input, Long.class)); } public enum VariableDependency { diff --git a/src/main/java/org/rumbledb/context/RuntimeStaticContext.java b/src/main/java/org/rumbledb/context/RuntimeStaticContext.java index e5cce1f65d..c8f0a73761 100644 --- a/src/main/java/org/rumbledb/context/RuntimeStaticContext.java +++ b/src/main/java/org/rumbledb/context/RuntimeStaticContext.java @@ -8,7 +8,12 @@ import org.rumbledb.expressions.ExecutionMode; import org.rumbledb.types.SequenceType; -public class RuntimeStaticContext implements Serializable { +import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.KryoSerializable; +import com.esotericsoftware.kryo.io.Input; +import com.esotericsoftware.kryo.io.Output; + +public class RuntimeStaticContext implements Serializable, KryoSerializable { private static final long serialVersionUID = 1L; private RumbleRuntimeConfiguration configuration; @@ -16,6 +21,13 @@ public class RuntimeStaticContext implements Serializable { private ExecutionMode executionMode; private ExceptionMetadata metadata; + public RuntimeStaticContext() { + this.configuration = null; + this.staticType = null; + this.executionMode = null; + this.metadata = null; + } + public RuntimeStaticContext( RumbleRuntimeConfiguration configuration, SequenceType staticType, @@ -62,4 +74,20 @@ public ExceptionMetadata getMetadata() { return this.metadata; } + @Override + public void write(Kryo kryo, Output output) { + kryo.writeObject(output, this.configuration); + kryo.writeObject(output, this.staticType); + kryo.writeObject(output, this.executionMode); + kryo.writeObject(output, this.metadata); + } + + @Override + public void read(Kryo kryo, Input input) { + this.configuration = kryo.readObject(input, RumbleRuntimeConfiguration.class); + this.staticType = kryo.readObject(input, SequenceType.class); + this.executionMode = kryo.readObject(input, ExecutionMode.class); + this.metadata = kryo.readObject(input, ExceptionMetadata.class); + } + } diff --git a/src/main/java/org/rumbledb/exceptions/ExceptionMetadata.java b/src/main/java/org/rumbledb/exceptions/ExceptionMetadata.java index d4401e2b3d..e59acfb733 100644 --- a/src/main/java/org/rumbledb/exceptions/ExceptionMetadata.java +++ b/src/main/java/org/rumbledb/exceptions/ExceptionMetadata.java @@ -22,20 +22,36 @@ import java.io.Serializable; +import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.KryoSerializable; +import com.esotericsoftware.kryo.io.Input; +import com.esotericsoftware.kryo.io.Output; + /** * Metadata for error reporting (line and column number) * * @author Stefan Irimescu, Ghislain Fourny */ -public class ExceptionMetadata implements Serializable { +public class ExceptionMetadata implements Serializable, KryoSerializable { + + private String location; + private int tokenLineNumber; + private int tokenColumnNumber; + private String code; private static final long serialVersionUID = 1L; - private final String location; - private final int tokenLineNumber; - private final int tokenColumnNumber; - private final String code; public static final ExceptionMetadata EMPTY_METADATA = new ExceptionMetadata("none", 1, 0, ""); + /** + * Builds a new empty metadata object (for serialization and deserialization only) + */ + public ExceptionMetadata() { + this.location = ""; + this.tokenLineNumber = -1; + this.tokenColumnNumber = -1; + this.code = ""; + } + /** * Builds a new metadata object * @@ -118,4 +134,20 @@ public String toString() { + getTokenColumnNumber() + ":"; } + + @Override + public void write(Kryo kryo, Output output) { + kryo.writeObject(output, this.location); + kryo.writeObject(output, this.tokenLineNumber); + kryo.writeObject(output, this.tokenColumnNumber); + kryo.writeObject(output, this.code); + } + + @Override + public void read(Kryo kryo, Input input) { + this.location = kryo.readObject(input, String.class); + this.tokenLineNumber= kryo.readObject(input, Integer.class); + this.tokenColumnNumber = kryo.readObject(input, Integer.class); + this.code = kryo.readObject(input, String.class); + } } diff --git a/src/main/java/org/rumbledb/items/FunctionItem.java b/src/main/java/org/rumbledb/items/FunctionItem.java index 4e0413abf0..7ce4a6f325 100644 --- a/src/main/java/org/rumbledb/items/FunctionItem.java +++ b/src/main/java/org/rumbledb/items/FunctionItem.java @@ -57,10 +57,9 @@ public class FunctionItem implements Item { private static final long serialVersionUID = 1L; + private FunctionIdentifier identifier; private List parameterNames; - - // signature contains type information for all parameters and the return value private FunctionSignature signature; private RuntimeIterator bodyIterator; private DynamicContext dynamicModuleContext; @@ -242,20 +241,8 @@ public void write(Kryo kryo, Output output) { "We do not support serializing DataFrames in function closures." ); } - // kryo.writeObject(output, this.dynamicModuleContext); - - // convert RuntimeIterator to byte[] data - /* - * try { - * byte[] data = SerializationUtils.serialize(this.bodyIterator); - * output.writeInt(data.length); - * output.writeBytes(data); - * } catch (Exception e) { - * throw new OurBadException( - * "Error converting functionItem-bodyRuntimeIterator to byte[]:" + e.getMessage() - * ); - * } - */ + kryo.writeObject(output, this.dynamicModuleContext); + kryo.writeClassAndObject(output, this.bodyIterator); } @SuppressWarnings("unchecked") @@ -267,20 +254,8 @@ public void read(Kryo kryo, Input input) { this.localVariablesInClosure = kryo.readObject(input, HashMap.class); this.RDDVariablesInClosure = new HashMap<>(); this.dataFrameVariablesInClosure = new HashMap<>(); - // this.dynamicModuleContext = kryo.readObject(input, DynamicContext.class); - // this.bodyIterator = kryo.readObject(input, RuntimeIterator.class); - - /* - * try { - * int dataLength = input.readInt(); - * byte[] data = input.readBytes(dataLength); - * this.bodyIterator = SerializationUtils.deserialize(data); - * } catch (Exception e) { - * throw new OurBadException( - * "Error converting functionItem-bodyRuntimeIterator to functionItem:" + e.getMessage() - * ); - * } - */ + this.dynamicModuleContext = kryo.readObject(input, DynamicContext.class); + this.bodyIterator = (RuntimeIterator) kryo.readClassAndObject(input); } @Override diff --git a/src/main/java/org/rumbledb/runtime/AtMostOneItemLocalRuntimeIterator.java b/src/main/java/org/rumbledb/runtime/AtMostOneItemLocalRuntimeIterator.java index 325561efaa..d5462c7bb1 100644 --- a/src/main/java/org/rumbledb/runtime/AtMostOneItemLocalRuntimeIterator.java +++ b/src/main/java/org/rumbledb/runtime/AtMostOneItemLocalRuntimeIterator.java @@ -33,6 +33,10 @@ import org.rumbledb.expressions.comparison.ComparisonExpression.ComparisonOperator; import org.rumbledb.types.BuiltinTypesCatalogue; +import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.io.Input; +import com.esotericsoftware.kryo.io.Output; + import sparksoniq.spark.SparkSessionManager; import org.rumbledb.runtime.misc.ComparisonIterator; @@ -47,6 +51,11 @@ public abstract class AtMostOneItemLocalRuntimeIterator extends RuntimeIterator private static final long serialVersionUID = 1L; private Item result; + protected AtMostOneItemLocalRuntimeIterator() { + super(); + this.result = null; + } + protected AtMostOneItemLocalRuntimeIterator( List children, RuntimeStaticContext staticContext @@ -186,4 +195,14 @@ public boolean getEffectiveBooleanValueOrCheckPosition(DynamicContext dynamicCon getMetadata() ); } + + @Override + public void write(Kryo kryo, Output output) { + super.write(kryo, output); + } + + @Override + public void read(Kryo kryo, Input input) { + super.read(kryo, input); + } } diff --git a/src/main/java/org/rumbledb/runtime/HybridRuntimeIterator.java b/src/main/java/org/rumbledb/runtime/HybridRuntimeIterator.java index 131742fe57..13217126ce 100644 --- a/src/main/java/org/rumbledb/runtime/HybridRuntimeIterator.java +++ b/src/main/java/org/rumbledb/runtime/HybridRuntimeIterator.java @@ -43,6 +43,12 @@ public abstract class HybridRuntimeIterator extends RuntimeIterator { protected List result = null; private int currentResultIndex = 0; + protected HybridRuntimeIterator() { + super(); + this.result = null; + this.currentResultIndex = 0; + } + protected HybridRuntimeIterator( List children, RuntimeStaticContext staticContext diff --git a/src/main/java/org/rumbledb/runtime/RuntimeIterator.java b/src/main/java/org/rumbledb/runtime/RuntimeIterator.java index 429b88cc6e..436ccaf911 100644 --- a/src/main/java/org/rumbledb/runtime/RuntimeIterator.java +++ b/src/main/java/org/rumbledb/runtime/RuntimeIterator.java @@ -72,6 +72,15 @@ public abstract class RuntimeIterator implements RuntimeIteratorInterface, KryoS protected URI staticURI; // private StaticContext staticContext; + public RuntimeIterator() { + this.hasNext = false; + this.isOpen = false; + this.children = null; + this.currentDynamicContextForLocalExecution = null; + this.staticContext = null; + this.staticURI = null; + } + protected RuntimeIterator(List children, RuntimeStaticContext staticContext) { this.staticContext = staticContext; if (this.staticContext.getStaticType() == null) { @@ -220,6 +229,7 @@ public void reset(DynamicContext context) { @Override public void write(Kryo kryo, Output output) { + kryo.writeObject(output, this.staticContext); kryo.writeObject(output, this.children); // TODO serializer other fields } @@ -230,6 +240,7 @@ public void read(Kryo kryo, Input input) { this.hasNext = false; this.isOpen = false; this.currentDynamicContextForLocalExecution = null; + this.staticContext = kryo.readObject(input, RuntimeStaticContext.class); this.children = kryo.readObject(input, ArrayList.class); // TODO serializer other fields } diff --git a/src/main/java/org/rumbledb/runtime/arithmetics/AdditiveOperationIterator.java b/src/main/java/org/rumbledb/runtime/arithmetics/AdditiveOperationIterator.java index 3fc8cb51bf..deaa5242db 100644 --- a/src/main/java/org/rumbledb/runtime/arithmetics/AdditiveOperationIterator.java +++ b/src/main/java/org/rumbledb/runtime/arithmetics/AdditiveOperationIterator.java @@ -23,12 +23,14 @@ import java.math.BigDecimal; import java.math.BigInteger; import java.util.Arrays; +import java.util.Set; import org.joda.time.DateTime; import org.joda.time.Period; import org.joda.time.PeriodType; import org.rumbledb.api.Item; import org.rumbledb.context.DynamicContext; +import org.rumbledb.context.Name; import org.rumbledb.context.RuntimeStaticContext; import org.rumbledb.exceptions.MoreThanOneItemException; import org.rumbledb.exceptions.NonAtomicKeyException; @@ -40,470 +42,388 @@ import org.rumbledb.types.SequenceType; import org.rumbledb.types.SequenceType.Arity; +import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.io.Input; +import com.esotericsoftware.kryo.io.Output; public class AdditiveOperationIterator extends AtMostOneItemLocalRuntimeIterator { - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - private Item left; - private Item right; - private boolean isMinus; - private RuntimeIterator leftIterator; - private RuntimeIterator rightIterator; + private Item left; + private Item right; + private boolean isMinus; + private RuntimeIterator leftIterator; + private RuntimeIterator rightIterator; - public AdditiveOperationIterator( - RuntimeIterator leftIterator, - RuntimeIterator rightIterator, - boolean isMinus, - RuntimeStaticContext staticContext - ) { - super(Arrays.asList(leftIterator, rightIterator), staticContext); - this.leftIterator = leftIterator; - this.rightIterator = rightIterator; - this.isMinus = isMinus; - } + public AdditiveOperationIterator() { + super(); + this.leftIterator = null; + this.rightIterator = null; + this.isMinus = false; + } - public Item materializeFirstItemOrNull( - DynamicContext dynamicContext - ) { - try { - this.left = this.leftIterator.materializeAtMostOneItemOrNull(dynamicContext); - } catch (MoreThanOneItemException e) { - throw new UnexpectedTypeException( - "Addition expression requires at most one item in its left input sequence.", - getMetadata() - ); - } - try { - this.right = this.rightIterator.materializeAtMostOneItemOrNull(dynamicContext); - } catch (MoreThanOneItemException e) { - throw new UnexpectedTypeException( - "Addition expression requires at most one item in its right input sequence.", - getMetadata() - ); - } + public AdditiveOperationIterator(RuntimeIterator leftIterator, RuntimeIterator rightIterator, boolean isMinus, + RuntimeStaticContext staticContext) { + super(Arrays.asList(leftIterator, rightIterator), staticContext); + this.leftIterator = leftIterator; + this.rightIterator = rightIterator; + this.isMinus = isMinus; + } - // if left or right equals empty sequence, return empty sequence - if (this.left == null || this.right == null) { - return null; - } - if (!this.left.isAtomic()) { - String message = String.format( - "Can not atomize an %1$s item: an %1$s has probably been passed where " - + - "an atomic value is expected (e.g., as a key, or to a function expecting an atomic item)", - this.left.getDynamicType().toString() - ); - throw new NonAtomicKeyException(message, getMetadata()); - } - if (!this.right.isAtomic()) { - String message = String.format( - "Can not atomize an %1$s item: an %1$s has probably been passed where " - + - "an atomic value is expected (e.g., as a key, or to a function expecting an atomic item)", - this.right.getDynamicType().toString() - ); - throw new NonAtomicKeyException(message, getMetadata()); - } - Item result = processItem(this.left, this.right, this.isMinus); - if (result == null) { - throw new UnexpectedTypeException( - " \"+\": operation not possible with parameters of type \"" - + this.left.getDynamicType().toString() - + "\" and \"" - + this.right.getDynamicType().toString() - + "\"", - getMetadata() - ); - } - return result; - } + public Item materializeFirstItemOrNull(DynamicContext dynamicContext) { + try { + this.left = this.leftIterator.materializeAtMostOneItemOrNull(dynamicContext); + } catch (MoreThanOneItemException e) { + throw new UnexpectedTypeException( + "Addition expression requires at most one item in its left input sequence.", getMetadata()); + } + try { + this.right = this.rightIterator.materializeAtMostOneItemOrNull(dynamicContext); + } catch (MoreThanOneItemException e) { + throw new UnexpectedTypeException( + "Addition expression requires at most one item in its right input sequence.", getMetadata()); + } - public static Item processItem( - Item left, - Item right, - boolean isMinus - ) { - // The integer 0 is considered the default neutral element for addition in sum(), even though - // it is technically incompatible with durations. In the future, we should - // make sure an error is thrown if an actual 0 appears in the sum with durations. - if (!isMinus && left.isInteger() && left.getIntegerValue().equals(BigInteger.ZERO)) { - return right; - } - if (!isMinus && right.isInteger() && right.getIntegerValue().equals(BigInteger.ZERO)) { - return left; - } - if ( - left.isInt() - && right.isInt() - ) { - if ( - right.isInt() - && (left.getIntValue() < Integer.MAX_VALUE / 2 - && left.getIntValue() > -Integer.MAX_VALUE / 2 - && right.getIntValue() > -Integer.MAX_VALUE / 2 - && right.getIntValue() < Integer.MAX_VALUE / 2) - ) { - return processInt(left.getIntValue(), right.getIntValue(), isMinus); - } - } + // if left or right equals empty sequence, return empty sequence + if (this.left == null || this.right == null) { + return null; + } + if (!this.left.isAtomic()) { + String message = String.format( + "Can not atomize an %1$s item: an %1$s has probably been passed where " + + "an atomic value is expected (e.g., as a key, or to a function expecting an atomic item)", + this.left.getDynamicType().toString()); + throw new NonAtomicKeyException(message, getMetadata()); + } + if (!this.right.isAtomic()) { + String message = String.format( + "Can not atomize an %1$s item: an %1$s has probably been passed where " + + "an atomic value is expected (e.g., as a key, or to a function expecting an atomic item)", + this.right.getDynamicType().toString()); + throw new NonAtomicKeyException(message, getMetadata()); + } + Item result = processItem(this.left, this.right, this.isMinus); + if (result == null) { + throw new UnexpectedTypeException( + " \"+\": operation not possible with parameters of type \"" + this.left.getDynamicType().toString() + + "\" and \"" + this.right.getDynamicType().toString() + "\"", + getMetadata()); + } + return result; + } - // General cases - if (left.isDouble() && right.isNumeric()) { - double l = left.getDoubleValue(); - double r = 0; - if (right.isDouble()) { - r = right.getDoubleValue(); - } else { - r = right.castToDoubleValue(); - } - return processDouble(l, r, isMinus); - } - if (right.isDouble() && left.isNumeric()) { - double l = left.castToDoubleValue(); - double r = right.getDoubleValue(); - return processDouble(l, r, isMinus); - } - if (left.isFloat() && right.isNumeric()) { - float l = left.getFloatValue(); - float r = 0; - if (right.isFloat()) { - r = right.getFloatValue(); - } else { - r = right.castToFloatValue(); - } - return processFloat(l, r, isMinus); - } - if (right.isFloat() && left.isNumeric()) { - float l = left.castToFloatValue(); - float r = right.getFloatValue(); - return processFloat(l, r, isMinus); - } - if (left.isInteger() && right.isInteger()) { - BigInteger l = left.getIntegerValue(); - BigInteger r = right.getIntegerValue(); - return processInteger(l, r, isMinus); - } - if (left.isDecimal() && right.isDecimal()) { - BigDecimal l = left.getDecimalValue(); - BigDecimal r = right.getDecimalValue(); - return processDecimal(l, r, isMinus); - } - if (left.isYearMonthDuration() && right.isYearMonthDuration()) { - Period l = left.getDurationValue(); - Period r = right.getDurationValue(); - return processYearMonthDuration(l, r, isMinus); - } - if (left.isDayTimeDuration() && right.isDayTimeDuration()) { - Period l = left.getDurationValue(); - Period r = right.getDurationValue(); - return processDayTimeDuration(l, r, isMinus); - } - if (left.isDate() && right.isYearMonthDuration()) { - DateTime l = left.getDateTimeValue(); - Period r = right.getDurationValue(); - return processDateTimeDurationDate(l, r, isMinus, left.hasTimeZone()); - } - if (left.isDate() && right.isDayTimeDuration()) { - DateTime l = left.getDateTimeValue(); - Period r = right.getDurationValue(); - return processDateTimeDurationDate(l, r, isMinus, left.hasTimeZone()); - } - if (left.isYearMonthDuration() && right.isDate()) { - if (!isMinus) { - Period l = left.getDurationValue(); - DateTime r = right.getDateTimeValue(); - return processDateTimeDurationDate(r, l, isMinus, right.hasTimeZone()); - } - } - if (left.isDayTimeDuration() && right.isDate()) { - if (!isMinus) { - Period l = left.getDurationValue(); - DateTime r = right.getDateTimeValue(); - return processDateTimeDurationDate(r, l, isMinus, right.hasTimeZone()); - } - } - if (left.isTime() && right.isDayTimeDuration()) { - DateTime l = left.getDateTimeValue(); - Period r = right.getDurationValue(); - return processDateTimeDurationTime(l, r, isMinus, left.hasTimeZone()); - } - if (left.isDayTimeDuration() && right.isTime()) { - if (!isMinus) { - Period l = left.getDurationValue(); - DateTime r = right.getDateTimeValue(); - return processDateTimeDurationTime(r, l, isMinus, right.hasTimeZone()); - } - } - if (left.isDateTime() && right.isYearMonthDuration()) { - DateTime l = left.getDateTimeValue(); - Period r = right.getDurationValue(); - return processDateTimeDurationDateTime(l, r, isMinus, left.hasTimeZone()); - } - if (left.isDateTime() && right.isDayTimeDuration()) { - DateTime l = left.getDateTimeValue(); - Period r = right.getDurationValue(); - return processDateTimeDurationDateTime(l, r, isMinus, left.hasTimeZone()); - } - if (left.isYearMonthDuration() && right.isDateTime()) { - if (!isMinus) { - Period l = left.getDurationValue(); - DateTime r = right.getDateTimeValue(); - return processDateTimeDurationDateTime(r, l, isMinus, right.hasTimeZone()); - } - } - if (left.isDayTimeDuration() && right.isDateTime()) { - if (!isMinus) { - Period l = left.getDurationValue(); - DateTime r = right.getDateTimeValue(); - return processDateTimeDurationDateTime(r, l, isMinus, right.hasTimeZone()); - } - } - if (left.isDate() && right.isDate()) { - if (isMinus) { - DateTime l = left.getDateTimeValue(); - DateTime r = right.getDateTimeValue(); - return processDateTimeDayTime(l, r); - } - } - if (left.isTime() && right.isTime()) { - if (isMinus) { - DateTime l = left.getDateTimeValue(); - DateTime r = right.getDateTimeValue(); - return processDateTimeDayTime(l, r); - } - } - if (left.isDateTime() && right.isDateTime()) { - if (isMinus) { - DateTime l = left.getDateTimeValue(); - DateTime r = right.getDateTimeValue(); - return processDateTimeDayTime(l, r); - } - } - return null; - } + public static Item processItem(Item left, Item right, boolean isMinus) { + // The integer 0 is considered the default neutral element for addition in + // sum(), even though + // it is technically incompatible with durations. In the future, we should + // make sure an error is thrown if an actual 0 appears in the sum with + // durations. + if (!isMinus && left.isInteger() && left.getIntegerValue().equals(BigInteger.ZERO)) { + return right; + } + if (!isMinus && right.isInteger() && right.getIntegerValue().equals(BigInteger.ZERO)) { + return left; + } + if (left.isInt() && right.isInt()) { + if (right.isInt() && (left.getIntValue() < Integer.MAX_VALUE / 2 + && left.getIntValue() > -Integer.MAX_VALUE / 2 && right.getIntValue() > -Integer.MAX_VALUE / 2 + && right.getIntValue() < Integer.MAX_VALUE / 2)) { + return processInt(left.getIntValue(), right.getIntValue(), isMinus); + } + } - private static Item processDouble( - double l, - double r, - boolean isMinus - ) { - if (isMinus) { - return ItemFactory.getInstance().createDoubleItem(l - r); - } else { - return ItemFactory.getInstance().createDoubleItem(l + r); - } - } + // General cases + if (left.isDouble() && right.isNumeric()) { + double l = left.getDoubleValue(); + double r = 0; + if (right.isDouble()) { + r = right.getDoubleValue(); + } else { + r = right.castToDoubleValue(); + } + return processDouble(l, r, isMinus); + } + if (right.isDouble() && left.isNumeric()) { + double l = left.castToDoubleValue(); + double r = right.getDoubleValue(); + return processDouble(l, r, isMinus); + } + if (left.isFloat() && right.isNumeric()) { + float l = left.getFloatValue(); + float r = 0; + if (right.isFloat()) { + r = right.getFloatValue(); + } else { + r = right.castToFloatValue(); + } + return processFloat(l, r, isMinus); + } + if (right.isFloat() && left.isNumeric()) { + float l = left.castToFloatValue(); + float r = right.getFloatValue(); + return processFloat(l, r, isMinus); + } + if (left.isInteger() && right.isInteger()) { + BigInteger l = left.getIntegerValue(); + BigInteger r = right.getIntegerValue(); + return processInteger(l, r, isMinus); + } + if (left.isDecimal() && right.isDecimal()) { + BigDecimal l = left.getDecimalValue(); + BigDecimal r = right.getDecimalValue(); + return processDecimal(l, r, isMinus); + } + if (left.isYearMonthDuration() && right.isYearMonthDuration()) { + Period l = left.getDurationValue(); + Period r = right.getDurationValue(); + return processYearMonthDuration(l, r, isMinus); + } + if (left.isDayTimeDuration() && right.isDayTimeDuration()) { + Period l = left.getDurationValue(); + Period r = right.getDurationValue(); + return processDayTimeDuration(l, r, isMinus); + } + if (left.isDate() && right.isYearMonthDuration()) { + DateTime l = left.getDateTimeValue(); + Period r = right.getDurationValue(); + return processDateTimeDurationDate(l, r, isMinus, left.hasTimeZone()); + } + if (left.isDate() && right.isDayTimeDuration()) { + DateTime l = left.getDateTimeValue(); + Period r = right.getDurationValue(); + return processDateTimeDurationDate(l, r, isMinus, left.hasTimeZone()); + } + if (left.isYearMonthDuration() && right.isDate()) { + if (!isMinus) { + Period l = left.getDurationValue(); + DateTime r = right.getDateTimeValue(); + return processDateTimeDurationDate(r, l, isMinus, right.hasTimeZone()); + } + } + if (left.isDayTimeDuration() && right.isDate()) { + if (!isMinus) { + Period l = left.getDurationValue(); + DateTime r = right.getDateTimeValue(); + return processDateTimeDurationDate(r, l, isMinus, right.hasTimeZone()); + } + } + if (left.isTime() && right.isDayTimeDuration()) { + DateTime l = left.getDateTimeValue(); + Period r = right.getDurationValue(); + return processDateTimeDurationTime(l, r, isMinus, left.hasTimeZone()); + } + if (left.isDayTimeDuration() && right.isTime()) { + if (!isMinus) { + Period l = left.getDurationValue(); + DateTime r = right.getDateTimeValue(); + return processDateTimeDurationTime(r, l, isMinus, right.hasTimeZone()); + } + } + if (left.isDateTime() && right.isYearMonthDuration()) { + DateTime l = left.getDateTimeValue(); + Period r = right.getDurationValue(); + return processDateTimeDurationDateTime(l, r, isMinus, left.hasTimeZone()); + } + if (left.isDateTime() && right.isDayTimeDuration()) { + DateTime l = left.getDateTimeValue(); + Period r = right.getDurationValue(); + return processDateTimeDurationDateTime(l, r, isMinus, left.hasTimeZone()); + } + if (left.isYearMonthDuration() && right.isDateTime()) { + if (!isMinus) { + Period l = left.getDurationValue(); + DateTime r = right.getDateTimeValue(); + return processDateTimeDurationDateTime(r, l, isMinus, right.hasTimeZone()); + } + } + if (left.isDayTimeDuration() && right.isDateTime()) { + if (!isMinus) { + Period l = left.getDurationValue(); + DateTime r = right.getDateTimeValue(); + return processDateTimeDurationDateTime(r, l, isMinus, right.hasTimeZone()); + } + } + if (left.isDate() && right.isDate()) { + if (isMinus) { + DateTime l = left.getDateTimeValue(); + DateTime r = right.getDateTimeValue(); + return processDateTimeDayTime(l, r); + } + } + if (left.isTime() && right.isTime()) { + if (isMinus) { + DateTime l = left.getDateTimeValue(); + DateTime r = right.getDateTimeValue(); + return processDateTimeDayTime(l, r); + } + } + if (left.isDateTime() && right.isDateTime()) { + if (isMinus) { + DateTime l = left.getDateTimeValue(); + DateTime r = right.getDateTimeValue(); + return processDateTimeDayTime(l, r); + } + } + return null; + } - private static Item processFloat( - float l, - float r, - boolean isMinus - ) { - if (isMinus) { - return ItemFactory.getInstance().createFloatItem(l - r); - } else { - return ItemFactory.getInstance().createFloatItem(l + r); - } - } + private static Item processDouble(double l, double r, boolean isMinus) { + if (isMinus) { + return ItemFactory.getInstance().createDoubleItem(l - r); + } else { + return ItemFactory.getInstance().createDoubleItem(l + r); + } + } - private static Item processDecimal( - BigDecimal l, - BigDecimal r, - boolean isMinus - ) { - if (isMinus) { - return ItemFactory.getInstance().createDecimalItem(l.subtract(r)); - } else { - return ItemFactory.getInstance().createDecimalItem(l.add(r)); - } - } + private static Item processFloat(float l, float r, boolean isMinus) { + if (isMinus) { + return ItemFactory.getInstance().createFloatItem(l - r); + } else { + return ItemFactory.getInstance().createFloatItem(l + r); + } + } - private static Item processInteger( - BigInteger l, - BigInteger r, - boolean isMinus - ) { - if (isMinus) { - return ItemFactory.getInstance().createIntegerItem(l.subtract(r)); - } else { - return ItemFactory.getInstance().createIntegerItem(l.add(r)); - } - } + private static Item processDecimal(BigDecimal l, BigDecimal r, boolean isMinus) { + if (isMinus) { + return ItemFactory.getInstance().createDecimalItem(l.subtract(r)); + } else { + return ItemFactory.getInstance().createDecimalItem(l.add(r)); + } + } - private static Item processInt( - int l, - int r, - boolean isMinus - ) { - if (isMinus) { - return ItemFactory.getInstance().createIntItem(l - r); - } else { - return ItemFactory.getInstance().createIntItem(l + r); - } - } + private static Item processInteger(BigInteger l, BigInteger r, boolean isMinus) { + if (isMinus) { + return ItemFactory.getInstance().createIntegerItem(l.subtract(r)); + } else { + return ItemFactory.getInstance().createIntegerItem(l.add(r)); + } + } - private static Item processYearMonthDuration( - Period l, - Period r, - boolean isMinus - ) { - if (isMinus) { - return ItemFactory.getInstance().createYearMonthDurationItem(l.minus(r)); - } else { - return ItemFactory.getInstance().createYearMonthDurationItem(l.plus(r)); - } - } + private static Item processInt(int l, int r, boolean isMinus) { + if (isMinus) { + return ItemFactory.getInstance().createIntItem(l - r); + } else { + return ItemFactory.getInstance().createIntItem(l + r); + } + } - private static Item processDayTimeDuration( - Period l, - Period r, - boolean isMinus - ) { - if (isMinus) { - return ItemFactory.getInstance().createDayTimeDurationItem(l.minus(r)); - } else { - return ItemFactory.getInstance().createDayTimeDurationItem(l.plus(r)); - } - } + private static Item processYearMonthDuration(Period l, Period r, boolean isMinus) { + if (isMinus) { + return ItemFactory.getInstance().createYearMonthDurationItem(l.minus(r)); + } else { + return ItemFactory.getInstance().createYearMonthDurationItem(l.plus(r)); + } + } - private static Item processDateTimeDayTime( - DateTime l, - DateTime r - ) { - return ItemFactory.getInstance() - .createDayTimeDurationItem(new Period(r, l, PeriodType.dayTime())); - } + private static Item processDayTimeDuration(Period l, Period r, boolean isMinus) { + if (isMinus) { + return ItemFactory.getInstance().createDayTimeDurationItem(l.minus(r)); + } else { + return ItemFactory.getInstance().createDayTimeDurationItem(l.plus(r)); + } + } - private static Item processDateTimeDurationDate( - DateTime l, - Period r, - boolean isMinus, - boolean timeZone - ) { - if (isMinus) { - return ItemFactory.getInstance() - .createDateItem(l.minus(r), timeZone); - } else { - return ItemFactory.getInstance() - .createDateItem(l.plus(r), timeZone); - } - } + private static Item processDateTimeDayTime(DateTime l, DateTime r) { + return ItemFactory.getInstance().createDayTimeDurationItem(new Period(r, l, PeriodType.dayTime())); + } - private static Item processDateTimeDurationTime( - DateTime l, - Period r, - boolean isMinus, - boolean timeZone - ) { - if (isMinus) { - return ItemFactory.getInstance() - .createTimeItem(l.minus(r), timeZone); - } else { - return ItemFactory.getInstance() - .createTimeItem(l.plus(r), timeZone); - } - } + private static Item processDateTimeDurationDate(DateTime l, Period r, boolean isMinus, boolean timeZone) { + if (isMinus) { + return ItemFactory.getInstance().createDateItem(l.minus(r), timeZone); + } else { + return ItemFactory.getInstance().createDateItem(l.plus(r), timeZone); + } + } - private static Item processDateTimeDurationDateTime( - DateTime l, - Period r, - boolean isMinus, - boolean timeZone - ) { - if (isMinus) { - return ItemFactory.getInstance() - .createDateTimeItem(l.minus(r), timeZone); - } else { - return ItemFactory.getInstance() - .createDateTimeItem(l.plus(r), timeZone); - } - } + private static Item processDateTimeDurationTime(DateTime l, Period r, boolean isMinus, boolean timeZone) { + if (isMinus) { + return ItemFactory.getInstance().createTimeItem(l.minus(r), timeZone); + } else { + return ItemFactory.getInstance().createTimeItem(l.plus(r), timeZone); + } + } - @Override - public NativeClauseContext generateNativeQuery(NativeClauseContext nativeClauseContext) { - NativeClauseContext leftResult = this.leftIterator.generateNativeQuery(nativeClauseContext); - if (leftResult == NativeClauseContext.NoNativeQuery) { - return NativeClauseContext.NoNativeQuery; - } - if (!this.leftIterator.getStaticType().getArity().equals(Arity.One)) { - return NativeClauseContext.NoNativeQuery; - } - NativeClauseContext rightResult = this.rightIterator.generateNativeQuery(nativeClauseContext); - if (rightResult == NativeClauseContext.NoNativeQuery) { - return NativeClauseContext.NoNativeQuery; - } - if (!this.rightIterator.getStaticType().getArity().equals(Arity.One)) { - return NativeClauseContext.NoNativeQuery; - } - String leftQuery = leftResult.getResultingQuery(); - String rightQuery = rightResult.getResultingQuery(); - if ( - this.leftIterator.getStaticType().isSubtypeOf(SequenceType.DOUBLE_QM) - && - this.rightIterator.getStaticType().getItemType().isNumeric() - ) { - if (!this.rightIterator.getStaticType().isSubtypeOf(SequenceType.DOUBLE_QM)) { - rightQuery = "(CAST (" + rightQuery + " AS DOUBLE))"; - } - } else if ( - this.rightIterator.getStaticType().isSubtypeOf(SequenceType.DOUBLE_QM) - && - this.leftIterator.getStaticType().getItemType().isNumeric() - ) { - if (!this.leftIterator.getStaticType().isSubtypeOf(SequenceType.DOUBLE_QM)) { - leftQuery = "(CAST (" + leftQuery + " AS DOUBLE))"; - } - } else if ( - this.leftIterator.getStaticType().isSubtypeOf(SequenceType.FLOAT_QM) - && - this.rightIterator.getStaticType().getItemType().isNumeric() - ) { - if (!this.rightIterator.getStaticType().isSubtypeOf(SequenceType.FLOAT_QM)) { - rightQuery = "(CAST (" + rightQuery + " AS FLOAT))"; - } - } else if ( - this.rightIterator.getStaticType().isSubtypeOf(SequenceType.FLOAT_QM) - && - this.leftIterator.getStaticType().getItemType().isNumeric() - ) { - if (!this.leftIterator.getStaticType().isSubtypeOf(SequenceType.FLOAT_QM)) { - leftQuery = "(CAST (" + leftQuery + " AS FLOAT))"; - } - } else if ( - this.leftIterator.getStaticType().isSubtypeOf(SequenceType.INTEGER_QM) - && - this.rightIterator.getStaticType().isSubtypeOf(SequenceType.INTEGER_QM) - ) { - } else if ( - this.leftIterator.getStaticType().isSubtypeOf(SequenceType.DECIMAL_QM) - && - this.rightIterator.getStaticType().isSubtypeOf(SequenceType.DECIMAL_QM) - ) { - } else { - return NativeClauseContext.NoNativeQuery; - } + private static Item processDateTimeDurationDateTime(DateTime l, Period r, boolean isMinus, boolean timeZone) { + if (isMinus) { + return ItemFactory.getInstance().createDateTimeItem(l.minus(r), timeZone); + } else { + return ItemFactory.getInstance().createDateTimeItem(l.plus(r), timeZone); + } + } - if (this.isMinus) { - String resultingQuery = "( " - + leftQuery - + " - " - + rightQuery - + " )"; - return new NativeClauseContext( - nativeClauseContext, - resultingQuery - ); - } else { - String resultingQuery = "( " - + leftQuery - + " + " - + rightQuery - + " )"; - return new NativeClauseContext( - nativeClauseContext, - resultingQuery - ); - } - } + @Override + public NativeClauseContext generateNativeQuery(NativeClauseContext nativeClauseContext) { + NativeClauseContext leftResult = this.leftIterator.generateNativeQuery(nativeClauseContext); + if (leftResult == NativeClauseContext.NoNativeQuery) { + return NativeClauseContext.NoNativeQuery; + } + if (!this.leftIterator.getStaticType().getArity().equals(Arity.One)) { + return NativeClauseContext.NoNativeQuery; + } + NativeClauseContext rightResult = this.rightIterator.generateNativeQuery(nativeClauseContext); + if (rightResult == NativeClauseContext.NoNativeQuery) { + return NativeClauseContext.NoNativeQuery; + } + if (!this.rightIterator.getStaticType().getArity().equals(Arity.One)) { + return NativeClauseContext.NoNativeQuery; + } + String leftQuery = leftResult.getResultingQuery(); + String rightQuery = rightResult.getResultingQuery(); + if (this.leftIterator.getStaticType().isSubtypeOf(SequenceType.DOUBLE_QM) + && this.rightIterator.getStaticType().getItemType().isNumeric()) { + if (!this.rightIterator.getStaticType().isSubtypeOf(SequenceType.DOUBLE_QM)) { + rightQuery = "(CAST (" + rightQuery + " AS DOUBLE))"; + } + } else if (this.rightIterator.getStaticType().isSubtypeOf(SequenceType.DOUBLE_QM) + && this.leftIterator.getStaticType().getItemType().isNumeric()) { + if (!this.leftIterator.getStaticType().isSubtypeOf(SequenceType.DOUBLE_QM)) { + leftQuery = "(CAST (" + leftQuery + " AS DOUBLE))"; + } + } else if (this.leftIterator.getStaticType().isSubtypeOf(SequenceType.FLOAT_QM) + && this.rightIterator.getStaticType().getItemType().isNumeric()) { + if (!this.rightIterator.getStaticType().isSubtypeOf(SequenceType.FLOAT_QM)) { + rightQuery = "(CAST (" + rightQuery + " AS FLOAT))"; + } + } else if (this.rightIterator.getStaticType().isSubtypeOf(SequenceType.FLOAT_QM) + && this.leftIterator.getStaticType().getItemType().isNumeric()) { + if (!this.leftIterator.getStaticType().isSubtypeOf(SequenceType.FLOAT_QM)) { + leftQuery = "(CAST (" + leftQuery + " AS FLOAT))"; + } + } else if (this.leftIterator.getStaticType().isSubtypeOf(SequenceType.INTEGER_QM) + && this.rightIterator.getStaticType().isSubtypeOf(SequenceType.INTEGER_QM)) { + } else if (this.leftIterator.getStaticType().isSubtypeOf(SequenceType.DECIMAL_QM) + && this.rightIterator.getStaticType().isSubtypeOf(SequenceType.DECIMAL_QM)) { + } else { + return NativeClauseContext.NoNativeQuery; + } + + if (this.isMinus) { + String resultingQuery = "( " + leftQuery + " - " + rightQuery + " )"; + return new NativeClauseContext(nativeClauseContext, resultingQuery); + } else { + String resultingQuery = "( " + leftQuery + " + " + rightQuery + " )"; + return new NativeClauseContext(nativeClauseContext, resultingQuery); + } + } + + @Override + public void write(Kryo kryo, Output output) { + super.write(kryo, output); + kryo.writeClassAndObject(output, this.left); + kryo.writeClassAndObject(output, this.right); + kryo.writeObject(output, this.isMinus); + kryo.writeClassAndObject(output, this.leftIterator); + kryo.writeClassAndObject(output, this.rightIterator); + } + + @Override + public void read(Kryo kryo, Input input) { + super.read(kryo, input); + this.left = (Item) kryo.readClassAndObject(input); + this.right = (Item) kryo.readClassAndObject(input); + this.isMinus = kryo.readObject(input, Boolean.class); + this.leftIterator = (RuntimeIterator) kryo.readClassAndObject(input); + this.rightIterator = (RuntimeIterator) kryo.readClassAndObject(input); + } } diff --git a/src/main/java/org/rumbledb/runtime/control/AtMostOneItemIfRuntimeIterator.java b/src/main/java/org/rumbledb/runtime/control/AtMostOneItemIfRuntimeIterator.java index 1fc7cb348d..7910e9dc44 100644 --- a/src/main/java/org/rumbledb/runtime/control/AtMostOneItemIfRuntimeIterator.java +++ b/src/main/java/org/rumbledb/runtime/control/AtMostOneItemIfRuntimeIterator.java @@ -24,12 +24,17 @@ import org.rumbledb.api.Item; import org.rumbledb.context.DynamicContext; +import org.rumbledb.context.Name; import org.rumbledb.context.RuntimeStaticContext; import org.rumbledb.runtime.AtMostOneItemLocalRuntimeIterator; import org.rumbledb.runtime.RuntimeIterator; import org.rumbledb.runtime.flwor.NativeClauseContext; import org.rumbledb.types.SequenceType; +import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.io.Input; +import com.esotericsoftware.kryo.io.Output; + public class AtMostOneItemIfRuntimeIterator extends AtMostOneItemLocalRuntimeIterator { @@ -89,4 +94,14 @@ public NativeClauseContext generateNativeQuery(NativeClauseContext nativeClauseC + " ) )"; return new NativeClauseContext(nativeClauseContext, resultingQuery); } + + @Override + public void write(Kryo kryo, Output output) { + super.write(kryo, output); + } + + @Override + public void read(Kryo kryo, Input input) { + super.read(kryo, input); + } } diff --git a/src/main/java/org/rumbledb/runtime/flwor/FlworDataFrameUtils.java b/src/main/java/org/rumbledb/runtime/flwor/FlworDataFrameUtils.java index 776f010b8a..f16505cb49 100644 --- a/src/main/java/org/rumbledb/runtime/flwor/FlworDataFrameUtils.java +++ b/src/main/java/org/rumbledb/runtime/flwor/FlworDataFrameUtils.java @@ -78,9 +78,12 @@ import org.rumbledb.items.TimeItem; import org.rumbledb.items.YearMonthDurationItem; import org.rumbledb.items.structured.JSoundDataFrame; +import org.rumbledb.runtime.arithmetics.AdditiveOperationIterator; import org.rumbledb.runtime.flwor.FlworDataFrameColumn.ColumnFormat; -import org.rumbledb.types.ItemType; +import org.rumbledb.runtime.primary.VariableReferenceIterator; +import org.rumbledb.types.AtomicItemType; import org.rumbledb.types.ItemItemType; +import org.rumbledb.types.ItemType; import org.rumbledb.types.SequenceType; import com.esotericsoftware.kryo.Kryo; @@ -128,14 +131,19 @@ public static void registerKryoClassesKryo(Kryo kryo) { kryo.register(FunctionItem.class); kryo.register(FunctionIdentifier.class); kryo.register(Name.class); + kryo.register(SequenceType.class); kryo.register(SequenceType.Arity.class); kryo.register(ItemType.class); kryo.register(ItemItemType.class); + kryo.register(AtomicItemType.class); kryo.register(ArrayList.class); kryo.register(RumbleRuntimeConfiguration.class); + + kryo.register(AdditiveOperationIterator.class); + kryo.register(VariableReferenceIterator.class); } public static byte[] serializeItem(Item toSerialize, Kryo kryo, Output output) { diff --git a/src/main/java/org/rumbledb/runtime/primary/VariableReferenceIterator.java b/src/main/java/org/rumbledb/runtime/primary/VariableReferenceIterator.java index 1d4e8cc96a..10294ef667 100644 --- a/src/main/java/org/rumbledb/runtime/primary/VariableReferenceIterator.java +++ b/src/main/java/org/rumbledb/runtime/primary/VariableReferenceIterator.java @@ -36,6 +36,10 @@ import org.rumbledb.runtime.flwor.FlworDataFrameUtils; import org.rumbledb.runtime.flwor.NativeClauseContext; +import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.io.Input; +import com.esotericsoftware.kryo.io.Output; + import java.util.List; import java.util.Map; import java.util.TreeMap; @@ -48,6 +52,13 @@ public class VariableReferenceIterator extends HybridRuntimeIterator { private List items = null; private int currentIndex = 0; + public VariableReferenceIterator() { + super(); + this.variableName = null; + this.items= null; + this.currentIndex = 0; + } + public VariableReferenceIterator( Name variableName, RuntimeStaticContext staticContext @@ -157,4 +168,16 @@ public Map getVariableDependencies() { result.put(this.variableName, DynamicContext.VariableDependency.FULL); return result; } + + @Override + public void write(Kryo kryo, Output output) { + super.write(kryo, output); + kryo.writeObject(output, this.variableName); + } + + @Override + public void read(Kryo kryo, Input input) { + super.read(kryo, input); + this.variableName = kryo.readObject(input, Name.class); + } } diff --git a/src/main/java/org/rumbledb/types/AtomicItemType.java b/src/main/java/org/rumbledb/types/AtomicItemType.java index 02b3b48e82..97639ca9c1 100644 --- a/src/main/java/org/rumbledb/types/AtomicItemType.java +++ b/src/main/java/org/rumbledb/types/AtomicItemType.java @@ -4,6 +4,10 @@ import org.rumbledb.config.RumbleRuntimeConfiguration; import org.rumbledb.context.Name; +import com.esotericsoftware.kryo.Kryo; +import com.esotericsoftware.kryo.io.Input; +import com.esotericsoftware.kryo.io.Output; + import java.util.*; /** @@ -547,4 +551,26 @@ public boolean isCompatibleWithDataFrames(RumbleRuntimeConfiguration configurati } return true; } + + @Override + public void write(Kryo kryo, Output output) { + kryo.writeObject(output, this.name); + kryo.writeObject(output, this.allowedFacets.size()); + for(FacetTypes f : this.allowedFacets) + { + kryo.writeObject(output, f); + } + } + + @Override + public void read(Kryo kryo, Input input) { + this.name = kryo.readObject(input, Name.class); + int n = kryo.readObject(input, Integer.class); + this.allowedFacets = new HashSet<>(n); + for(int i = 0; i < n; ++i) + { + FacetTypes t = kryo.readObject(input, FacetTypes.class); + this.allowedFacets.add(t); + } + } } diff --git a/src/main/java/org/rumbledb/types/SequenceType.java b/src/main/java/org/rumbledb/types/SequenceType.java index 47db9f8d9e..3ab1a31dc2 100644 --- a/src/main/java/org/rumbledb/types/SequenceType.java +++ b/src/main/java/org/rumbledb/types/SequenceType.java @@ -749,7 +749,6 @@ public void write(Kryo kryo, Output output) { kryo.writeObject(output, this.arity); } - @SuppressWarnings("unchecked") @Override public void read(Kryo kryo, Input input) { this.itemType = (ItemType) kryo.readClassAndObject(input);