import dk.vajhoej.record.FieldType; import dk.vajhoej.record.Struct; import dk.vajhoej.record.StructField; @Struct public class Data { @StructField(n=0,type=FieldType.INT4) private int iv; @StructField(n=1,type=FieldType.FP8) private double xv; @StructField(n=2,type=FieldType.FIXSTR,length=8,encoding="ISO-8859-1") private String sv; public int getIv() { return iv; } public void setIv(int iv) { this.iv = iv; } public double getXv() { return xv; } public void setXv(double xv) { this.xv = xv; } public String getSv() { return sv; } public void setSv(String sv) { this.sv = sv; } }
The class got a @Struct annotation. Each field in the class got a @StructField annotation with an element n that determines the order of the fields and an element type that describes the datatype in the native struct plus some optional elements that are needed for some field types.
// read StructReader sr = new StructReader(somebytearray); Data obj = sr.read(Data.class); // write Data obj = new Data(); ... StructWriter sw = new StructWriter(); sw.write(obj); byte[] ba = sw.GetBytes();
To specify a field as an array put an @Array annotation on the field and make the Java type an array.
To specify a field as a sub struct just specify type=FieldType.STRUCT in the @StructField annotation.
The Record library supports polymorphism in records.
You must use the @Selector annotation on the last field in the super class.
import dk.vajhoej.record.Alignment; import dk.vajhoej.record.FieldType; import dk.vajhoej.record.Struct; import dk.vajhoej.record.StructField; import dk.vajhoej.record.Selector; import dk.vajhoej.record.SubType; @Struct public class Data { @StructField(n=0,type=FieldType.INT4) protected int id; @StructField(n=1,type=FieldType.INT4) @Selector(subtypes={@SubType(value=1,type=DataX.class), @SubType(value=3,type=DataY.class)}) protected int typ; public int getId() { return id; } public void setId(int id) { this.id = id; } public int getTyp() { return typ; } public void setTyp(int typ) { this.typ = typ; } }
Usage is as simple as:
Data obj = sr.read(Data.class);
This will actually read DataX or DataY instances depending on the value of the typ field.
Note that the numbering of the struct fields continue in the sub class - it does not reset to zero.
The API described above read/write by runtime analyzing the class and interpreting the output from the analysis.
The fast API analyze the class once and generate Java code dynamically to read/write using the Javassist library.
The annotation son the POJO classes are the same.
Note that not all features are supported in fast API - anything dynamic with length providers etc. does not work.
// read FastStructReader<Data> fsr = CodeGen.genReader(Data.class); fsr.init(somebytearray); Data obj = fsr.read(Data.class); // write Data obj = new Data(); ... FastStructWriter fsw = CodGen.genWriter(Data.class); fsw.write(obj); byte[] ba = sw.GetBytes();
// read Map<Class<? extends Data>, FastStructReader<? extends Data>> map = new HashMap<Class<? extends Data>, FastStructReader<? extends Data>>(); map.put(DataX.class, CodeGen.genReader(DataX.class)); map.put(DataY.class, CodeGen.genReader(DataY.class)); FastStructReader<Data> fsr = new CompositFastStructReader<Data>(Data.class, map); fsr.init(somebytearray); Data obj = fsr.read(Data.class); // write Data obj = new Data(); ... Map<Class<? extends Data>, FastStructReader<? extends Data>> map = new HashMap<Class<? extends Data>, FastStructReader<? extends Data>>(); map.put(DataX.class, CodeGen.genReader(DataX.class)); map.put(DataY.class, CodeGen.genReader(DataY.class)); FastStructWriter<Object> fsw = new CompositFastStructWriter(map); fsw.write(obj); byte[] ba = sw.GetBytes();