package mil.nga.giat.geowave.core.ingest.avro;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.apache.avro.Schema;
import org.apache.avro.io.BinaryDecoder;
import org.apache.avro.io.BinaryEncoder;
import org.apache.avro.io.DecoderFactory;
import org.apache.avro.io.EncoderFactory;
import org.apache.avro.specific.SpecificDatumReader;
import org.apache.avro.specific.SpecificDatumWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Generic Avro serializer/deserializer, can convert Avro Java object to a byte
* array and a byte array back to a usable Avro Java object.
*
* @param <T>
* - Base Avro class extended by all generated class files
*/
public class GenericAvroSerializer<T>
{
private final static Logger LOGGER = LoggerFactory.getLogger(GenericAvroSerializer.class);
private static final EncoderFactory ef = EncoderFactory.get();
private static final DecoderFactory df = DecoderFactory.get();
private static final Map<String, SpecificDatumWriter> writers = new HashMap<>();
private static final Map<String, SpecificDatumReader> readers = new HashMap<>();
public GenericAvroSerializer() {}
synchronized public static <T> byte[] serialize(
final T avroObject,
final Schema avroSchema ) {
try {
final ByteArrayOutputStream os = new ByteArrayOutputStream();
final BinaryEncoder encoder = ef.binaryEncoder(
os,
null);
final String schemaName = getSchemaName(avroSchema);
if (!writers.containsKey(schemaName)) {
writers.put(
schemaName,
new SpecificDatumWriter<T>(
avroSchema));
}
final SpecificDatumWriter<T> writer = writers.get(schemaName);
writer.write(
avroObject,
encoder);
encoder.flush();
return os.toByteArray();
}
catch (final IOException e) {
LOGGER.error(
"Unable to serialize Avro record to byte[]: " + e.getMessage(),
e);
return null;
}
}
synchronized public static <T> T deserialize(
final byte[] avroData,
final Schema avroSchema ) {
try {
final BinaryDecoder decoder = df.binaryDecoder(
avroData,
null);
final String schemaName = getSchemaName(avroSchema);
if (!readers.containsKey(schemaName)) {
readers.put(
schemaName,
new SpecificDatumReader<T>(
avroSchema));
}
final SpecificDatumReader<T> reader = readers.get(schemaName);
return reader.read(
null,
decoder);
}
catch (final IOException e) {
LOGGER.error(
"Unable to deserialize byte[] to Avro object: " + e.getMessage(),
e);
return null;
}
}
private static String getSchemaName(
final Schema schema ) {
return schema.getNamespace() + "." + schema.getName();
}
}