package com.taobao.tddl.executor.codec;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.taobao.tddl.executor.record.CloneableRecord;
import com.taobao.tddl.executor.record.FixedLengthRecord;
import com.taobao.tddl.optimizer.config.table.ColumnMeta;
import com.taobao.tddl.optimizer.core.datatype.DataType;
import com.taobao.tddl.optimizer.core.datatype.DataType.DecodeResult;
/**
* @author jianxing <jianxing.qx@taobao.com>
*/
public class FixedLengthCodec implements RecordCodec<byte[]> {
List<ColumnMeta> columns;
Map<String, Integer> index;
int sizeCache = 0;
public FixedLengthCodec(List<ColumnMeta> columns){
this.columns = columns;
sizeCache = columns.size();
this.index = new HashMap(sizeCache);
for (ColumnMeta key : columns) {
if (!index.containsKey(key.getName())) {
index.put(key.getName(), index.size());
}
}
}
@Override
public byte[] encode(CloneableRecord record) {
int length = calculateEncodedLength(record, columns);
byte[] dst = new byte[length];
int offset = 0;
for (ColumnMeta c : columns) {
Object v = record.get(c.getName());
DataType t = c.getDataType();
if (v == null && !c.isNullable()) {
throw new RuntimeException(c + " is not nullable.");
}
offset += t.encodeToBytes(v, dst, offset);
// offset += encode1(v, t, dst, offset);
}
return dst;
}
private int calculateEncodedLength(CloneableRecord record, List<ColumnMeta> columns) {
int length = 0;
for (ColumnMeta c : columns) {
Object v = record.get(c.getName());
DataType t = c.getDataType();
length += t.getLength(v);
// if (t == DATA_TYPE.LONG_VAL) {
// if (v == null) {
// length += 1;
// } else {
// length += 9;
// }
// } else if (t == DATA_TYPE.INT_VAL) {
// if (v == null) {
// length += 1;
// } else {
// length += 5;
// }
// } else if (t == DATA_TYPE.STRING_VAL) {
//
// if (v != null && !(v instanceof String)) {
// v = v.toString();
// }
// length += KeyEncoder.calculateEncodedStringLength((String) v);
// } else if (t == DATA_TYPE.FLOAT_VAL) {
// length += 4;
// } else if (t == DATA_TYPE.BYTES_VAL) {
// length += KeyEncoder.calculateEncodedLength((byte[]) v);
// } else if (t == DATA_TYPE.DATE_VAL || t ==
// DATA_TYPE.TIMESTAMP_VAL) {
// if (v == null) {
// length += 1;
// } else {
//
// length += 9;
// }
// } else {
// throw new RuntimeException("Column:" + c.getName() +
// " DATA_TYPE=" + t + "is not fixed length .");
// }
}
return length;
}
// private int encode1(Object v, DATA_TYPE t, byte[] dst, int offset) {
// if (t == DATA_TYPE.LONG_VAL) {
//
// if (v instanceof BigDecimal) return DataEncoder.encode(new
// Long(((BigDecimal) v).longValue()), dst, offset);
// return DataEncoder.encode((Long) v, dst, offset);
//
// } else if (t == DATA_TYPE.INT_VAL) {
// if (v instanceof BigDecimal) return DataEncoder.encode(new
// Integer(((BigDecimal) v).intValue()),
// dst,
// offset);
// return DataEncoder.encode((Integer) v, dst, offset);
// } else if (t == DATA_TYPE.STRING_VAL) {
// if (v != null && !(v instanceof String)) {
// v = v.toString();
// }
// return KeyEncoder.encode((String) v, dst, offset);
// } else if (t == DATA_TYPE.FLOAT_VAL) {
// if (v instanceof BigDecimal) DataEncoder.encode(new Float(((BigDecimal)
// v).floatValue()), dst, offset);
// else DataEncoder.encode((Float) v, dst, offset);
// return 4;
// } else if (t == DATA_TYPE.DOUBLE_VAL) {
// if (v instanceof BigDecimal) DataEncoder.encode(new Double(((BigDecimal)
// v).doubleValue()), dst, offset);
// else DataEncoder.encode((Double) v, dst, offset);
// return 4;
// } else if (t == DATA_TYPE.BYTES_VAL) {
// return KeyEncoder.encode((byte[]) v, dst, offset);
// } else if (t == DATA_TYPE.DATE_VAL || t == DATA_TYPE.TIMESTAMP_VAL) {
// if (v != null && !(v instanceof Long)) {
// if (v instanceof Date) {
// v = ((Date) v).getTime();
// } else {
// v = ExecUtils.convertStringToDate(v.toString()).getTime();
// }
// }
// return DataEncoder.encode((Long) v, dst, offset);
//
// } else {
// throw new RuntimeException("DATA_TYPE=" + t + "is not supported yet.");
// }
// }
@Override
public CloneableRecord decode(byte[] bytes) {
if (bytes == null) {
return null;
}
FixedLengthRecord record = new FixedLengthRecord(index, sizeCache);
int offset = 0;
for (int i = 0; i < columns.size(); i++) {
ColumnMeta c = columns.get(i);
DataType t = c.getDataType();
Object v = null;
DecodeResult res = t.decodeFromBytes(bytes, offset);
v = res.value;
offset += res.length;
// try {
// if (t == DATA_TYPE.LONG_VAL) {
// v = DataDecoder.decodeLongObj(bytes, offset);
// if (v == null) {
// offset += 1;
// } else {
// offset += 9;
// }
// } else if (t == DATA_TYPE.INT_VAL) {
// v = DataDecoder.decodeIntegerObj(bytes, offset);
// if (v == null) {
// offset += 1;
// } else {
// offset += 5;
// }
// } else if (t == DATA_TYPE.STRING_VAL) {
// String[] val = new String[1];
// offset += KeyDecoder.decodeString(bytes, offset, val);
// v = val[0];
// } else if (t == DATA_TYPE.FLOAT_VAL) {
// v = DataDecoder.decodeFloatObj(bytes, offset);
// offset += 4;
// } else if (t == DATA_TYPE.BYTES_VAL) {
// byte[][] val = new byte[1][];
// offset += KeyDecoder.decode(bytes, offset, val);
// v = val[0];
// } else if (t == DATA_TYPE.DATE_VAL || t ==
// DATA_TYPE.TIMESTAMP_VAL) {
//
// v = DataDecoder.decodeLongObj(bytes, offset);
//
// if (v == null) {
// offset += 1;
// } else {
// v = new Date((Long) v);
// offset += 9;
// }
// } else {
// throw new RuntimeException("DATA_TYPE=" + t +
// "is not supported yet.");
// }
// } catch (CorruptEncodingException ex) {
// throw new RuntimeException("CorruptEncodingException " + t + " "
// + v, ex);
// }
record.setValueByIndex(index.get(c.getName()), v);
}
return record;
}
@Override
public CloneableRecord newEmptyRecord() {
return new FixedLengthRecord(index, 0);
}
}