package er.memoryadaptor;
import com.webobjects.eoaccess.EOAdaptorChannel;
import com.webobjects.eoaccess.EOAttribute;
import com.webobjects.eoaccess.EOEntity;
import com.webobjects.eoaccess.EOGeneralAdaptorException;
import com.webobjects.eoaccess.EOModel;
import com.webobjects.eoaccess.EOSQLExpression;
import com.webobjects.eoaccess.EOStoredProcedure;
import com.webobjects.eocontrol.EOFetchSpecification;
import com.webobjects.eocontrol.EOQualifier;
import com.webobjects.foundation.NSArray;
import com.webobjects.foundation.NSDictionary;
import com.webobjects.foundation.NSMutableArray;
import com.webobjects.foundation.NSMutableDictionary;
/**
* ERMemoryAdaptorChannel provides the adaptor channel implementation for ERMemoryAdaptor.
*
* @author mschrag
*/
public class ERMemoryAdaptorChannel extends EOAdaptorChannel {
private NSArray<EOAttribute> _attributes;
private NSMutableArray<NSMutableDictionary<String, Object>> _fetchedRows;
private int _fetchIndex;
private boolean _open;
// During a fetch, the adaptor channel is called:
// 1) selectAttributes
// 2) Multiple calls to fetchRow()
// We need a variable for the "is fetch in progress" because it should be true from 1) to the last call in 2).
// Of course, it become false if there is an exception during this process (cancelFetch is called in such case).
private boolean _fetchInProgress = false;
public ERMemoryAdaptorChannel(ERMemoryAdaptorContext context) {
super(context);
_fetchIndex = -1;
}
@Override
public ERMemoryAdaptorContext adaptorContext() {
return (ERMemoryAdaptorContext) super.adaptorContext();
}
@Override
public NSArray<EOAttribute> attributesToFetch() {
return _attributes;
}
@Override
public void cancelFetch() {
_fetchInProgress = false;
_fetchedRows = null;
_fetchIndex = -1;
}
@Override
public void closeChannel() {
_open = false;
}
@Override
public NSArray describeResults() {
return _attributes;
}
@Override
public NSArray describeTableNames() {
return NSArray.EmptyArray;
}
@Override
public EOModel describeModelWithTableNames(NSArray anArray) {
return null;
}
@Override
public void evaluateExpression(EOSQLExpression anExpression) {
throw new UnsupportedOperationException("ERMemoryAdaptorChannel.evaluateExpression");
}
@Override
public void executeStoredProcedure(EOStoredProcedure aStoredProcedure, NSDictionary someValues) {
throw new UnsupportedOperationException("ERMemoryAdaptorChannel.executeStoredProcedure");
}
@Override
public NSMutableDictionary fetchRow() {
if (!_fetchInProgress) {
return null;
}
NSMutableDictionary row = null;
if (hasMoreRowsToReturn()) {
row = _fetchedRows.objectAtIndex(_fetchIndex++);
}
_fetchInProgress = hasMoreRowsToReturn();
return row;
}
private boolean hasMoreRowsToReturn() {
return _fetchedRows != null && _fetchIndex < _fetchedRows.count();
}
@Override
public boolean isFetchInProgress() {
return _fetchInProgress;
}
@Override
public boolean isOpen() {
return _open;
}
@Override
public void openChannel() {
if (!_open) {
_open = true;
}
}
@Override
public NSDictionary returnValuesForLastStoredProcedureInvocation() {
throw new UnsupportedOperationException("ERMemoryAdaptorChannel.returnValuesForLastStoredProcedureInvocation");
}
@Override
public void selectAttributes(NSArray<EOAttribute> attributesToFetch, EOFetchSpecification fetchSpecification, boolean shouldLock, EOEntity entity) {
if (entity == null) {
throw new IllegalArgumentException("null entity.");
}
if (attributesToFetch == null) {
throw new IllegalArgumentException("null attributes.");
}
_fetchInProgress = true;
setAttributesToFetch(attributesToFetch);
EREntityStore store = adaptorContext()._entityStoreForEntity(entity);
try {
_fetchIndex = 0;
_fetchedRows = store.fetch(attributesToFetch, fetchSpecification, shouldLock, entity, adaptorContext());
}
catch (EOGeneralAdaptorException e) {
cancelFetch();
throw e;
}
catch (Throwable e) {
e.printStackTrace();
cancelFetch();
throw new EOGeneralAdaptorException("Failed to fetch '" + entity.name() + "' with fetch specification '" + fetchSpecification + "': " + e.getMessage());
}
}
@SuppressWarnings("unchecked")
@Override
public void setAttributesToFetch(NSArray attributesToFetch) {
if (attributesToFetch == null) {
throw new IllegalArgumentException("ERMemoryAdaptorChannel.setAttributesToFetch: null attributes.");
}
_attributes = attributesToFetch;
}
@Override
public int updateValuesInRowsDescribedByQualifier(NSDictionary updatedRow, EOQualifier qualifier, EOEntity entity) {
try {
EREntityStore store = adaptorContext()._entityStoreForEntity(entity);
return store.updateValuesInRowsDescribedByQualifier(updatedRow, qualifier, entity);
}
catch (EOGeneralAdaptorException e) {
throw e;
}
catch (Throwable e) {
e.printStackTrace();
throw new EOGeneralAdaptorException("Failed to update '" + entity.name() + "' row " + updatedRow + " with qualifier " + qualifier + ": " + e.getMessage());
}
}
@Override
public void insertRow(NSDictionary row, EOEntity entity) {
try {
EREntityStore store = adaptorContext()._entityStoreForEntity(entity);
store.insertRow(row, entity);
}
catch (EOGeneralAdaptorException e) {
throw e;
}
catch (Throwable e) {
e.printStackTrace();
throw new EOGeneralAdaptorException("Failed to insert '" + entity.name() + "' with row " + row + ": " + e.getMessage());
}
}
@Override
public int deleteRowsDescribedByQualifier(EOQualifier qualifier, EOEntity entity) {
try {
EREntityStore store = adaptorContext()._entityStoreForEntity(entity);
return store.deleteRowsDescribedByQualifier(qualifier, entity);
}
catch (EOGeneralAdaptorException e) {
throw e;
}
catch (Throwable e) {
e.printStackTrace();
throw new EOGeneralAdaptorException("Failed to delete '" + entity.name() + "' with qualifier " + qualifier + ": " + e.getMessage());
}
}
}