package photoSpreadUtilities;
import java.awt.event.KeyEvent;
import java.io.File;
import java.util.Collection;
import java.util.HashMap;
import photoSpread.PhotoSpread;
import photoSpread.PhotoSpreadException;
import photoSpread.PhotoSpreadException.IllegalArgumentException;
import photoSpreadObjects.ObjectIndexerFinder;
import photoSpreadObjects.PhotoSpreadDoubleObject;
import photoSpreadObjects.PhotoSpreadFileObject;
import photoSpreadObjects.PhotoSpreadObject;
import photoSpreadObjects.PhotoSpreadStringObject;
import photoSpreadObjects.PhotoSpreadTableObject;
import photoSpreadParser.photoSpreadExpression.PhotoSpreadComputable;
import photoSpreadTable.PhotoSpreadTable;
public class PhotoSpreadObjIndexerFinder implements ObjectIndexerFinder<PhotoSpreadObject> {
protected static enum PhotoSpreadDispatch {
STRING,
DOUBLE,
FILE,
TABLE
}
private DispatchHashMap _dispatchTable = null;
private HashMap<Object, PhotoSpreadObject> _contentIndex =
new HashMap<Object, PhotoSpreadObject>();
// Reserved string to prepend to file names so that
// we can distinguish them from regular strings: We
// prepend the string "<cnt-E>File:" to the path:
private static char[] _reservedNameMarkerPrefix = {KeyEvent.VK_5};
private String _fileNameMarker = new String(_reservedNameMarkerPrefix) + "File:";
private String _tableMarker = new String(_reservedNameMarkerPrefix) + "Table:";
/****************************************************
* Constructors
*****************************************************/
public PhotoSpreadObjIndexerFinder () {
_dispatchTable = new DispatchHashMap();
}
/****************************************************
* Inner class DispatchHashMap
*****************************************************/
public class DispatchHashMap extends HashMap<Class<?> , PhotoSpreadDispatch> {
private static final long serialVersionUID = 1L;
public DispatchHashMap () {
try {
put(Class.forName("photoSpreadObjects.PhotoSpreadStringObject"), PhotoSpreadDispatch.STRING);
put(Class.forName("photoSpreadObjects.PhotoSpreadDoubleObject"), PhotoSpreadDispatch.DOUBLE);
put(Class.forName("photoSpreadObjects.PhotoSpreadTextFile"), PhotoSpreadDispatch.FILE);
put(Class.forName("photoSpreadObjects.PhotoSpreadImage"), PhotoSpreadDispatch.FILE);
put(Class.forName("photoSpreadObjects.PhotoSpreadTableObject"), PhotoSpreadDispatch.TABLE);
} catch (ClassNotFoundException e) {
// Use a runtime exception here, because class-not-found
// will be obvious at debug time. This way we don't
// have to drag handling of this exception around at runtime.
throw new RuntimeException(
"Class not found. Fix DispatchHashMap table initialization: " +
e.getMessage());
}
}
};
/****************************************************
* Methods for ADDing objects to the index
*****************************************************/
@Override
public boolean add(PhotoSpreadComputable obj) throws IllegalArgumentException {
PhotoSpreadDispatch dispatch = _dispatchTable.get(obj.getClass());
if (dispatch != null)
switch (dispatch) {
case STRING:
return add((PhotoSpreadStringObject) obj);
case DOUBLE:
return add((PhotoSpreadDoubleObject) obj);
case FILE:
return add((PhotoSpreadFileObject) obj);
case TABLE:
return add((PhotoSpreadTableObject) obj);
}
throw new PhotoSpreadException.IllegalArgumentException(
"Expecting a PhotoSpreadObject subtype to be indexed. Got: " + obj);
}
private boolean add(PhotoSpreadStringObject obj) {
if (_contentIndex.put(getObjectIndexKey(obj), obj) == null) {
PhotoSpread.trace("Indexed new PhotoSpreadStringObject " + obj);
return true;
}
PhotoSpread.trace("PhotoSpreadStringObject replaced in index. Previous obj: " + obj);
return false;
}
private boolean add(PhotoSpreadDoubleObject obj) {
if (_contentIndex.put(getObjectIndexKey(obj), obj) == null) {
PhotoSpread.trace("Indexed new PhotoSpreadDoubleObject " + obj);
return true;
}
PhotoSpread.trace("PhotoSpreadDoubleObject replaced in index. Previous obj: " + obj);
return false;
}
private boolean add(PhotoSpreadFileObject obj) {
if (_contentIndex.put(getObjectIndexKey(obj), obj) == null) {
PhotoSpread.trace("Indexed new PhotoSpreadFileObject " + obj);
return true;
}
PhotoSpread.trace("PhotoSpreadFileObject replaced in index. Previous obj: " + obj);
return false;
}
private boolean add(PhotoSpreadTableObject psTableObj) {
if (_contentIndex.put(getObjectIndexKey(psTableObj), psTableObj) == null) {
PhotoSpread.trace("Indexed new PhotoSpreadTableObject " + psTableObj);
return true;
}
PhotoSpread.trace("PhotoSpreadTableObject replaced in index. Previous obj: " + psTableObj);
return false;
}
@Override
public boolean addAll(Collection<PhotoSpreadComputable> objs)
throws IllegalArgumentException {
for (PhotoSpreadComputable item : objs) {
add(item);
}
return true;
}
/****************************************************
* Methods for REMOVEing objects to the index
*****************************************************/
@Override
public void clear() {
_contentIndex.clear();
PhotoSpread.trace("Cleared index");
}
@Override
public boolean remove(PhotoSpreadComputable obj)
throws IllegalArgumentException {
PhotoSpreadDispatch dispatch = _dispatchTable.get(obj.getClass());
if (dispatch != null)
switch (dispatch) {
case STRING:
return remove((PhotoSpreadStringObject) obj);
case DOUBLE:
return remove((PhotoSpreadDoubleObject) obj);
case FILE:
return remove((PhotoSpreadFileObject) obj);
case TABLE:
return remove((PhotoSpreadTableObject) obj);
}
throw new PhotoSpreadException.IllegalArgumentException(
"Expecting a PhotoSpreadObject subtype to be indexed. Got: " + obj);
}
private boolean remove(PhotoSpreadStringObject obj) {
_contentIndex.remove(getObjectIndexKey(obj));
PhotoSpread.trace("Removed string object " + obj);
return true;
}
private boolean remove(PhotoSpreadDoubleObject obj) {
_contentIndex.remove(getObjectIndexKey(obj));
PhotoSpread.trace("Removed double object " + obj);
return true;
}
private boolean remove(PhotoSpreadFileObject obj) {
_contentIndex.remove(getObjectIndexKey(obj));
PhotoSpread.trace("Removed file object " + obj);
return true;
}
private boolean remove(PhotoSpreadTableObject psTableObj) {
_contentIndex.remove(getObjectIndexKey(psTableObj));
PhotoSpread.trace("Removed table object " + psTableObj);
return true;
}
/****************************************************
* Methods for FINDing objects in the index.
*****************************************************/
public PhotoSpreadStringObject find (String strContent) {
return (PhotoSpreadStringObject) _contentIndex.get(strContent);
}
public PhotoSpreadDoubleObject find (Double doubleContent) {
return (PhotoSpreadDoubleObject) _contentIndex.get(doubleContent);
}
public PhotoSpreadFileObject find (File fileObj) {
return (PhotoSpreadFileObject) _contentIndex.get(generateKeyFromFileObj(fileObj));
}
public PhotoSpreadTableObject find (PhotoSpreadTable psTableObj) {
return (PhotoSpreadTableObject) _contentIndex.get(_tableMarker + psTableObj.toString());
}
/****************************************************
* Methods for maintenance
*****************************************************/
public boolean isEmpty() {
return _contentIndex.isEmpty();
}
public int size() {
return _contentIndex.size();
}
/****************************************************
* Methods for generating index keys from objects that will be indexed
*****************************************************/
private String getObjectIndexKey (PhotoSpreadStringObject obj) {
return obj.valueOf();
}
private Double getObjectIndexKey (PhotoSpreadDoubleObject obj) {
return obj.valueOf();
}
private String getObjectIndexKey (PhotoSpreadFileObject obj) {
// We need to make an index key that we can reliably re-create
// later from just the passed-in object's file name when
// given a corresponding File object:
File tmpFileWrapper = new File(obj.getFilePath());
return generateKeyFromFileObj(tmpFileWrapper);
}
private String generateKeyFromFileObj (File theFile) {
return _fileNameMarker + theFile.getAbsolutePath();
}
private String getObjectIndexKey (PhotoSpreadTableObject psTableObj) {
// We need to make an index key that we can reliably re-create
// later from just the passed-in table object,
// given a corresponding Table object:
PhotoSpreadTable tmpTblObj = psTableObj.getTable();
return generateKeyFromTableObj(tmpTblObj);
}
private String generateKeyFromTableObj (PhotoSpreadTable tbl) {
return _tableMarker + tbl.toString();
}
/*
* If this index contains a *value* that is the passed-in object,
* then return that object, else return null.
*/
@Override
public PhotoSpreadObject containsValue(PhotoSpreadObject obj) {
return _contentIndex.get(obj.valueOf());
}
}