package com.revolsys.gis.esri.gdb.file.test;
import java.io.File;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Date;
import com.revolsys.beans.Classes;
import com.revolsys.geometry.model.Geometry;
import com.revolsys.geometry.model.LineString;
import com.revolsys.geometry.model.Lineal;
import com.revolsys.geometry.model.Polygonal;
import com.revolsys.geometry.model.Punctual;
import com.revolsys.io.endian.LittleEndianRandomAccessFile;
import com.revolsys.record.schema.FieldDefinition;
import com.revolsys.record.schema.RecordDefinition;
public class FileGdbTable {
private final long fieldHeaderOffset = 40;
private final LittleEndianRandomAccessFile out;
public FileGdbTable(final File file) {
this.out = new LittleEndianRandomAccessFile(file, "rw");
}
public FileGdbTable(final File file, final RecordDefinition recordDefinition) {
this.out = new LittleEndianRandomAccessFile(file, "rw");
writeFieldHeader(recordDefinition);
}
private void writeFieldHeader(final FieldDefinition field) {
final String name = field.getName();
writeUtf16String255(name);
final Class<?> fieldClass = field.getTypeClass();
if (Byte.class.isAssignableFrom(fieldClass) || Short.class.isAssignableFrom(fieldClass)) {
this.out.write(0);
} else if (Integer.class.isAssignableFrom(fieldClass) || Long.class.isAssignableFrom(fieldClass)
|| BigInteger.class.isAssignableFrom(fieldClass)) {
this.out.write(1);
} else if (Float.class.isAssignableFrom(fieldClass)) {
this.out.write(2);
} else if (Double.class.isAssignableFrom(fieldClass)
|| BigDecimal.class.isAssignableFrom(fieldClass)) {
this.out.write(3);
} else if (Date.class.isAssignableFrom(fieldClass)) {
this.out.write(5);
} else if (Geometry.class.isAssignableFrom(fieldClass)) {
this.out.write(7);
} else {
this.out.write(4);
int fieldLength = field.getLength();
if (fieldLength == 0) {
fieldLength = 255;
}
this.out.writeLEInt(fieldLength);
}
}
private void writeFieldHeader(final RecordDefinition recordDefinition) {
byte geometryType = 0;
final FieldDefinition geometryField = recordDefinition.getGeometryField();
if (geometryField != null) {
final Class<?> geometryClass = geometryField.getTypeClass();
if (Punctual.class.isAssignableFrom(geometryClass)) {
geometryType = 1;
} else if (LineString.class.isAssignableFrom(geometryClass)) {
geometryType = 3;
} else if (Lineal.class.isAssignableFrom(geometryClass)) {
geometryType = 3;
} else if (Polygonal.class.isAssignableFrom(geometryClass)) {
geometryType = 4;
} else {
throw new IllegalArgumentException(
"Geometry type not supported " + Classes.className(geometryClass));
}
}
final short fieldCount = (short)(recordDefinition.getFieldCount() + 1);
this.out.writeLEInt(0);
this.out.writeLEInt(4); // Version
this.out.write(geometryType);
this.out.write(0x03);
this.out.write(0);
this.out.write(0);
this.out.writeLEShort(fieldCount);
for (final FieldDefinition field : recordDefinition.getFields()) {
writeFieldHeader(field);
}
// Update field header size
final long offset = this.out.getFilePointer();
final int fieldHeaderSize = (int)(offset - 14 - this.fieldHeaderOffset);
this.out.seek(this.fieldHeaderOffset);
this.out.write(fieldHeaderSize);
this.out.seek(offset);
this.out.write(0xDE);
this.out.write(0xAD);
this.out.write(0xBE);
this.out.write(0xEF);
}
private void writeUtf16String255(final String string) {
final int length = string.length();
if (length > 255) {
throw new IllegalArgumentException("Exceeds maximum string length " + length + " > 255");
} else {
this.out.write(length);
for (int i = 0; i < length; i++) {
final char c = string.charAt(i);
this.out.writeLEShort((short)c);
}
}
}
}