/*
Copyright (C) 2007 Mobixess Inc. http://www.java-objects-database.com
This file is part of the JODB (Java Objects Database) open source project.
JODB is free software; you can redistribute it and/or modify it under
the terms of version 2 of the GNU General Public License as published
by the Free Software Foundation.
JODB is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package com.mobixess.jodb.core.query;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.BitSet;
import com.mobixess.jodb.core.JodbIOException;
import com.mobixess.jodb.core.io.IOBase;
import com.mobixess.jodb.core.io.JODBOperationContext;
import com.mobixess.jodb.core.io.ObjectDataContainer;
import com.mobixess.jodb.core.io.ObjectDataContainer.FieldRecord;
import com.mobixess.jodb.core.io.ObjectDataContainer.FieldsIterator;
import com.mobixess.jodb.core.transaction.TransactionUtils;
import com.mobixess.jodb.core.transaction.JODBSession.ClassDescriptor;
import com.mobixess.jodb.util.IntVector;
public class NQueryDataObjectProxy {
private long _objectOffset;
private ClassDescriptor _classDescriptor;
private BitSet _requestedFields = new BitSet();
private ByteBuffer[] _fieldValues;
private JODBOperationContext _context;
private ObjectDataContainer _container;
private IntVector _acceptedClassIds = new IntVector();
private IntVector _rejectedClassIds = new IntVector();
private FieldsIterator _fieldsIterator;
public NQueryDataObjectProxy() {
_container = TransactionUtils.getObjectDataContainerCache().pullObjectDataContainer();
}
public void setTargetClass(JODBOperationContext context, ClassDescriptor classDescriptor) throws IOException{
_fieldsIterator = null;
_acceptedClassIds.setSize(0);
_rejectedClassIds.setSize(0);
if(_fieldValues == null || _fieldValues.length != classDescriptor.getObjectFieldsTotal()){
_fieldValues = new ByteBuffer[classDescriptor.getAllFields().length];
}else{
Arrays.fill(_fieldValues, null);
}
_context = context;
_classDescriptor = classDescriptor;
_acceptedClassIds.addElement(_context.getBase().getClassTypeSubstitutionID(classDescriptor.getType().getName()));
_requestedFields.set(0, _fieldValues.length, false);
}
public boolean setObjectData(long objectOffset, int indexingField, ByteBuffer indexData) throws IOException {
_objectOffset = objectOffset;
_fieldsIterator = null;
if(indexingField>=0 && indexData!=null){
int fieldPos = _classDescriptor.getFieldIndexForID(indexingField);
if(fieldPos>=0){
setDataForField(fieldPos, indexData);
}
}else{
_container.reset();
_fieldsIterator = _container.readObject(_context, objectOffset, true);
int classId = _container.getOriginalClassType();
if(_acceptedClassIds.indexOf(classId)<0){
if(_rejectedClassIds.indexOf(classId)>-1){
return false;
}
String type = _context.getBase().getClassTypeForID(classId);
ClassDescriptor classDescriptor;
try {
classDescriptor = _context.getSession().getDescriptorForClass(type);
} catch (ClassNotFoundException e) {
throw new JodbIOException(e);
}
if(_classDescriptor.getType().isAssignableFrom(classDescriptor.getType())){
_acceptedClassIds.addElement(classId);
}else{
_rejectedClassIds.addElement(classId);
return false;
}
}
}
_requestedFields.clear();
return true;
}
private ByteBuffer getDataForField(int fieldId){
int fieldPos = _classDescriptor.getFieldIndexForID(fieldId);
if(fieldPos<0){
throw new IllegalArgumentException("field="+fieldId);
}
ensureFieldInitialized(fieldPos);
_fieldValues[fieldPos].rewind();
_requestedFields.set(fieldPos);
return _fieldValues[fieldPos];
}
public boolean isFieldRequested(int fieldId){
int fieldPos = _classDescriptor.getFieldIndexForID(fieldId);
return _requestedFields.get(fieldPos);
}
private void ensureFieldInitialized(int index){
if(_requestedFields.get(index)){
return;
}
try{
if(_fieldsIterator == null){
_container.reset();
_fieldsIterator = _container.readObject(_context, _objectOffset, true);
}
FieldRecord record = _container.getRecordCache();
IOBase base = _context.getBase();
final String stringClassName = String.class.getName();
while(_fieldsIterator.hasNext()){
_fieldsIterator.next(record, base, false);
int fieldPos = _classDescriptor.getFieldIndexForID(record._fieldID);
if(fieldPos < 0) {
continue;
}
if(record._fieldTypeName.equals(stringClassName)){
record._primitiveRawDataBuffer.clear();//TODO optimize: iterator should directly write offset to buffer
record._primitiveRawDataBuffer.limit(16);
record._primitiveRawDataBuffer.putLong(0, record._objectOffset);
//record._primitiveRawDataBuffer.flip();
}
setDataForField(fieldPos, record._primitiveRawDataBuffer);
}
}catch (IOException e) {
throw new RuntimeException(e);
}
}
private void setDataForField(int fieldIndex, ByteBuffer data){
if(_fieldValues[fieldIndex]==null){
_fieldValues[fieldIndex] = ByteBuffer.allocate(data.capacity());
}else{
_fieldValues[fieldIndex].clear();
}
_fieldValues[fieldIndex].put(data);
}
public float getValue_float(int fieldId){
return getDataForField(fieldId).getFloat();
};
public double getValue_double(int fieldId){
return getDataForField(fieldId).getDouble();
};
public long getValue_long(int fieldId){
return getDataForField(fieldId).getLong();
};
public int getValue_int(int fieldId){
return getDataForField(fieldId).getInt();
};
public short getValue_short(int fieldId){
return getDataForField(fieldId).getShort();
};
public char getValue_char(int fieldId){
return getDataForField(fieldId).getChar();
};
public byte getValue_byte(int fieldId){
return getDataForField(fieldId).get();
};
public String getValue_String(int fieldId){
long id = getValue_long(fieldId);
try {
return (String) _context.getSession().getObjectForOffset(id);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}