package org.reldb.rel.v0.storage.relvars.external.accdb;
import java.io.File;
import java.io.IOException;
import org.reldb.rel.exceptions.ExceptionSemantic;
import org.reldb.rel.v0.generator.Generator;
import org.reldb.rel.v0.storage.RelDatabase;
import org.reldb.rel.v0.storage.relvars.RelvarExternal;
import org.reldb.rel.v0.storage.relvars.RelvarExternalMetadata;
import org.reldb.rel.v0.storage.relvars.RelvarHeading;
import org.reldb.rel.v0.storage.tables.TableCustom;
import org.reldb.rel.v0.types.Heading;
import org.reldb.rel.v0.values.RelTupleFilter;
import org.reldb.rel.v0.values.RelTupleMap;
import org.reldb.rel.v0.values.TupleFilter;
import org.reldb.rel.v0.values.TupleIterator;
import org.reldb.rel.v0.values.TupleIteratorAutokey;
import org.reldb.rel.v0.values.TupleIteratorCount;
import org.reldb.rel.v0.values.TupleIteratorUnique;
import org.reldb.rel.v0.values.Value;
import org.reldb.rel.v0.values.ValueCharacter;
import org.reldb.rel.v0.values.ValueRelation;
import org.reldb.rel.v0.values.ValueTuple;
import org.reldb.rel.v0.vm.Context;
import com.healthmarketscience.jackcess.Column;
import com.healthmarketscience.jackcess.Cursor;
import com.healthmarketscience.jackcess.CursorBuilder;
import com.healthmarketscience.jackcess.Database;
import com.healthmarketscience.jackcess.DatabaseBuilder;
import com.healthmarketscience.jackcess.Row;
import com.healthmarketscience.jackcess.Table;
public class TableACCDB extends TableCustom {
private RelvarACCDBMetadata meta;
private Generator generator;
private DuplicateHandling duplicates;
private Heading fileHeading;
public TableACCDB(String Name, RelvarExternalMetadata metadata, Generator generator, DuplicateHandling duplicates) {
meta = (RelvarACCDBMetadata) metadata;
this.generator = generator;
this.duplicates = duplicates;
RelDatabase database = generator.getDatabase();
RelvarHeading heading = meta.getHeadingDefinition(database);
Heading storedHeading = heading.getHeading();
fileHeading = RelvarACCDBMetadata.getHeading(database, meta.getConnectionString(), duplicates).getHeading();
if (storedHeading.toString().compareTo(fileHeading.toString()) != 0)
throw new ExceptionSemantic("RS0476: Stored ACCDB metadata is " + storedHeading + " but table metadata is " + fileHeading + ". Has the table structure changed?");
meta.checkTableExistence();
}
@Override
public TupleIterator iterator() {
try {
switch (duplicates) {
case DUP_REMOVE: return new TupleIteratorUnique(iteratorRaw());
case DUP_COUNT: return new TupleIteratorUnique(new TupleIteratorCount(iteratorRaw(), generator));
case AUTOKEY: return new TupleIteratorAutokey(iteratorRaw(), generator);
default: throw new ExceptionSemantic("RS0477: Duplicate handling method " + duplicates.toString() + " not supported by ACCDB.");
}
} catch (IOException ioe) {
throw new ExceptionSemantic("RS0478: Error accessing table " + meta.getTable() + " in " + meta.getFileSpec() + " due to: " + ioe);
}
}
@Override
public long getCardinality() {
long count = 0;
TupleIterator iterator = iterator();
try {
while (iterator.hasNext()) {
count++;
iterator.next();
}
} finally {
iterator.close();
}
return count;
}
@Override
public TupleIterator iterator(Generator generator) {
return iterator();
}
private static void notImplemented(String what) {
throw new ExceptionSemantic("RS0475: ACCDB relvars do not yet support " + what + ".");
}
@Override
public boolean contains(Generator generator, ValueTuple tuple) {
TupleIterator iterator = iterator();
try {
while (iterator.hasNext())
if (tuple.equals(iterator.next()))
return true;
} finally {
iterator.close();
}
return false;
}
@Override
public ValueTuple getTupleForKey(Generator generator, ValueTuple tuple) {
return null;
}
@Override
public void setValue(RelvarExternal relvarJDBC, ValueRelation relation) {
notImplemented("assignment");
}
@Override
public long insert(Generator generator, ValueRelation relation) {
notImplemented("INSERT");
return 0;
}
@Override
public long insert(Generator generator, ValueTuple tuple) {
notImplemented("INSERT");
return 0;
}
@Override
public long insertNoDuplicates(Generator generator, ValueRelation relation) {
notImplemented("INSERT");
return 0;
}
@Override
public void purge() {
notImplemented("DELETE");
}
@Override
public void delete(Generator generator, ValueTuple tuple) {
notImplemented("DELETE");
}
@Override
public long delete(Generator generator, RelTupleFilter relTupleFilter) {
notImplemented("DELETE");
return 0;
}
@Override
public long delete(Generator generator, TupleFilter filter) {
notImplemented("DELETE");
return 0;
}
@Override
public long delete(Context context, ValueRelation tuplesToDelete, boolean errorIfNotIncluded) {
notImplemented("DELETE");
return 0;
}
@Override
public long update(Generator generator, RelTupleMap relTupleMap) {
notImplemented("UPDATE");
return 0;
}
@Override
public long update(Generator generator, RelTupleFilter relTupleFilter, RelTupleMap relTupleMap) {
notImplemented("UPDATE");
return 0;
}
private ValueTuple toTuple(Table table, Row row) {
Value[] rowData = new Value[table.getColumnCount()];
int columnIndex = 0;
for (Column column: table.getColumns()) {
String columnName = column.getName();
Object value = row.get(columnName);
rowData[columnIndex++] = ValueCharacter.select(generator, (value == null) ? "" : value.toString());
}
return new ValueTuple(generator, rowData);
}
private TupleIterator iteratorRaw() throws IOException {
return new TupleIterator() {
Database db = DatabaseBuilder.open(new File(meta.getFileSpec()));
Table table = db.getTable(meta.getTable());
Cursor cursor = CursorBuilder.createCursor(table);
Row currentLine = null;
@Override
public boolean hasNext() {
if (currentLine != null)
return true;
try {
if (cursor.moveToNextRow()) {
currentLine = cursor.getCurrentRow();
if (currentLine == null)
return false;
return true;
}
} catch (IOException ioe) {
System.out.println("TableACCDB[1]: error " + ioe);
}
return false;
}
@Override
public ValueTuple next() {
if (hasNext())
try {
return toTuple(table, currentLine);
} finally {
currentLine = null;
}
else
return null;
}
@Override
public void close() {
try {
db.close();
} catch (IOException e) {
System.out.println("TableACCDB[2]: error " + e);
}
}
};
}
}