/**
* Copyright (c) 2009 - 2012 Red Hat, Inc.
*
* This software is licensed to you under the GNU General Public License,
* version 2 (GPLv2). There is NO WARRANTY for this software, express or
* implied, including the implied warranties of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2
* along with this software; if not, see
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
*
* Red Hat trademarks are not licensed under GPLv2. No permission is
* granted to use or replicate Red Hat trademarks that are incorporated
* in this software or its documentation.
*/
package org.candlepin.model;
import org.candlepin.util.ElementTransformer;
import org.hibernate.Session;
import org.hibernate.criterion.Order;
import java.util.Iterator;
import java.util.List;
import java.util.LinkedList;
import javax.persistence.LockModeType;
/**
* The TransformedCandlepinQuery class is a decorator for standard CandlepinQuery implementations,
* providing element transformation from one type to another using an ElementTransformer instance.
* <p></p>
* Typically, this class does not need to be instantiated directly, and can be obtained by calling
* the <tt>.transform</tt> method on the base CandlepinQuery instance.
*
* @param <I>
* The element type returned by the base CandlepinQuery this instance is transforming
*
* @param <O>
* The element type to be returned by this query's result output methods
*/
public class TransformedCandlepinQuery<I, O> implements CandlepinQuery<O> {
/**
* The TransformedResultIterator class applies element transformation to an existing
* ResultIterator instance.
*
* @param <I>
* The element type returned by the base ResultIterator this instance is transforming
*
* @param <O>
* The element type to be returned by this iterators's output methods
*/
private static class TransformedResultIterator<I, O> implements ResultIterator<O> {
private ResultIterator<I> iterator;
private ElementTransformer<I, O> transformer;
public TransformedResultIterator(ResultIterator<I> iterator, ElementTransformer<I, O> transformer) {
if (iterator == null) {
throw new IllegalArgumentException("iterator is null");
}
if (transformer == null) {
throw new IllegalArgumentException("transformer is null");
}
this.iterator = iterator;
this.transformer = transformer;
}
@Override
public boolean hasNext() {
return this.iterator.hasNext();
}
@Override
public O next() {
return this.transformer.transform(this.iterator.next());
}
@Override
public void remove() {
this.iterator.remove();
}
@Override
public void close() {
this.iterator.close();
}
}
private CandlepinQuery<I> query;
private ElementTransformer<I, O> transformer;
/**
* Creates a new TransformedCandlepinQuery instance from the given query and element
* transformer.
*
* @param query
* The CandlepinQuery to be transformed by the given element transformer
*
* @param transformer
* The ElementTransformer to apply to the results of the provided query
*
* @throws IllegalArgumentException
* if either the query or transformer are null
*/
public TransformedCandlepinQuery(CandlepinQuery<I> query, ElementTransformer<I, O> transformer) {
if (query == null) {
throw new IllegalArgumentException("query is null");
}
if (transformer == null) {
throw new IllegalArgumentException("transformer is null");
}
this.query = query;
this.transformer = transformer;
}
/**
* {@inheritDoc}
*/
@Override
public CandlepinQuery<O> useSession(Session session) {
this.query.useSession(session);
return this;
}
/**
* {@inheritDoc}
*/
@Override
public CandlepinQuery<O> setFirstResult(int offset) {
this.query.setFirstResult(offset);
return this;
}
/**
* {@inheritDoc}
*/
@Override
public CandlepinQuery<O> setMaxResults(int limit) {
this.query.setMaxResults(limit);
return this;
}
/**
* {@inheritDoc}
*/
@Override
public CandlepinQuery<O> addOrder(Order order) {
this.query.addOrder(order);
return this;
}
/**
* {@inheritDoc}
*/
@Override
public CandlepinQuery<O> setLockMode(LockModeType lockMode) {
this.query.setLockMode(lockMode);
return this;
}
/**
* {@inheritDoc}
*/
@Override
public <T> CandlepinQuery<T> transform(ElementTransformer<O, T> transformer) {
return new TransformedCandlepinQuery(this, transformer);
}
/**
* {@inheritDoc}
*/
@Override
public List<O> list() {
List<O> output = new LinkedList<O>();
ResultIterator<O> iterator = this.iterate(); // Should we auto-evict here?
try {
while (iterator.hasNext()) {
output.add(iterator.next());
}
}
finally {
iterator.close();
}
return output;
}
/**
* {@inheritDoc}
*/
@Override
public int forEach(ResultProcessor<O> processor) {
return this.forEach(0, false, processor);
}
/**
* {@inheritDoc}
*/
@Override
public int forEach(int column, ResultProcessor<O> processor) {
return this.forEach(column, false, processor);
}
/**
* {@inheritDoc}
*/
@Override
public int forEach(int column, boolean evict, ResultProcessor<O> processor) {
if (processor == null) {
throw new IllegalArgumentException("processor is null");
}
final ResultProcessor<O> wrapped = processor;
final ElementTransformer<I, O> transformer = this.transformer;
return this.query.forEach(column, evict, new ResultProcessor<I>() {
@Override
public boolean process(I element) {
return wrapped.process(transformer.transform(element));
}
});
}
/**
* {@inheritDoc}
*/
@Override
public int forEachRow(ResultProcessor<Object[]> processor) {
return this.query.forEachRow(processor);
}
/**
* {@inheritDoc}
*/
@Override
public ResultIterator<O> iterate() {
return this.iterate(0, false);
}
/**
* {@inheritDoc}
*/
@Override
public Iterator<O> iterator() {
return this.iterate(0, false);
}
/**
* {@inheritDoc}
*/
@Override
public ResultIterator<O> iterate(int column) {
return this.iterate(column, false);
}
/**
* {@inheritDoc}
*/
@Override
public ResultIterator<O> iterate(int column, boolean evict) {
ResultIterator<I> iterator = this.query.iterate(column, evict);
return new TransformedResultIterator<I, O>(iterator, this.transformer);
}
/**
* {@inheritDoc}
*/
@Override
public ResultIterator<Object[]> iterateByRow() {
return this.query.iterateByRow();
}
/**
* {@inheritDoc}
*/
@Override
public O uniqueResult() {
return this.transformer.transform(this.query.uniqueResult());
}
/**
* {@inheritDoc}
*/
@Override
public int getRowCount() {
return this.query.getRowCount();
}
}