blob: 52071af75c02d36fec54a046b5bda952e4f54698 [file] [log] [blame]
package edu.uci.ics.asterix.external.library.java;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import edu.uci.ics.asterix.common.exceptions.AsterixException;
import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt32SerializerDeserializer;
import edu.uci.ics.asterix.dataflow.data.nontagged.serde.ARecordSerializerDeserializer;
import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AStringSerializerDeserializer;
import edu.uci.ics.asterix.dataflow.data.nontagged.serde.SerializerDeserializerUtil;
import edu.uci.ics.asterix.external.library.java.JObjects.ByteArrayAccessibleDataInputStream;
import edu.uci.ics.asterix.external.library.java.JObjects.JBoolean;
import edu.uci.ics.asterix.external.library.java.JObjects.JCircle;
import edu.uci.ics.asterix.external.library.java.JObjects.JDate;
import edu.uci.ics.asterix.external.library.java.JObjects.JDateTime;
import edu.uci.ics.asterix.external.library.java.JObjects.JDouble;
import edu.uci.ics.asterix.external.library.java.JObjects.JDuration;
import edu.uci.ics.asterix.external.library.java.JObjects.JFloat;
import edu.uci.ics.asterix.external.library.java.JObjects.JInt;
import edu.uci.ics.asterix.external.library.java.JObjects.JInterval;
import edu.uci.ics.asterix.external.library.java.JObjects.JLine;
import edu.uci.ics.asterix.external.library.java.JObjects.JOrderedList;
import edu.uci.ics.asterix.external.library.java.JObjects.JPoint;
import edu.uci.ics.asterix.external.library.java.JObjects.JPoint3D;
import edu.uci.ics.asterix.external.library.java.JObjects.JPolygon;
import edu.uci.ics.asterix.external.library.java.JObjects.JRecord;
import edu.uci.ics.asterix.external.library.java.JObjects.JRectangle;
import edu.uci.ics.asterix.external.library.java.JObjects.JString;
import edu.uci.ics.asterix.external.library.java.JObjects.JTime;
import edu.uci.ics.asterix.external.library.java.JObjects.JUnorderedList;
import edu.uci.ics.asterix.om.pointables.base.IVisitablePointable;
import edu.uci.ics.asterix.om.types.AOrderedListType;
import edu.uci.ics.asterix.om.types.ARecordType;
import edu.uci.ics.asterix.om.types.ATypeTag;
import edu.uci.ics.asterix.om.types.AUnionType;
import edu.uci.ics.asterix.om.types.AUnorderedListType;
import edu.uci.ics.asterix.om.types.BuiltinType;
import edu.uci.ics.asterix.om.types.EnumDeserializer;
import edu.uci.ics.asterix.om.types.IAType;
import edu.uci.ics.asterix.om.util.NonTaggedFormatUtil;
import edu.uci.ics.asterix.om.util.container.IObjectPool;
public class JObjectUtil {
public static IJObject getJType(ATypeTag typeTag, IAType type, ByteArrayAccessibleDataInputStream dis,
IObjectPool<IJObject, IAType> objectPool) throws IOException, AsterixException {
IJObject jObject;
switch (typeTag) {
case INT32: {
int v = dis.readInt();
jObject = objectPool.allocate(BuiltinType.AINT32);
((JInt) jObject).setValue(v);
break;
}
case FLOAT: {
float v = dis.readFloat();
jObject = objectPool.allocate(BuiltinType.AFLOAT);
((JFloat) jObject).setValue(v);
break;
}
case DOUBLE: {
double value = dis.readDouble();
jObject = objectPool.allocate(BuiltinType.ADOUBLE);
((JDouble) jObject).setValue(value);
break;
}
case STRING: {
String v = dis.readUTF();
jObject = objectPool.allocate(BuiltinType.ASTRING);
((JString) jObject).setValue(v);
break;
}
case BOOLEAN:
jObject = objectPool.allocate(BuiltinType.ABOOLEAN);
((JBoolean) jObject).setValue(dis.readBoolean());
break;
case DATE: {
int d = dis.readInt();
jObject = objectPool.allocate(BuiltinType.ADATE);
((JDate) jObject).setValue(d);
break;
}
case DATETIME: {
jObject = objectPool.allocate(BuiltinType.ADATETIME);
long value = dis.readLong();
((JDateTime) jObject).setValue(value);
break;
}
case DURATION: {
jObject = objectPool.allocate(BuiltinType.ADURATION);
int months = dis.readInt();
long msecs = dis.readLong();
((JDuration) jObject).setValue(months, msecs);
break;
}
case TIME: {
jObject = objectPool.allocate(BuiltinType.ATIME);
int time = dis.readInt();
((JTime) jObject).setValue(time);
break;
}
case INTERVAL: {
jObject = objectPool.allocate(BuiltinType.AINTERVAL);
long start = dis.readLong();
long end = dis.readLong();
byte intervalType = dis.readByte();
((JInterval) jObject).setValue(start, end, intervalType);
break;
}
case CIRCLE: {
jObject = objectPool.allocate(BuiltinType.ACIRCLE);
double x = dis.readDouble();
double y = dis.readDouble();
double radius = dis.readDouble();
JPoint jpoint = (JPoint) objectPool.allocate(BuiltinType.APOINT);
jpoint.setValue(x, y);
((JCircle) jObject).setValue(jpoint, radius);
break;
}
case POINT: {
jObject = objectPool.allocate(BuiltinType.APOINT);
double x = dis.readDouble();
double y = dis.readDouble();
((JPoint) jObject).setValue(x, y);
break;
}
case POINT3D: {
jObject = objectPool.allocate(BuiltinType.APOINT3D);
double x = dis.readDouble();
double y = dis.readDouble();
double z = dis.readDouble();
((JPoint3D) jObject).setValue(x, y, z);
break;
}
case LINE: {
jObject = objectPool.allocate(BuiltinType.ALINE);
double x1 = dis.readDouble();
double y1 = dis.readDouble();
double x2 = dis.readDouble();
double y2 = dis.readDouble();
JPoint jpoint1 = (JPoint) objectPool.allocate(BuiltinType.APOINT);
jpoint1.setValue(x1, y1);
JPoint jpoint2 = (JPoint) objectPool.allocate(BuiltinType.APOINT);
jpoint2.setValue(x2, y2);
((JLine) jObject).setValue(jpoint1, jpoint2);
break;
}
case POLYGON: {
jObject = objectPool.allocate(BuiltinType.APOLYGON);
short numberOfPoints = dis.readShort();
List<JPoint> points = new ArrayList<JPoint>();
for (int i = 0; i < numberOfPoints; i++) {
JPoint p1 = (JPoint) objectPool.allocate(BuiltinType.APOINT);
p1.setValue(dis.readDouble(), dis.readDouble());
points.add(p1);
}
((JPolygon) jObject).setValue(points);
break;
}
case RECTANGLE: {
jObject = objectPool.allocate(BuiltinType.ARECTANGLE);
double x1 = dis.readDouble();
double y1 = dis.readDouble();
double x2 = dis.readDouble();
double y2 = dis.readDouble();
JPoint jpoint1 = (JPoint) objectPool.allocate(BuiltinType.APOINT);
jpoint1.setValue(x1, y1);
JPoint jpoint2 = (JPoint) objectPool.allocate(BuiltinType.APOINT);
jpoint2.setValue(x2, y2);
((JRectangle) jObject).setValue(jpoint1, jpoint2);
break;
}
case UNORDEREDLIST: {
AUnorderedListType listType = (AUnorderedListType) type;
IAType elementType = listType.getItemType();
jObject = objectPool.allocate(listType);
boolean fixedSize = false;
ATypeTag tag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(dis.readByte());
switch (tag) {
case STRING:
case RECORD:
case ORDEREDLIST:
case UNORDEREDLIST:
case ANY:
fixedSize = false;
break;
default:
fixedSize = true;
break;
}
dis.readInt(); // list size
int numberOfitems;
numberOfitems = dis.readInt();
if (numberOfitems > 0) {
if (!fixedSize) {
for (int i = 0; i < numberOfitems; i++)
dis.readInt();
}
for (int i = 0; i < numberOfitems; i++) {
IJObject v = (IJObject) getJType(elementType.getTypeTag(), elementType, dis, objectPool);
((JUnorderedList) jObject).add(v);
}
}
break;
}
case ORDEREDLIST: {
AOrderedListType listType = (AOrderedListType) type;
IAType elementType = listType.getItemType();
jObject = objectPool.allocate(listType);
boolean fixedSize = false;
ATypeTag tag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(dis.readByte());
switch (tag) {
case STRING:
case RECORD:
case ORDEREDLIST:
case UNORDEREDLIST:
case ANY:
fixedSize = false;
break;
default:
fixedSize = true;
break;
}
dis.readInt(); // list size
int numberOfitems;
numberOfitems = dis.readInt();
if (numberOfitems > 0) {
if (!fixedSize) {
for (int i = 0; i < numberOfitems; i++)
dis.readInt();
}
for (int i = 0; i < numberOfitems; i++) {
IJObject v = (IJObject) getJType(elementType.getTypeTag(), elementType, dis, objectPool);
((JOrderedList) jObject).add(v);
}
}
break;
}
case RECORD:
ARecordType recordType = (ARecordType) type;
int numberOfSchemaFields = recordType.getFieldTypes().length;
byte[] recordBits = dis.getInputStream().getArray();
boolean isExpanded = false;
int s = dis.getInputStream().getPosition();
int recordOffset = s;
int openPartOffset = 0;
int offsetArrayOffset = 0;
int[] fieldOffsets = new int[numberOfSchemaFields];
IJObject[] closedFields = new IJObject[numberOfSchemaFields];
if (recordType == null) {
openPartOffset = s + AInt32SerializerDeserializer.getInt(recordBits, s + 6);
s += 8;
isExpanded = true;
} else {
dis.skip(4); // reading length is not required.
if (recordType.isOpen()) {
isExpanded = dis.readBoolean();
if (isExpanded) {
openPartOffset = s + dis.readInt(); // AInt32SerializerDeserializer.getInt(recordBits, s + 6);
} else {
// do nothing s += 6;
}
} else {
// do nothing s += 5;
}
}
if (numberOfSchemaFields > 0) {
int numOfSchemaFields = dis.readInt(); //s += 4;
int nullBitMapOffset = 0;
boolean hasNullableFields = NonTaggedFormatUtil.hasNullableField(recordType);
if (hasNullableFields) {
nullBitMapOffset = dis.getInputStream().getPosition();//s
offsetArrayOffset = dis.getInputStream().getPosition() //s
+ (numberOfSchemaFields % 8 == 0 ? numberOfSchemaFields / 8
: numberOfSchemaFields / 8 + 1);
} else {
offsetArrayOffset = dis.getInputStream().getPosition();
}
for (int i = 0; i < numberOfSchemaFields; i++) {
fieldOffsets[i] = dis.readInt(); // AInt32SerializerDeserializer.getInt(recordBits, offsetArrayOffset) + recordOffset;
// offsetArrayOffset += 4;
}
for (int fieldNumber = 0; fieldNumber < numberOfSchemaFields; fieldNumber++) {
if (hasNullableFields) {
byte b1 = recordBits[nullBitMapOffset + fieldNumber / 8];
int p = 1 << (7 - (fieldNumber % 8));
if ((b1 & p) == 0) {
// set null value (including type tag inside)
//fieldValues.add(nullReference);
continue;
}
}
IAType[] fieldTypes = recordType.getFieldTypes();
ATypeTag fieldValueTypeTag = null;
IAType fieldType = fieldTypes[fieldNumber];
if (fieldTypes[fieldNumber].getTypeTag() == ATypeTag.UNION) {
if (NonTaggedFormatUtil.isOptionalField((AUnionType) fieldTypes[fieldNumber])) {
fieldType = ((AUnionType) fieldTypes[fieldNumber]).getUnionList().get(
NonTaggedFormatUtil.OPTIONAL_TYPE_INDEX_IN_UNION_LIST);
fieldValueTypeTag = fieldType.getTypeTag();
// fieldValueLength = NonTaggedFormatUtil.getFieldValueLength(recordBits,
// fieldOffsets[fieldNumber], typeTag, false);
}
} else {
fieldValueTypeTag = fieldTypes[fieldNumber].getTypeTag();
}
closedFields[fieldNumber] = getJType(fieldValueTypeTag, fieldType, dis, objectPool);
}
}
if (isExpanded) {
int numberOfOpenFields = dis.readInt();
String[] fieldNames = new String[numberOfOpenFields];
IAType[] fieldTypes = new IAType[numberOfOpenFields];
IJObject[] openFields = new IJObject[numberOfOpenFields];
for (int i = 0; i < numberOfOpenFields; i++) {
dis.readInt();
dis.readInt();
}
for (int i = 0; i < numberOfOpenFields; i++) {
fieldNames[i] = AStringSerializerDeserializer.INSTANCE.deserialize(dis).getStringValue();
ATypeTag openFieldTypeTag = SerializerDeserializerUtil.deserializeTag(dis);
openFields[i] = getJType(openFieldTypeTag, null, dis, objectPool);
fieldTypes[i] = openFields[i].getIAObject().getType();
}
ARecordType openPartRecType = new ARecordType(null, fieldNames, fieldTypes, true);
if (numberOfSchemaFields > 0) {
ARecordType mergedRecordType = mergeRecordTypes(recordType, openPartRecType);
IJObject[] mergedFields = mergeFields(closedFields, openFields);
jObject = objectPool.allocate(recordType);
return new JRecord(mergedRecordType, mergedFields);
} else {
return new JRecord(recordType, openFields);
}
} else {
return new JRecord(recordType, closedFields);
}
default:
throw new IllegalStateException("Argument type: " + typeTag);
}
return jObject;
}
private static IJObject[] mergeFields(IJObject[] closedFields, IJObject[] openFields) {
IJObject[] fields = new IJObject[closedFields.length + openFields.length];
int i = 0;
for (; i < closedFields.length; i++) {
fields[i] = closedFields[i];
}
for (int j = 0; j < openFields.length; j++) {
fields[closedFields.length + j] = openFields[j];
}
return fields;
}
private static ARecordType mergeRecordTypes(ARecordType recType1, ARecordType recType2) throws AsterixException {
String[] fieldNames = new String[recType1.getFieldNames().length + recType2.getFieldNames().length];
IAType[] fieldTypes = new IAType[recType1.getFieldTypes().length + recType2.getFieldTypes().length];
int i = 0;
for (; i < recType1.getFieldNames().length; i++) {
fieldNames[i] = recType1.getFieldNames()[i];
fieldTypes[i] = recType1.getFieldTypes()[i];
}
for (int j = 0; j < recType2.getFieldNames().length; i++, j++) {
fieldNames[i] = recType2.getFieldNames()[j];
fieldTypes[i] = recType2.getFieldTypes()[j];
}
return new ARecordType(null, fieldNames, fieldTypes, true);
}
}