/*! ******************************************************************************
*
* Pentaho Data Integration
*
* Copyright (C) 2002-2015 by Pentaho : http://www.pentaho.com
*
*******************************************************************************
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*
* Created on 4-apr-2003
*
*/
package org.pentaho.di.shapefilereader;
import org.pentaho.di.core.Const;
import org.pentaho.di.core.exception.KettleStepException;
import org.pentaho.di.core.row.RowDataUtil;
import org.pentaho.di.core.row.RowMeta;
import org.pentaho.di.core.row.RowMetaInterface;
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;
import org.pentaho.gis.shapefiles.Shape;
import org.pentaho.gis.shapefiles.ShapeFile;
import org.pentaho.gis.shapefiles.ShapeInterface;
import org.pentaho.gis.shapefiles.ShapePoint;
import org.pentaho.gis.shapefiles.ShapePolyLine;
import org.pentaho.gis.shapefiles.ShapePolyLineM;
import org.pentaho.gis.shapefiles.ShapePolygon;
public class ShapeFileReader extends BaseStep implements StepInterface
{
private ShapeFileReaderMeta meta;
private ShapeFileReaderData data;
public ShapeFileReader(StepMeta s, StepDataInterface stepDataInterface, int c, TransMeta t, Trans dis)
{
super(s,stepDataInterface,c,t,dis);
}
public synchronized boolean processRow(StepMetaInterface smi, StepDataInterface sdi) throws KettleStepException
{
meta = (ShapeFileReaderMeta)smi;
data = (ShapeFileReaderData)sdi;
boolean retval=true;
if (data.shapeNr>=data.shapeFile.getNrShapes())
{
setOutputDone();
return false;
}
if (first)
{
first=false;
data.outputRowMeta = new RowMeta();
meta.getFields(data.outputRowMeta, getStepname(), null, null, this);
}
// building new row
Object[] outputRow = RowDataUtil.allocateRowData(data.outputRowMeta.size());
int outputIndex;
// getting shape # data.shapeNr from shapefile
// Get the shape from the shapefile
//
ShapeInterface si = data.shapeFile.getShape(data.shapeNr);
switch(si.getType())
{
case Shape.SHAPE_TYPE_POLYLINE_M:
{
// PolyLimeM";
ShapePolyLineM eplm = (ShapePolyLineM)si;
int partnr=0;
for (int j=0;j<eplm.nrpoints;j++)
{
// PolyLimeM, point #"+j;
for (int k=0;k<eplm.nrparts;k++)
{
if (j==eplm.part_starts[k]) partnr++;
}
outputIndex=0;
// adding the basics";
// Add the basics...
// The filename...
outputRow[outputIndex++] = meta.getShapeFilename();
// The file type
outputRow[outputIndex++] = data.shapeFile.getFileHeader().getShapeTypeDesc();
// The shape nr
outputRow[outputIndex++] = new Long(data.shapeNr+1);
// The part nr
outputRow[outputIndex++] = new Long(partnr);
// The nr of parts
outputRow[outputIndex++] = new Long(eplm.nrparts);
// The point nr
outputRow[outputIndex++] = new Long(j+1);
// The nr of points
outputRow[outputIndex++] = new Long(eplm.nrpoints);
// The X coordinate
outputRow[outputIndex++] = new Double(eplm.point[j].x);
// The Y coordinate
outputRow[outputIndex++] = new Double(eplm.point[j].y);
// The measure
outputRow[outputIndex++] = new Double(eplm.measures[j]);
// The Values in the DBF file...
// PolyLimeM, point #"+j+", add dbf data";
Object[] dbfData = si.getDbfData();
RowMetaInterface dbfMeta = si.getDbfMeta();
for (int d=0;d<dbfMeta.size();d++)
{
outputRow[outputIndex++] = dbfData[d];
}
linesInput++;
// Put it out to the rest of the world...
putRow(data.outputRowMeta, outputRow);
}
}
break;
case Shape.SHAPE_TYPE_POLYGON:
{
// ShapePolygon";
ShapePolygon epl = (ShapePolygon)si;
int partnr=0;
for (int j=0;j<epl.nrpoints;j++)
{
// PolyLime, point #"+j;
for (int k=0;k<epl.nrparts;k++)
{
if (j==epl.part_starts[k]) partnr++;
}
outputIndex=0;
// adding the basics";
// Add the basics...
// The filename...
outputRow[outputIndex++] = meta.getShapeFilename();
// The file type
outputRow[outputIndex++] = data.shapeFile.getFileHeader().getShapeTypeDesc();
// The shape nr
outputRow[outputIndex++] = new Long(data.shapeNr+1);
// The part nr
outputRow[outputIndex++] = new Long(partnr);
// The nr of parts
outputRow[outputIndex++] = new Long(epl.nrparts);
// The point nr
outputRow[outputIndex++] = new Long(j+1);
// The nr of points
outputRow[outputIndex++] = new Long(epl.nrpoints);
// The X coordinate
outputRow[outputIndex++] = new Double(epl.point[j].x);
// The Y coordinate
outputRow[outputIndex++] = new Double(epl.point[j].y);
// The measure
outputRow[outputIndex++] = new Double(0.0);
// The Values in the DBF file...
// PolyLime, point #"+j+", add dbf data";
//
Object[] dbfData = si.getDbfData();
RowMetaInterface dbfMeta = si.getDbfMeta();
for (int d=0;d<dbfMeta.size();d++)
{
outputRow[outputIndex++] = dbfData[d];
}
linesInput++;
// Put it out to the rest of the world...
putRow(data.outputRowMeta, outputRow);
}
}
break;
case Shape.SHAPE_TYPE_POLYLINE:
{
// PolyLime";
ShapePolyLine epl = (ShapePolyLine)si;
int partnr=0;
for (int j=0;j<epl.nrpoints;j++)
{
// PolyLime, point #"+j;
for (int k=0;k<epl.nrparts;k++)
{
if (j==epl.part_starts[k]) partnr++;
}
outputIndex=0;
// adding the basics";
// Add the basics...
// The filename...
outputRow[outputIndex++] = meta.getShapeFilename();
// The file type
outputRow[outputIndex++] = data.shapeFile.getFileHeader().getShapeTypeDesc();
// The shape nr
outputRow[outputIndex++] = new Long(data.shapeNr+1);
// The part nr
outputRow[outputIndex++] = new Long(partnr);
// The nr of parts
outputRow[outputIndex++] = new Long(epl.nrparts);
// The point nr
outputRow[outputIndex++] = new Long(j+1);
// The nr of points
outputRow[outputIndex++] = new Long(epl.nrpoints);
// The X coordinate
outputRow[outputIndex++] = new Double(epl.point[j].x);
// The Y coordinate
outputRow[outputIndex++] = new Double(epl.point[j].y);
// The measure
outputRow[outputIndex++] = new Double(0.0);
// The Values in the DBF file...
// PolyLime, point #"+j+", add dbf data";
//
Object[] dbfData = si.getDbfData();
RowMetaInterface dbfMeta = si.getDbfMeta();
for (int d=0;d<dbfMeta.size();d++)
{
outputRow[outputIndex++] = dbfData[d];
}
linesInput++;
// Put it out to the rest of the world...
putRow(data.outputRowMeta, outputRow);
}
}
break;
case Shape.SHAPE_TYPE_POINT:
{
// Point";
ShapePoint ep = (ShapePoint)si;
// Add the basics...
outputIndex=0;
// The filename...
outputRow[outputIndex++] = meta.getShapeFilename();
// The file type
outputRow[outputIndex++] = data.shapeFile.getFileHeader().getShapeTypeDesc();
// The shape nr
outputRow[outputIndex++] = new Long(data.shapeNr);
// The part nr
outputRow[outputIndex++] = new Long(0L);
// The nr of parts
outputRow[outputIndex++] = new Long(0L);
// The point nr
outputRow[outputIndex++] = new Long(0L);
// The nr of points
outputRow[outputIndex++] = new Long(0L);
// The X coordinate
outputRow[outputIndex++] = new Double(ep.x);
// The Y coordinate
outputRow[outputIndex++] = new Double(ep.y);
// The measure
outputRow[outputIndex++] = new Double(0.0);
// The Values in the DBF file...
// PolyLimeM, point #"+data.shapeNr+", add dbf data";
//
Object[] dbfData = si.getDbfData();
RowMetaInterface dbfMeta = si.getDbfMeta();
for (int d=0;d<dbfMeta.size();d++)
{
outputRow[outputIndex++] = dbfData[d];
}
linesInput++;
// Put it out to the rest of the world...
putRow(data.outputRowMeta, outputRow);
}
break;
default:
System.out.println("Unable to parse shape type ["+Shape.getEsriTypeDesc(si.getType())+"] : not yet implemented.");
throw new KettleStepException("Unable to parse shape type ["+Shape.getEsriTypeDesc(si.getType())+"] : not yet implemented.");
}
// Next shape please!
data.shapeNr++;
if ((linesInput%Const.ROWS_UPDATE)==0) logBasic("linenr "+linesInput);
return retval;
}
public boolean init(StepMetaInterface smi, StepDataInterface sdi)
{
meta = (ShapeFileReaderMeta)smi;
data = (ShapeFileReaderData)sdi;
if (super.init(meta, data))
{
if (meta.getShapeFilename()==null ||
meta.getDbfFilename()==null ||
meta.getShapeFilename().length()==0 ||
meta.getDbfFilename().length()==0
)
{
logError("We need both a shapefile and a DBF file.");
return false;
}
data.shapeFile = new ShapeFile(log, meta.getShapeFilename(), meta.getDbfFilename());
try
{
data.shapeFile.readFile();
}
catch(Exception e)
{
logError("Unable to read shapefile ["+meta.getShapeFilename()+"] because of an error: "+e.toString());
return false;
}
data.shapeNr=0;
}
return true;
}
public void dispose(StepMetaInterface smi, StepDataInterface sdi)
{
meta = (ShapeFileReaderMeta)smi;
data = (ShapeFileReaderData)sdi;
super.dispose(smi, sdi);
}
//
// Run is were the action happens!
//
//
public void run()
{
logBasic("Starting to run...");
try
{
while (processRow(meta, data) && !isStopped());
}
catch(Exception e)
{
logError("Unexpected error", e);
setErrors(1);
stopAll();
}
finally
{
dispose(meta, data);
logBasic("Finished, processed "+linesInput+" rows, written "+linesWritten+" lines.");
markStop();
}
}
}