/* * Copyright (c) 2010 Mysema Ltd. * All rights reserved. * */ package com.mysema.query.collections; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.collections15.IteratorUtils; import com.mysema.commons.lang.CloseableIterator; import com.mysema.commons.lang.IteratorAdapter; import com.mysema.query.JoinType; import com.mysema.query.QueryException; import com.mysema.query.QueryMetadata; import com.mysema.query.QueryModifiers; import com.mysema.query.SearchResults; import com.mysema.query.support.ProjectableQuery; import com.mysema.query.support.QueryMixin; import com.mysema.query.types.Expr; import com.mysema.query.types.Ops; import com.mysema.query.types.Path; import com.mysema.query.types.expr.EArrayConstructor; import com.mysema.query.types.expr.OSimple; /** * AbstractColQuery provides a base class for Collection query implementations. * Extend it like this * *
 * public class MyType extends AbstractColQuery<MyType>{
 *   ...
 * }
 * 
* * @see ColQuery * * @author tiwe * @version $Id$ */ public abstract class AbstractColQuery> extends ProjectableQuery { private final ExprEvaluatorFactory evaluatorFactory; private final Map, Iterable> iterables = new HashMap, Iterable>(); private final IteratorFactory iteratorFactory; @SuppressWarnings("unchecked") public AbstractColQuery(QueryMetadata metadata, ExprEvaluatorFactory evaluatorFactory) { super(new QueryMixin(metadata)); this.queryMixin.setSelf((Q) this); this.evaluatorFactory = evaluatorFactory; this.iteratorFactory = new IteratorFactory(evaluatorFactory); } @Override public long count() { try { Iterator iterator = createIterator(true); long count = 0l; while (iterator.hasNext()) { iterator.next(); count++; } return count; } catch (Exception e) { throw new QueryException(e.getMessage(), e); }finally{ reset(); } } private Iterator createIterator(boolean forCount){ QueryMetadata metadata = queryMixin.getMetadata(); if (metadata.getJoins().size() == 1) { return new SingleSourceIterable(metadata, evaluatorFactory, iteratorFactory, iterables, forCount).iterator(); } else { return new MultiSourceIterable(metadata, evaluatorFactory, iteratorFactory, iterables, forCount).iterator(); } } private Iterator createPagedIterator() throws Exception { Iterator iterator = createIterator(false); return LimitingIterator.create(iterator, queryMixin.getMetadata().getModifiers()); } @SuppressWarnings("unchecked") public Q from(Path entity, Iterable col) { iterables.put(entity.asExpr(), col); queryMixin.getMetadata().addJoin(JoinType.DEFAULT, entity.asExpr()); return (Q)this; } @SuppressWarnings("unchecked") public

Q innerJoin(Path> target, Path

alias) { queryMixin.getMetadata().addJoin(JoinType.INNERJOIN, createAlias(target, alias)); return (Q)this; } @SuppressWarnings("unchecked") private Expr createAlias(Path> target, Path alias){ return OSimple.create((Class)alias.getType(), Ops.ALIAS, target.asExpr(), alias.asExpr()); } protected ExprEvaluatorFactory getEvaluatorFactory() { return evaluatorFactory; } @SuppressWarnings("unchecked") @Override public CloseableIterator iterate(Expr[] args) { return iterate(new EArrayConstructor(Object[].class, args)); } @Override public CloseableIterator iterate(Expr projection) { try { queryMixin.addToProjection(projection); return new IteratorAdapter(this.createPagedIterator()); } catch (Exception e) { throw new QueryException(e.getMessage(), e); }finally{ reset(); } } @Override public SearchResults listResults(Expr projection) { queryMixin.addToProjection(projection); QueryModifiers modifiers = queryMixin.getMetadata().getModifiers(); List list; try { list = IteratorUtils.toList(this.createIterator(false)); } catch (Exception e) { throw new QueryException(e.getMessage(), e); } // empty results if (list.isEmpty()) { reset(); return SearchResults.emptyResults(); // no restrictions } else if (!modifiers.isRestricting()) { reset(); return new SearchResults(list, modifiers, list.size()); } else { int start = 0; int end = list.size(); if (modifiers.getOffset() != null) { if (modifiers.getOffset() < list.size()) { start = modifiers.getOffset().intValue(); } else { reset(); return new SearchResults(Collections. emptyList(), modifiers, list.size()); } } if (modifiers.getLimit() != null) { end = (int) Math.min(start + modifiers.getLimit(), list.size()); } reset(); return new SearchResults(list.subList(start, end), modifiers, list.size()); } } private void reset(){ queryMixin.getMetadata().reset(); } }