package com.ctriposs.baiji.specific;
import com.ctriposs.baiji.exception.BaijiRuntimeException;
import com.ctriposs.baiji.exception.BaijiTypeException;
import com.ctriposs.baiji.generic.PreresolvingDatumWriter;
import com.ctriposs.baiji.io.Encoder;
import com.ctriposs.baiji.schema.EnumSchema;
import com.ctriposs.baiji.schema.RecordSchema;
import com.ctriposs.baiji.schema.Schema;
import com.ctriposs.baiji.schema.SchemaType;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* {@link com.ctriposs.baiji.generic.DatumWriter DatumWriter} for generated Java classes.
*/
public class SpecificDatumWriter<T> extends PreresolvingDatumWriter<T> {
public SpecificDatumWriter(Schema schema) {
super(schema, new SpecificArrayAccess(), new DefaultMapAccess());
}
@Override
protected void writeRecordFields(Object recordObj, RecordFieldWriter[] writers, Encoder encoder) throws IOException {
SpecificRecord record = (SpecificRecord) recordObj;
for (int i = 0; i < writers.length; i++) {
RecordFieldWriter writer = writers[i];
writer._fieldWriter.write(record.get(writer._field.getPos()), encoder);
}
}
@Override
protected ItemWriter resolveEnum(EnumSchema es) {
return new EnumItemWriter(es);
}
private static class EnumItemWriter implements ItemWriter {
private final EnumSchema _schema;
public EnumItemWriter(EnumSchema schema) {
_schema = schema;
}
@Override
public void write(Object value, Encoder encoder) throws IOException {
if (value == null) {
throw new BaijiTypeException("value is null in SpecificDatumWriter.EnumItemWriter.write");
}
encoder.writeEnum(_schema.ordinal(value.toString()));
}
}
@Override
protected boolean unionBranchMatches(Schema sc, Object obj) {
if (obj == null && sc.getType() != SchemaType.NULL) {
return false;
}
switch (sc.getType()) {
case NULL:
return obj == null;
case BOOLEAN:
return obj instanceof Boolean;
case INT:
return obj instanceof Integer;
case LONG:
return obj instanceof Long;
case FLOAT:
return obj instanceof Float;
case DOUBLE:
return obj instanceof Double;
case BYTES:
return obj instanceof byte[];
case STRING:
return obj instanceof String;
case RECORD:
return obj instanceof SpecificRecord &&
(((RecordSchema) ((SpecificRecord) obj).getSchema())).getSchemaName().equals(
((RecordSchema) (sc)).getSchemaName());
case ENUM:
return obj.getClass().isEnum() && ((EnumSchema) sc).getSymbols().contains(obj.toString());
case ARRAY:
return obj instanceof List;
case MAP:
return obj instanceof Map;
case UNION:
return false; // Union directly within another union not allowed!
default:
throw new BaijiRuntimeException("Unknown schema type: " + sc.getType());
}
}
private static class SpecificArrayAccess implements ArrayAccess {
@Override
public void ensureArrayObject(Object value) {
if (!(value instanceof List)) {
throw new BaijiTypeException("Array does not implement non-generic IList");
}
}
@Override
public long getArrayLength(Object value) {
return ((List) value).size();
}
@Override
public void writeArrayValues(Object array, ItemWriter valueWriter, Encoder encoder)
throws IOException {
List list = (List) array;
for (int i = 0; i < list.size(); i++) {
valueWriter.write(list.get(i), encoder);
}
}
}
}