/*
* This program is free software; you can redistribute it and/or modify it under the
* terms of the GNU Lesser General Public License, version 2.1 as published by the Free Software
* Foundation.
*
* You should have received a copy of the GNU Lesser General Public License along with this
* program; if not, you can obtain a copy at http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html
* or from the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* This program 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.
*
* Copyright (c) 2006 - 2013 Pentaho Corporation.. All rights reserved.
*/
package org.pentaho.reporting.engine.classic.extensions.datasources.kettle;
import java.math.BigDecimal;
import java.util.Date;
import javax.swing.table.TableModel;
import org.pentaho.di.core.exception.KettleStepException;
import org.pentaho.di.core.exception.KettleValueException;
import org.pentaho.di.core.row.RowMetaInterface;
import org.pentaho.di.core.row.ValueMetaInterface;
import org.pentaho.di.trans.step.RowListener;
import org.pentaho.reporting.engine.classic.core.ReportDataFactoryException;
import org.pentaho.reporting.engine.classic.core.util.TypedTableModel;
public class TableProducer implements RowListener
{
private TypedTableModel tableModel;
private int rowsWritten;
private RowMetaInterface rowMeta;
private int queryLimit;
private boolean stopOnError;
private boolean firstCall;
private boolean error;
public TableProducer(final RowMetaInterface rowMeta, final int queryLimit, final boolean stopOnError)
{
this.rowMeta = rowMeta;
this.queryLimit = queryLimit;
this.stopOnError = stopOnError;
this.firstCall = true;
}
/**
* This method is called when a row is written to another step (even if there is no next step)
*
* @param rowMeta the metadata of the row
* @param row the data of the row
* @throws org.pentaho.di.core.exception.KettleStepException an exception that can be thrown to hard stop the step
*/
public void rowWrittenEvent(final RowMetaInterface rowMeta, final Object[] row) throws KettleStepException
{
if (firstCall)
{
this.tableModel = createTableModel(rowMeta);
firstCall = false;
}
if (queryLimit > 0 && rowsWritten > queryLimit)
{
return;
}
try
{
rowsWritten += 1;
final int count = tableModel.getColumnCount();
final Object dataRow[] = new Object[count];
for (int columnNo = 0; columnNo < count; columnNo++)
{
final ValueMetaInterface valueMeta = rowMeta.getValueMeta(columnNo);
switch (valueMeta.getType())
{
case ValueMetaInterface.TYPE_BIGNUMBER:
dataRow[columnNo] = rowMeta.getBigNumber(row, columnNo);
break;
case ValueMetaInterface.TYPE_BOOLEAN:
dataRow[columnNo] = rowMeta.getBoolean(row, columnNo);
break;
case ValueMetaInterface.TYPE_DATE:
dataRow[columnNo] = rowMeta.getDate(row, columnNo);
break;
case ValueMetaInterface.TYPE_INTEGER:
dataRow[columnNo] = rowMeta.getInteger(row, columnNo);
break;
case ValueMetaInterface.TYPE_NONE:
dataRow[columnNo] = rowMeta.getString(row, columnNo);
break;
case ValueMetaInterface.TYPE_NUMBER:
dataRow[columnNo] = rowMeta.getNumber(row, columnNo);
break;
case ValueMetaInterface.TYPE_STRING:
dataRow[columnNo] = rowMeta.getString(row, columnNo);
break;
case ValueMetaInterface.TYPE_BINARY:
dataRow[columnNo] = rowMeta.getBinary(row, columnNo);
break;
default:
dataRow[columnNo] = rowMeta.getString(row, columnNo);
}
}
tableModel.addRow(dataRow);
}
catch (final KettleValueException kve)
{
throw new KettleStepException(kve);
}
catch (final Exception e)
{
throw new KettleStepException(e);
}
}
protected TypedTableModel createTableModel(final RowMetaInterface rowMeta)
{
final int colCount = rowMeta.size();
final String fieldNames[] = new String[colCount];
final Class<?> fieldTypes[] = new Class<?>[colCount];
for (int columnNo = 0; columnNo < colCount; columnNo++)
{
final ValueMetaInterface valueMeta = rowMeta.getValueMeta(columnNo);
fieldNames[columnNo] = valueMeta.getName();
switch (valueMeta.getType())
{
case ValueMetaInterface.TYPE_BIGNUMBER:
fieldTypes[columnNo] = BigDecimal.class;
break;
case ValueMetaInterface.TYPE_BOOLEAN:
fieldTypes[columnNo] = Boolean.class;
break;
case ValueMetaInterface.TYPE_DATE:
fieldTypes[columnNo] = Date.class;
break;
case ValueMetaInterface.TYPE_INTEGER:
fieldTypes[columnNo] = Integer.class;
break;
case ValueMetaInterface.TYPE_NONE:
fieldTypes[columnNo] = String.class;
break;
case ValueMetaInterface.TYPE_NUMBER:
fieldTypes[columnNo] = Double.class;
break;
case ValueMetaInterface.TYPE_STRING:
fieldTypes[columnNo] = String.class;
break;
case ValueMetaInterface.TYPE_BINARY:
fieldTypes[columnNo] = byte[].class;
break;
default:
fieldTypes[columnNo] = String.class;
}
}
return new TypedTableModel(fieldNames, fieldTypes);
}
/**
* This method is called when a row is read from another step
*
* @param rowMeta the metadata of the row
* @param row the data of the row
* @throws org.pentaho.di.core.exception.KettleStepException an exception that can be thrown to hard stop the step
*/
public void rowReadEvent(final RowMetaInterface rowMeta, final Object[] row) throws KettleStepException
{
}
/**
* This method is called when the error handling of a row is writing a row to the error stream.
*
* @param rowMeta the metadata of the row
* @param row the data of the row
* @throws org.pentaho.di.core.exception.KettleStepException an exception that can be thrown to hard stop the step
*/
public void errorRowWrittenEvent(final RowMetaInterface rowMeta, final Object[] row) throws KettleStepException
{
if (stopOnError)
{
throw new KettleStepException("Aborting transformation due to error detected");
}
error = true;
}
public TableModel getTableModel() throws ReportDataFactoryException
{
if (stopOnError && error)
{
throw new ReportDataFactoryException("Transformation produced an error.");
}
if (tableModel == null)
{
return createTableModel(rowMeta);
}
return tableModel;
}
}