/***********************************************************************************************************************
*
* Copyright (C) 2010-2013 by the Stratosphere project (http://stratosphere.eu)
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
**********************************************************************************************************************/
package eu.stratosphere.api.avro;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;
import org.apache.avro.mapred.AvroValue;
import org.apache.avro.reflect.ReflectDatumReader;
import org.apache.avro.reflect.ReflectDatumWriter;
import eu.stratosphere.types.Key;
import eu.stratosphere.util.ReflectionUtil;
public abstract class AvroBaseValue<T> extends AvroValue<T> implements Key<AvroBaseValue<T>> {
private static final long serialVersionUID = 1L;
public AvroBaseValue() {}
public AvroBaseValue(T datum) {
super(datum);
}
// --------------------------------------------------------------------------------------------
// Serialization / Deserialization
// --------------------------------------------------------------------------------------------
private ReflectDatumWriter<T> writer;
private ReflectDatumReader<T> reader;
private DataOutputEncoder encoder;
private DataInputDecoder decoder;
@Override
public void write(DataOutput out) throws IOException {
// the null flag
if (datum() == null) {
out.writeBoolean(false);
} else {
out.writeBoolean(true);
DataOutputEncoder encoder = getEncoder();
encoder.setOut(out);
getWriter().write(datum(), encoder);
}
}
@Override
public void read(DataInput in) throws IOException {
// the null flag
if (in.readBoolean()) {
DataInputDecoder decoder = getDecoder();
decoder.setIn(in);
datum(getReader().read(datum(), decoder));
}
}
private ReflectDatumWriter<T> getWriter() {
if (this.writer == null) {
@SuppressWarnings("unchecked")
Class<T> clazz = (Class<T>) datum().getClass();
this.writer = new ReflectDatumWriter<T>(clazz);
}
return this.writer;
}
private ReflectDatumReader<T> getReader() {
if (this.reader == null) {
Class<T> datumClass = ReflectionUtil.getTemplateType1(getClass());
this.reader = new ReflectDatumReader<T>(datumClass);
}
return this.reader;
}
private DataOutputEncoder getEncoder() {
if (this.encoder == null) {
this.encoder = new DataOutputEncoder();
}
return this.encoder;
}
private DataInputDecoder getDecoder() {
if (this.decoder == null) {
this.decoder = new DataInputDecoder();
}
return this.decoder;
}
// --------------------------------------------------------------------------------------------
// Hashing / Equality
// --------------------------------------------------------------------------------------------
@Override
public int hashCode() {
return datum() == null ? 0 : datum().hashCode();
}
@Override
public boolean equals(Object obj) {
if (obj.getClass() == this.getClass()) {
Object otherDatum = ((AvroBaseValue<?>) obj).datum();
Object thisDatum = datum();
if (thisDatum == null) {
return otherDatum == null;
} else {
return thisDatum.equals(otherDatum);
}
} else {
return false;
}
}
@Override
public String toString() {
return "AvroBaseValue (" + datum() + ")";
}
@SuppressWarnings("unchecked")
@Override
public int compareTo(AvroBaseValue<T> o) {
Object otherDatum = o.datum();
Object thisDatum = datum();
if (thisDatum == null) {
return otherDatum == null ? 0 : -1;
} else {
return otherDatum == null ? 1: ((Comparable<Object>) thisDatum).compareTo(otherDatum);
}
}
}