package er.indexing.storage;
import java.io.IOException;
import org.apache.lucene.store.IndexInput;
import org.apache.lucene.store.IndexOutput;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.webobjects.eocontrol.EOEditingContext;
import com.webobjects.foundation.NSData;
import com.webobjects.foundation.NSMutableData;
import com.webobjects.foundation.NSMutableRange;
import com.webobjects.foundation.NSTimestamp;
public class ERIFile extends _ERIFile {
/**
* Do I need to update serialVersionUID?
* See section 5.6 <cite>Type Changes Affecting Serialization</cite> on page 51 of the
* <a href="http://java.sun.com/j2se/1.4/pdf/serial-spec.pdf">Java Object Serialization Spec</a>
*/
private static final long serialVersionUID = 1L;
private static final Logger log = LoggerFactory.getLogger(ERIFile.class);
public static final ERIFileClazz clazz = new ERIFileClazz();
public static class ERIFileClazz extends _ERIFile._ERIFileClazz {
/* more clazz methods here */
}
public interface Key extends _ERIFile.Key {}
private class EOFIndexOutput extends IndexOutput {
long filePointer = 0;
long fileLength = 0;
NSMutableData data;
boolean dirty = false;
public EOFIndexOutput(NSData contentData) {
data = new NSMutableData(contentData);
fileLength = data.length();
}
private NSMutableData data() {
return data;
}
@Override
public void close() throws IOException {
flush();
}
@Override
public void flush() throws IOException {
if (dirty) {
if (length() < data().length()) {
data().setLength((int) length());
}
editingContext().lock();
try {
setContentData(data());
editingContext().saveChanges();
} finally {
editingContext().unlock();
}
}
dirty = false;
}
@Override
public long getFilePointer() {
return filePointer;
}
@Override
public long length() {
return fileLength;
}
@Override
public void seek(long l) throws IOException {
assureLength(l);
filePointer = l;
}
private void assureLength(long len) {
if(length() < len) {
if(data().length() < len) {
data().setLength((int) len + 128000);
}
fileLength = len;
dirty = true;
}
}
@Override
public void writeByte(byte byte0) throws IOException {
assureLength(filePointer+1);
NSMutableRange range = new NSMutableRange((int)filePointer, 1);
byte[] bytes = data().bytesNoCopy(range);
bytes[(int) filePointer] = byte0;
filePointer += 1;
dirty = true;
}
@Override
public void writeBytes(byte[] abyte0, int offset, int len) throws IOException {
assureLength(filePointer+len);
NSMutableRange range = new NSMutableRange((int)filePointer, len);
byte[] bytes = data().bytesNoCopy(range);
System.arraycopy(abyte0, offset, bytes, (int)filePointer, len);
filePointer += len;
dirty = true;
}
}
private class EOFIndexInput extends IndexInput {
long filePointer = 0;
NSData data;
public EOFIndexInput(NSData contentData) {
data = contentData;
}
private NSData data() {
return data;
}
@Override
public void close() throws IOException {
filePointer = 0;
}
@Override
public long getFilePointer() {
return filePointer;
}
@Override
public long length() {
return data().length();
}
private void assureLength(long len) throws IOException {
if(len > length()) {
throw new IOException("Not enough data: " + len + " vs " + length());
}
}
@Override
public byte readByte() throws IOException {
assureLength(filePointer+1);
return data().bytes((int)filePointer++, 1)[0];
}
@Override
public void readBytes(byte[] abyte0, int offset, int len) throws IOException {
assureLength(filePointer+len);
System.arraycopy(data().bytesNoCopy(new NSMutableRange((int)filePointer, len)), (int)filePointer, abyte0, offset, len);
filePointer += len;
}
@Override
public void seek(long l) throws IOException {
assureLength(l);
filePointer = l;
}
}
@Override
public void didInsert() {
super.didInsert();
log.debug("Did create: {}", name());
}
@Override
public void didUpdate() {
super.didUpdate();
log.debug("Did update: {}->{}", name(), length());
}
@Override
public void didDelete(EOEditingContext ec) {
super.didUpdate();
log.debug("Did delete: {}->{}", name(), length());
}
@Override
public void init(EOEditingContext ec) {
super.init(ec);
ERIFileContent content = ERIFileContent.clazz.createAndInsertObject(ec);
setContent(content);
setContentData(new NSData());
}
private void setContentData(NSData data) {
setLastModified(new NSTimestamp());
setLength((long)data.length());
content().setContent(data);
}
private NSData contentData() {
return content().content();
}
public void touch() {
setLastModified(new NSTimestamp());
editingContext().saveChanges();
}
public IndexInput openInput() {
return new EOFIndexInput(contentData());
}
public long timestamp() {
return lastModified().getTime();
}
public IndexOutput createOutput() {
return new EOFIndexOutput(contentData());
}
}