package nl.amis.jsf.model;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.faces.model.DataModelEvent;
import javax.faces.model.DataModelListener;
import static nl.amis.jsf.model.EntityLovModelUtil.getKeyFromEntity;
import org.apache.myfaces.trinidad.model.CollectionModel;
import org.apache.myfaces.trinidad.model.RowKeySet;
public abstract class EntityCollectionModel extends CollectionModel {
private Method keyGetter;
private Class entityClass;
private int currentRowIndex = -1;
private Object selectedRowKey = null;
private List indexCache;
private Map<Object, Object> keyCache;
public EntityCollectionModel(Class entityClass) {
this.entityClass = entityClass;
}
public void setKeyGetter(Method keyGetter) {
this.keyGetter = keyGetter;
}
private List getIndexData() {
if (null == indexCache || isJpqlChanged()) {
indexCache = getFilteredList();
if (null != indexCache) {
keyCache = new HashMap<Object, Object>();
for (Object object : indexCache) {
if (null != object && entityClass.isAssignableFrom(object.getClass())) {
keyCache.put(getKeyFromEntity(keyGetter, object), object);
}
}
}
}
return indexCache;
}
private Map<Object, Object> getKeyCache() {
if (null == keyCache) {
getIndexData() ;
}
return keyCache;
}
public Object getRowKey() {
return getKeyFromEntity(keyGetter, getRowData());
}
public void setRowKey(Object key) {
if (null == key) {
return;
}
if (key instanceof RowKeySet) {
selectedRowKey = unwrapRowKeySet((RowKeySet)key);
} else if (key instanceof List) {
selectedRowKey = getKeyFromEntity(keyGetter, ((List)key).get(0));
} else if (entityClass.isAssignableFrom(key.getClass())) {
selectedRowKey = getKeyFromEntity(keyGetter, key);
} else {
selectedRowKey = key;
}
Object object = getKeyCache().get(selectedRowKey);
rowSelected(getIndexData().indexOf(object));
}
private Object unwrapRowKeySet(RowKeySet rks) {
if (null == rks) {
return null;
}
Object result = rks.iterator().next();
return result;
}
public boolean isRowAvailable() {
if (null == getIndexData() || currentRowIndex < 0) {
return false;
} else {
return getIndexData().size() > currentRowIndex;
}
}
public int getRowCount() {
if (null == getIndexData()) {
return 0;
} else {
int size = getIndexData().size();
return size;
}
}
public Object getRowData() {
if (null == getIndexData() || currentRowIndex < 0 || currentRowIndex >= getIndexData().size()) {
return getKeyCache().get(selectedRowKey);
} else {
return getIndexData().get(currentRowIndex);
}
}
public Object getRowData(int index) {
if (index >= 0 && index < getIndexData().size()) {
return getIndexData().get(index);
} else {
return null;
}
}
public Object getRowData(Object key) {
if (key instanceof RowKeySet) {
key = unwrapRowKeySet((RowKeySet)key);
} else if (entityClass.isAssignableFrom(key.getClass())) {
return key;
}
if (null != key) {
return getKeyCache().get(key);
} else {
return null;
}
}
public int getRowIndex() {
return currentRowIndex;
}
public void setRowIndex(int i) {
if (i >= 0 && i < getIndexData().size()) {
currentRowIndex = i;
} else {
currentRowIndex = -1;
}
rowSelected(i);
}
public Object getWrappedData() {
return getIndexData();
}
public void setWrappedData(Object object) {
throw new UnsupportedOperationException();
}
private void rowSelected(int index) {
if (index >= 0 && index < getRowCount()) {
DataModelEvent event = new DataModelEvent(this, index, getIndexData().get(index));
for (DataModelListener listener : getDataModelListeners()) {
listener.rowSelected(event);
}
}
}
public Object findByToString(String string) {
int pos = string.indexOf("@");
if (pos < 0) {
return null;
}
String hashCodeString = string.substring(pos+1);
int hashCode = Integer.valueOf(hashCodeString, 16);
for (Object object : getIndexData()) {
if (hashCode == object.hashCode()) {
return object;
}
}
return null;
}
public abstract List getFilteredList();
public abstract boolean isJpqlChanged();
}