package de.onyxbits.tradetrax.remix;
import java.util.Date;
import java.util.List;
import java.util.Vector;
import org.apache.tapestry5.grid.GridDataSource;
import org.apache.tapestry5.grid.SortConstraint;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.LogicalExpression;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.hibernate.criterion.SimpleExpression;
import de.onyxbits.tradetrax.entities.Stock;
/**
* For displaying the stocks table in a paged grid.
*
* @author patrick
*
*/
public class StockPagedGridDataSource implements GridDataSource {
private Session session;
private List<Stock> preparedResults;
private int startIndex;
private Criterion nameRestriction;
private Criterion variantRestriction;
private LogicalExpression stateRestriction;
private SimpleExpression acquisitionRestriction;
private SimpleExpression liquidationRestriction;
private Criterion locationRestriction;
private Criterion commentRestriction;
/**
* Construct a new object
*
* @param session
* database session from which to load objects.
* @param moneyConverter
* for formatting money values.
*/
public StockPagedGridDataSource(Session session) {
this.session = session;
preparedResults = new Vector<Stock>();
}
/**
* Add a name restriction
*
* @param label
* (sub)string to match or null to disable name filtering.
* @return this reference for method chaining.
*/
public StockPagedGridDataSource withName(String label) {
if (label != null) {
// nameRestriction = Restrictions.like("name.label", "%"+label+"%");
nameRestriction = Restrictions.ilike("name.label", "%" + label + "%");
}
else {
nameRestriction = null;
}
return this;
}
/**
* Add a state restriction
*
* @param filterState
* the state or null to disable statefiltering
* @return this reference for method chaining.
*/
public StockPagedGridDataSource withState(StockState state) {
if (state != null) {
switch (state) {
case ACQUIRED: {
stateRestriction = Restrictions.and(Restrictions.isNotNull("acquired"),
Restrictions.isNull("liquidated"));
break;
}
case LIQUIDATED: {
stateRestriction = Restrictions.and(Restrictions.isNull("acquired"),
Restrictions.isNotNull("liquidated"));
break;
}
case PREBOOKED: {
stateRestriction = Restrictions.and(Restrictions.isNull("acquired"),
Restrictions.isNull("liquidated"));
break;
}
case FINALIZED: {
stateRestriction = Restrictions.and(Restrictions.isNotNull("acquired"),
Restrictions.isNotNull("liquidated"));
break;
}
}
}
else {
stateRestriction = null;
}
return this;
}
/**
* Add a variant restriction
*
* @param label
* (sub)string to match or null to disable variant filtering.
* @return this reference for method chaining.
*/
public StockPagedGridDataSource withVariant(String label) {
if (label != null) {
variantRestriction = Restrictions.ilike("variant.label", "%" + label + "%");
}
else {
variantRestriction = null;
}
return this;
}
/**
* Add a comment restriction
*
* @param comment
* (sub) string to match or null to disable comment filtering.
* @return this reference for method chaining.
*/
public StockPagedGridDataSource withComment(String comment) {
if (comment != null) {
commentRestriction = Restrictions.ilike("comment", "%" + comment + "%");
}
else {
commentRestriction = null;
}
return this;
}
/**
* Add a location restriction
*
* @param filterLocation
* (sub)string to match or null to disable location filtering.
* @return this reference for method chaining.
*/
public StockPagedGridDataSource withLocation(String location) {
if (location != null) {
locationRestriction = Restrictions.ilike("location", "%" + location + "%");
}
else {
locationRestriction = null;
}
return this;
}
public StockPagedGridDataSource withAcquisition(Date filterAcquisition,
TimeSpan filterAcquisitionSpan) {
if (filterAcquisition == null || filterAcquisitionSpan == null) {
acquisitionRestriction = null;
}
else {
if (filterAcquisitionSpan == TimeSpan.BEFORE) {
acquisitionRestriction = Restrictions.le("acquired", filterAcquisition);
}
else {
acquisitionRestriction = Restrictions.ge("acquired", filterAcquisition);
}
}
return this;
}
public StockPagedGridDataSource withLiquidation(Date filterLiquidation,
TimeSpan filterLiquidationSpan) {
if (filterLiquidation == null || filterLiquidationSpan == null) {
liquidationRestriction = null;
}
else {
if (filterLiquidationSpan == TimeSpan.BEFORE) {
liquidationRestriction = Restrictions.le("liquidated", filterLiquidation);
}
else {
liquidationRestriction = Restrictions.ge("liquidated", filterLiquidation);
}
}
return this;
}
public int getAvailableRows() {
return ((Number) createFilterCriteria().setProjection(Projections.rowCount()).uniqueResult())
.intValue();
}
public long getItemCount() {
Long l = (Long) createFilterCriteria().setProjection(Projections.sum("unitCount")).uniqueResult();
if (l==null) {
return 0;
}
else {
return l.longValue();
}
}
private Criteria createFilterCriteria() {
Criteria crit = session.createCriteria(Stock.class);
if (nameRestriction != null) {
crit.createAlias("name", "name");
crit.add(nameRestriction);
}
if (variantRestriction != null) {
crit.createAlias("variant", "variant");
crit.add(variantRestriction);
}
if (stateRestriction != null) {
crit.add(stateRestriction);
}
if (acquisitionRestriction != null) {
crit.add(acquisitionRestriction);
}
if (liquidationRestriction != null) {
crit.add(liquidationRestriction);
}
if (locationRestriction != null) {
crit.add(locationRestriction);
}
if (commentRestriction != null) {
crit.add(commentRestriction);
}
return crit;
}
private void attachOrder(Criteria crit, SortConstraint sc) {
// NOTE: the logic of the columns we allow to be sort is inverse of the
// database logic, hence asc becomes desc.
switch (sc.getColumnSort()) {
case ASCENDING: {
crit.addOrder(Order.desc(sc.getPropertyModel().getId()));
break;
}
case DESCENDING: {
crit.addOrder(Order.asc(sc.getPropertyModel().getId()));
break;
}
default: {
}
}
}
@SuppressWarnings("unchecked")
public void prepare(int startIndex, int endIndex, List<SortConstraint> sortConstraints) {
Criteria crit = session.createCriteria(Stock.class).setFirstResult(startIndex)
.setMaxResults(endIndex - startIndex + 1);
for (SortConstraint sc : sortConstraints) {
if ("buyPrice".equals(sc.getPropertyModel().getId())) {
attachOrder(crit, sc);
}
if ("acquired".equals(sc.getPropertyModel().getId())) {
attachOrder(crit, sc);
}
if ("liquidated".equals(sc.getPropertyModel().getId())) {
attachOrder(crit, sc);
}
if ("sellPrice".equals(sc.getPropertyModel().getId())) {
attachOrder(crit, sc);
}
}
if (sortConstraints.size() == 0) {
crit.addOrder(Order.desc("acquired"));
}
crit.addOrder(Order.desc("id"));
if (nameRestriction != null) {
crit.createAlias("name", "name");
crit.add(nameRestriction);
}
if (variantRestriction != null) {
crit.createAlias("variant", "variant");
crit.add(variantRestriction);
}
if (stateRestriction != null) {
crit.add(stateRestriction);
}
if (acquisitionRestriction != null) {
crit.add(acquisitionRestriction);
}
if (liquidationRestriction != null) {
crit.add(liquidationRestriction);
}
if (locationRestriction != null) {
crit.add(locationRestriction);
}
if (commentRestriction != null) {
crit.add(commentRestriction);
}
this.preparedResults = crit.list();
this.startIndex = startIndex;
}
public Object getRowValue(int index) {
try {
return preparedResults.get(index - startIndex);
}
catch (IndexOutOfBoundsException e) {
return null;
}
}
public Class<Stock> getRowType() {
return Stock.class;
}
}