package org.jboss.seam.trinidad; import java.util.ArrayList; import java.util.List; import java.util.regex.Pattern; import org.apache.myfaces.trinidad.model.CollectionModel; import org.apache.myfaces.trinidad.model.SortCriterion; import org.jboss.seam.framework.Query; import org.jboss.seam.util.Strings; /** * Abstract base class for an Apache Trinidad CollectionModel * * Implementing classes need to provide conversion between the * current row index and a key for the unchanging row. * * Using rowIndex when backing the CollectionModel with a Query * is not possible as sorting and paging alters the rowIndex * outside the control of the CollectionModel. * * @author pmuir * */ public abstract class SeamCollectionModel extends CollectionModel { private static final Pattern COMMA = Pattern.compile(","); private static final Pattern SPACE = Pattern.compile("\\s+"); //private Object rowKey; private int rowIndex = -1; private List<SortCriterion> criteria; @Override public Object getWrappedData() { return getWrappedList(); } public void refresh() { getQuery().refresh(); } @Override public int getRowCount() { return getQuery().getResultCount().intValue(); } @Override public void setWrappedData(Object arg0) { throw new UnsupportedOperationException("Immutable DataModel"); } protected List getWrappedList() { return getQuery().getResultList(); } protected abstract Query getQuery(); @Override public boolean isSortable(String property) { return true; } @Override public List<SortCriterion> getSortCriteria() { if (criteria == null) { criteria = asCriteria(getQuery().getOrder()); } return criteria; } @Override public void setSortCriteria(List<SortCriterion> criteria) { if (criteria != null && !criteria.equals(getSortCriteria())) { getQuery().setOrder(asQl(criteria)); this.criteria = criteria; } } @Override public void setRowIndex(int rowIndex) { this.rowIndex = rowIndex; //rowKey = null; } @Override public int getRowIndex() { return rowIndex; } @Override public Object getRowData() { // We can attempt to do lazy loading if (getQuery().getMaxResults() != null) { boolean refresh = false; // Lazy load data refresh = page(); if (refresh) { refresh(); } return getWrappedList().get(getRowIndex() - getFirstResult()); } else { return getWrappedList().get(getRowIndex()); } } private boolean page() { if (getRowIndex() < getFirstResult()) { while (getRowIndex() < getFirstResult()) { getQuery().previous(); } return true; } else if (getRowIndex() >= getQuery().getNextFirstResult()) { while (getRowIndex() >= getQuery().getNextFirstResult()) { getQuery().next(); } return true; } else { return false; } } protected int getFirstResult() { if (getQuery().getFirstResult() == null) { getQuery().setFirstResult(0); } return getQuery().getFirstResult(); } @Override public boolean isRowAvailable() { return getRowIndex() >= 0 && getRowIndex() < getRowCount(); } public static String asQl(List<SortCriterion> criteria) { if (criteria != null && criteria.size() > 0) { StringBuffer sb = new StringBuffer(); boolean first = true; for (SortCriterion sortCriterion : criteria) { if (first) { first = false; } else { sb.append(','); } sb.append(sortCriterion.getProperty()).append(sortCriterion.isAscending() ? " ASC" : " DESC"); } return sb.toString(); } return null; } public static List<SortCriterion> asCriteria(String sql) { if (!Strings.isEmpty(sql)) { String[] tokens = COMMA.split(sql.trim()); List<SortCriterion> criteria = new ArrayList<SortCriterion>(tokens.length); for (int i = 0; i != tokens.length; i++) { String[] terms = SPACE.split(tokens[i].trim()); SortCriterion sortCriterion = new SortCriterion(terms[0], terms.length == 1 ? false : "ASC".equalsIgnoreCase(terms[1])); criteria.add(i, sortCriterion); } return criteria; } return new ArrayList<SortCriterion>(); } }