/*
* $Id: $
* $Version: $
*
* Copyright (c) Andres Puusepp 2009
* Copyright (c) Priit J�rv 2013
*
* This file is part of WhiteDB
*
* WhiteDB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* WhiteDB 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 WhiteDB. If not, see <http://www.gnu.org/licenses/>.
*
*/
/** @file WhiteDB.java
* Java API for WhiteDB.
*
*/
package whitedb.driver;
import whitedb.holder.Database;
import whitedb.holder.Record;
import whitedb.holder.Query;
import whitedb.util.FieldComparator;
import whitedb.util.ArgListEntry;
import java.lang.reflect.Field;
import java.util.Collections;
import java.util.Arrays;
public class WhiteDB {
/**************************** Constants ****************************/
public static final int COND_EQUAL = 1;
public static final int COND_NOT_EQUAL = 2;
public static final int COND_LESSTHAN = 4;
public static final int COND_GREATER = 8;
public static final int COND_LTEQUAL = 16;
public static final int COND_GTEQUAL = 32;
/************************** Native methods **************************/
/*
* Db connection: encapsulate in class
*/
private native Database getDatabase(String shmname, int size, boolean local);
private native void deleteLocalDatabase(long dbptr);
private native int detachDatabase(long dbptr);
/*
* Db management: public
*/
public native int deleteDatabase(String shmname);
/*
* Record handling: wrapped in Java functions
*/
private native Record createRecord(long dbptr, int fieldCount);
private native Record getFirstRecord(long dbptr);
private native Record getNextRecord(long dbptr, long rptr);
private native int deleteRecord(long dbptr, long rptr);
private native int getRecordLength(long dbptr, long rptr);
/*
* Read/write field data: wrapped in Java functions
*/
private native int setRecordIntField(long dbptr, long rptr, int field, int value);
private native int getIntFieldValue(long dbptr, long rptr, int field);
private native int setRecordStringField(long dbptr, long rptr, int field, String value);
private native String getStringFieldValue(long dbptr, long rptr, int field);
private native int setRecordBlobField(long dbptr, long rptr, int field, byte[] value);
private native byte[] getBlobFieldValue(long dbptr, long rptr, int field);
/*
* Query functions: wrapped.
*/
private native Query makeQuery(long dbptr, long matchrecptr,
ArgListEntry[] arglist, long rowlimit);
private native void freeQuery(long dbptr, Query query);
private native Record fetchQuery(long dbptr, long queryptr);
/*
* Locking functions: wrapped.
*/
private native long startRead(long dbptr);
private native long endRead(long dbptr, long lock);
private native long startWrite(long dbptr);
private native long endWrite(long dbptr, long lock);
static {
System.loadLibrary("whitedbDriver");
}
/*********************** Connection state ***************************/
private Database database;
private boolean local;
/****************** Class constructor: connect to db ****************/
public WhiteDB() {
this.local = false;
this.database = getDatabase(null, 0, false);
}
public WhiteDB(int size) {
this.local = false;
this.database = getDatabase(null, size, false);
}
public WhiteDB(String shmname) {
this.local = false;
this.database = getDatabase(shmname, 0, false);
}
public WhiteDB(String shmname, int size) {
this.local = false;
this.database = getDatabase(shmname, size, false);
}
public WhiteDB(int size, boolean local) {
this.local = local;
this.database = getDatabase(null, size, local);
}
public WhiteDB(boolean local) {
this.local = local;
this.database = getDatabase(null, 0, local);
}
public void close() {
if(local) {
deleteLocalDatabase(database.pointer);
} else {
detachDatabase(database.pointer);
}
}
/******************** Wrappers for native methods *******************/
public Record createRecord(int fieldCount) {
return createRecord(database.pointer, fieldCount);
}
public Record getFirstRecord() {
return getFirstRecord(database.pointer);
}
public Record getNextRecord(Record record) {
return getNextRecord(database.pointer, record.pointer);
}
public int deleteRecord(Record record) {
return deleteRecord(database.pointer, record.pointer);
}
public int getRecordLength(Record record) {
return getRecordLength(database.pointer, record.pointer);
}
public int setRecordIntField(Record record, int field, int value) {
return setRecordIntField(database.pointer, record.pointer, field, value);
}
public int getIntFieldValue(Record record, int field) {
return getIntFieldValue(database.pointer, record.pointer, field);
}
public int setRecordStringField(Record record, int field, String value) {
return setRecordStringField(database.pointer, record.pointer, field, value);
}
public String getStringFieldValue(Record record, int field) {
return getStringFieldValue(database.pointer, record.pointer, field);
}
public int setRecordBlobField(Record record, int field, byte[] value) {
return setRecordBlobField(database.pointer, record.pointer, field, value);
}
public byte[] getBlobFieldValue(Record record, int field) {
return getBlobFieldValue(database.pointer, record.pointer, field);
}
/****************** Wrappers for query functions ********************/
public Query makeQuery(Record record) {
return makeQuery(database.pointer, record.pointer, null, 0);
}
public Query makeQuery(ArgListEntry[] arglist) {
return makeQuery(database.pointer, 0, arglist, 0);
}
public Query makeQuery(Record record, long rowlimit) {
return makeQuery(database.pointer, record.pointer, null, rowlimit);
}
public Query makeQuery(ArgListEntry[] arglist, long rowlimit) {
return makeQuery(database.pointer, 0, arglist, rowlimit);
}
public void freeQuery(Query query) {
freeQuery(database.pointer, query);
}
public Record fetchQuery(Query query) {
return fetchQuery(database.pointer, query.query);
}
/**************** Wrappers for locking functions ********************/
public long startRead() {
return startRead(database.pointer);
}
public long endRead(long lock) {
return endRead(database.pointer, lock);
}
public long startWrite() {
return startWrite(database.pointer);
}
public long endWrite(long lock) {
return endWrite(database.pointer, lock);
}
/********************* ORM support functions ************************/
public void writeObjectToDatabase(Object object) throws IllegalAccessException {
Field[] declaredFields = object.getClass().getDeclaredFields();
Arrays.sort(declaredFields, new FieldComparator()); //Performance issue, cache sorted fields
Record record = createRecord(database.pointer, declaredFields.length);
for (int i = 0; i < declaredFields.length; i++) {
Integer value = getFieldValue(object, declaredFields[i]);
System.out.println("Writing field: [" + declaredFields[i].getName() + "] with value: " + value);
setRecordIntField(database.pointer, record.pointer, i, value);
}
}
public <T> T readObjectFromDatabase(Class<T> objecClass, Record record) throws IllegalAccessException, InstantiationException {
Field[] declaredFields = objecClass.getDeclaredFields();
Arrays.sort(declaredFields, new FieldComparator()); //Performance issue, cache sorted fields
T object = objecClass.newInstance();
for (int i = 0; i < declaredFields.length; i++) {
int value = getIntFieldValue(database.pointer, record.pointer, i);
System.out.println("Reading field: [" + declaredFields[i].getName() + "] with value: " + value);
setFieldValue(object, declaredFields[i], value);
}
return object;
}
public void setFieldValue(Object object, Field field, int value) throws IllegalAccessException {
field.set(object, value);
}
public Integer getFieldValue(Object object, Field field) throws IllegalAccessException {
return (Integer) field.get(object);
}
}