/*
* This file is part of PaloKettlePlugin.
*
* PaloKettlePlugin 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.
*
* PaloKettlePlugin 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 PaloKettlePlugin. If not, see <http://www.gnu.org/licenses/>.
*
* Portions Copyright 2008 Stratebi Business Solutions, S.L.
* Portions Copyright 2011 De Bortoli Wines Pty Limited (Australia)
* Portions Copyright 2011 - 2013 Pentaho Corporation
*/
package org.pentaho.di.trans.steps.palo.dimoutput;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.palo.core.ConsolidationCollection;
import org.pentaho.di.palo.core.ConsolidationElement;
import org.pentaho.di.palo.core.PaloHelper;
import org.pentaho.di.trans.Trans;
import org.pentaho.di.trans.TransMeta;
import org.pentaho.di.trans.step.BaseStep;
import org.pentaho.di.trans.step.StepDataInterface;
import org.pentaho.di.trans.step.StepInterface;
import org.pentaho.di.trans.step.StepMeta;
import org.pentaho.di.trans.step.StepMetaInterface;
public class PaloDimOutput extends BaseStep implements StepInterface {
private PaloDimOutputMeta meta;
private PaloDimOutputData data;
private int rowCount = 0;
private ConsolidationCollection consolidations;
public PaloDimOutput( final StepMeta stepMeta, final StepDataInterface stepDataInterface, final int copyNr,
final TransMeta transMeta, final Trans trans ) {
super( stepMeta, stepDataInterface, copyNr, transMeta, trans );
}
public final boolean processRow( final StepMetaInterface smi, final StepDataInterface sdi ) throws KettleException {
meta = (PaloDimOutputMeta) smi;
data = (PaloDimOutputData) sdi;
Object[] r = getRow();
if ( first ) {
first = false;
this.logBasic( "First Row Analysis:" );
if ( meta.getLevels().size() == 0 ) {
throw new KettleException( "Number of levels must be greater that 0 to process the rows" );
}
this.logBasic( "Number of defined levels: " + meta.getLevels().size() );
/* Indexes will follow [data index],[consolidation index],[data index],[consolidation index] .... */
data.indexes = new int[meta.getLevels().size() * 2];
for ( int i = 0; i < meta.getLevels().size(); i++ ) {
/* Get data field index */
String dataFieldName = meta.getLevels().get( i ).getFieldName();
int numRow = getInputRowMeta().indexOfValue( dataFieldName );
if ( numRow < 0 ) {
throw new KettleException( "DimOutput: failed to find input row meta for ".concat( meta.getLevels().get( i )
.getLevelName() ) );
}
data.indexes[i * 2] = numRow;
this.logDebug( meta.getLevels().get( i ).getLevelName() + " has index: " + numRow );
/* Get consolidation field index */
String consolidationFieldName = meta.getLevels().get( i ).getConsolidationFieldName();
if ( consolidationFieldName == null ) {
numRow = -1;
this.logDebug( "Consolidation factor was left to the default" );
} else {
numRow = getInputRowMeta().indexOfValue( consolidationFieldName );
if ( numRow < 0 ) {
throw new KettleException( "DimOutput: failed to find input row meta for ".concat( meta.getLevels().get( i )
.getConsolidationFieldName() ) );
}
this.logDebug( meta.getLevels().get( i ).getConsolidationFieldName() + " has index: " + numRow );
}
data.indexes[( i * 2 ) + 1] = numRow;
}
data.helper.manageDimension( meta.getDimension(), meta.getCreateNewDimension(), meta.getClearDimension(), meta
.getClearConsolidations(), meta.getRecreateDimension() );
try {
data.helper.loadDimensionCache( meta.getDimension(), meta.getEnableElementCache(), meta
.getPreloadElementCache() );
} catch ( Exception e ) {
throw new KettleException( "Failed to load cache", e );
}
}
if ( r != null ) {
rowCount++;
try {
ConsolidationElement parent = null;
for ( int i = 0; i < data.indexes.length; i++ ) {
if ( i % 2 == 0 ) {
if ( r[data.indexes[i]] == null ) {
continue;
}
data.elementNamesBatch.add( r[data.indexes[i]].toString() );
} else {
/* Default weight to 1 if it was left to default */
double consolidation_factor = 1;
if ( data.indexes[i] >= 0 ) {
consolidation_factor =
Double.parseDouble( ( r[data.indexes[i]] == null ? 0 : r[data.indexes[i]] ).toString() );
}
ConsolidationElement child = null;
if ( r[data.indexes[i - 1]] != null ) {
String elementName = r[data.indexes[i - 1]].toString();
if ( !this.consolidations.hasConsolidationElement( elementName ) ) {
child = new ConsolidationElement( elementName );
this.consolidations.add( child );
} else {
child = this.consolidations.getConsolidationElement( elementName );
}
if ( parent != null ) {
parent.addChild( child, consolidation_factor );
}
}
parent = child;
}
}
// Should probably make this a parameter on the dialog
if ( data.elementNamesBatch.size() % 100 == 0 ) {
commitBatch();
}
} catch ( Exception e ) {
throw new KettleException( "Failed to add row to the row buffer", e );
}
}
// this also waits for a previous step to be finished.
if ( r == null ) { // no more input to be expected...
try {
if ( data.elementNamesBatch.size() > 0 ) {
commitBatch();
}
// Because we add rows in bulk, the dimension cache isn't complete. It only keeps a list
// of added items for validation. If the cache must be pre-loaded, pre-load it now.
data.helper.clearDimensionCache();
data.helper.loadDimensionCache( meta.getDimension(), meta.getEnableElementCache(), meta
.getPreloadElementCache() );
// if it's the last row create the dimension
this.logBasic( "All rows have been added. Looking for consolidations" );
this.logBasic( "Updating consolidations for Dimension" + meta.getDimension() );
data.helper.addDimensionConsolidations( meta.getDimension(), this.consolidations );
this.logBasic( "Consolidations updated." );
setOutputDone();
return false;
} catch ( Exception e ) {
throw new KettleException( "Failed to add dimension rows", e );
}
}
return true;
}
private void commitBatch() throws Exception {
data.helper.addDimensionElements( data.elementNamesBatch, meta.getElementType() );
while ( rowCount > 0 ) {
incrementLinesOutput();
rowCount--;
}
data.elementNamesBatch.clear();
}
public final boolean init( StepMetaInterface smi, StepDataInterface sdi ) {
meta = (PaloDimOutputMeta) smi;
data = (PaloDimOutputData) sdi;
this.consolidations = new ConsolidationCollection();
if ( super.init( smi, sdi ) ) {
try {
this.logBasic( "Meta Levels:" + meta.getLevels().size() );
data.helper = new PaloHelper( meta.getDatabaseMeta(), getLogLevel() );
data.helper.connect();
return true;
} catch ( Exception e ) {
logError( "An error occurred, processing will be stopped: " + e.getMessage() );
setErrors( 1 );
stopAll();
}
}
return false;
}
public void dispose( StepMetaInterface smi, StepDataInterface sdi ) {
data.helper.disconnect();
super.dispose( smi, sdi );
}
}