/*
* StreamCruncher: Copyright (c) 2006-2008, Ashwin Jayaprakash. All Rights Reserved.
* Contact: ashwin {dot} jayaprakash {at} gmail {dot} com
* Web: http://www.StreamCruncher.com
*
* This file is part of StreamCruncher.
*
* StreamCruncher is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* StreamCruncher is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with StreamCruncher. If not, see <http://www.gnu.org/licenses/>.
*/
package streamcruncher.util;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
import streamcruncher.innards.impl.expression.ExpressionEvaluationException;
import streamcruncher.util.RowEvaluator.ContextHolder;
/*
* Author: Ashwin Jayaprakash Date: Jan 18, 2007 Time: 3:30:41 PM
*/
/**
* Uni-directional always-on ResultSet.
*/
public class PerpetualResultSet {
protected final String[] columnNames;
/**
* Label and ResultSet position, not Array position.
*/
protected final Map<String, Integer> columnLabelAndPos;
protected final Queue<Object[]> rows;
protected final AtomicInteger rowCounter;
protected Object[] currRow;
protected int sessionRowCounter;
public PerpetualResultSet(String[] columnNames) {
this.columnNames = columnNames;
this.columnLabelAndPos = new HashMap<String, Integer>();
for (int i = 0; i < columnNames.length; i++) {
this.columnLabelAndPos.put(columnNames[i], (i + 1));
}
this.rows = new ConcurrentLinkedQueue<Object[]>();
this.rowCounter = new AtomicInteger();
}
/**
* @param columnLabel
* @return The position in the ResultSet of the column - First column is at
* position <b>1</b>.
*/
public int findColumn(String columnLabel) {
return columnLabelAndPos.get(columnLabel) + 1;
}
/**
* @param reader
* @param filter
* Can be <code>null</code>
* @return Number of elements that were added.
* @throws ExpressionEvaluationException
*/
public int pumpRows(streamcruncher.util.TwoDAppendOnlyList.Reader reader, RowEvaluator filter)
throws ExpressionEvaluationException {
int c = reader.readInto(rows, filter);
rowCounter.addAndGet(c);
return c;
}
/**
* @param collection
* @param filter
* Can be <code>null</code>
* @return Number of elements that were added.
* @throws ExpressionEvaluationException
*/
public int pumpRows(Collection<Object[]> collection, RowEvaluator filter)
throws ExpressionEvaluationException {
int c = 0;
if (filter != null) {
filter.batchStart();
}
ContextHolder holder = null;
for (Object[] row : collection) {
if (filter != null) {
holder = filter.rowStart(holder, row);
}
if (filter == null || ((Boolean) filter.evaluate(holder)).booleanValue() == true) {
rows.add(row);
c++;
rowCounter.incrementAndGet();
}
if (filter != null) {
filter.rowEnd();
holder.clear();
}
}
if (filter != null) {
filter.batchEnd();
}
return c;
}
/**
* Keeps changing over time.
*
* @return
*/
public int getSize() {
return rowCounter.get();
}
// -----------
/**
* @param maxRows
* Max rows that should be picked up for this session.
*/
public void startSession(int maxRows) {
// Take a snapshot here.
sessionRowCounter = Math.min(maxRows, rowCounter.get());
}
/**
* @return <code>true</code> if there was a Row and the ResultSet moved
* forward.
*/
public boolean next() {
if (sessionRowCounter <= 0) {
return false;
}
sessionRowCounter--;
rowCounter.decrementAndGet();
currRow = rows.poll();
return true;
}
/**
* @param columnLabel
* @return
*/
public Object getColumnValue(String columnLabel) {
int pos = columnLabelAndPos.get(columnLabel);
return getColumnValue(pos);
}
/**
* @param columnIndex
* First column is at position <b>1</b>, not 0.
* @return
*/
public Object getColumnValue(int columnIndex) {
return currRow[columnIndex - 1];
}
public void closeSession() {
currRow = null;
sessionRowCounter = 0;
}
}