/*! ******************************************************************************
*
* Pentaho Data Integration
*
* Copyright (C) 2002-2016 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.
*
******************************************************************************/
package org.pentaho.di.trans.steps.xslt;
import java.io.File;
import java.util.List;
import org.pentaho.di.core.annotations.Step;
import org.pentaho.di.core.CheckResult;
import org.pentaho.di.core.CheckResultInterface;
import org.pentaho.di.core.Const;
import org.pentaho.di.core.util.Utils;
import org.pentaho.di.core.database.DatabaseMeta;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.exception.KettleStepException;
import org.pentaho.di.core.exception.KettleXMLException;
import org.pentaho.di.core.row.RowMetaInterface;
import org.pentaho.di.core.row.ValueMeta;
import org.pentaho.di.core.row.ValueMetaInterface;
import org.pentaho.di.core.variables.VariableSpace;
import org.pentaho.di.core.xml.XMLHandler;
import org.pentaho.di.i18n.BaseMessages;
import org.pentaho.di.repository.ObjectId;
import org.pentaho.di.repository.Repository;
import org.pentaho.di.trans.Trans;
import org.pentaho.di.trans.TransMeta;
import org.pentaho.di.trans.step.BaseStepMeta;
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.metastore.api.IMetaStore;
import org.w3c.dom.Node;
/*
* Created on 15-Oct-2007
*
*/
@Step( id = "XSLT", image = "XSLT.svg", i18nPackageName = "org.pentaho.di.trans.steps.xslt", name = "XSLT.name",
description = "XSLT.description", categoryDescription = "XSLT.category",
documentationUrl = "http://wiki.pentaho.com/display/EAI/XSL+Transformation" )
public class XsltMeta extends BaseStepMeta implements StepMetaInterface {
private static Class<?> PKG = XsltMeta.class; // for i18n purposes, needed by Translator2!!
public static final String[] outputProperties = new String[] { "method", "version", "encoding", "standalone",
"indent", "omit-xml-declaration", "doctype-public", "doctype-system", "media-type" };
private String xslFilename;
private String fieldName;
private String resultFieldname;
private String xslFileField;
private boolean xslFileFieldUse;
private boolean xslFieldIsAFile;
private String xslFactory;
/** output property name */
private String[] outputPropertyName;
/** output property value */
private String[] outputPropertyValue;
/** parameter name */
private String[] parameterName;
/** parameter field */
private String[] parameterField;
public XsltMeta() {
super(); // allocate BaseStepMeta
}
/**
* @return Returns the parameterName.
*/
public String[] getParameterName() {
return parameterName;
}
/**
* @param argumentDirection
* The parameterName to set.
*/
public void setParameterName( String[] argumentDirection ) {
this.parameterName = argumentDirection;
}
/**
* @return Returns the parameterField.
*/
public String[] getParameterField() {
return parameterField;
}
/**
* @param argumentDirection
* The parameterField to set.
*/
public void setParameterField( String[] argumentDirection ) {
this.parameterField = argumentDirection;
}
/**
* @return Returns the XSL filename.
*/
public String getXslFilename() {
return xslFilename;
}
/**
* @return Returns the OutputPropertyName.
*/
public String[] getOutputPropertyName() {
return outputPropertyName;
}
/**
* @param argumentDirection
* The OutputPropertyName to set.
*/
public void setOutputPropertyName( String[] argumentDirection ) {
this.outputPropertyName = argumentDirection;
}
/**
* @return Returns the OutputPropertyField.
*/
public String[] getOutputPropertyValue() {
return outputPropertyValue;
}
/**
* @param argumentDirection
* The outputPropertyValue to set.
*/
public void setOutputPropertyValue( String[] argumentDirection ) {
this.outputPropertyValue = argumentDirection;
}
public void setXSLFileField( String xslfilefieldin ) {
xslFileField = xslfilefieldin;
}
public void setXSLFactory( String xslfactoryin ) {
xslFactory = xslfactoryin;
}
/**
* @return Returns the XSL factory type.
*/
public String getXSLFactory() {
return xslFactory;
}
public String getXSLFileField() {
return xslFileField;
}
public String getResultfieldname() {
return resultFieldname;
}
public String getFieldname() {
return fieldName;
}
/**
* @param xslFilename
* The Xsl filename to set.
*/
public void setXslFilename( String xslFilename ) {
this.xslFilename = xslFilename;
}
public void setResultfieldname( String resultfield ) {
this.resultFieldname = resultfield;
}
public void setFieldname( String fieldnamein ) {
this.fieldName = fieldnamein;
}
public void loadXML( Node stepnode, List<DatabaseMeta> databases, IMetaStore metaStore ) throws KettleXMLException {
readData( stepnode );
}
public void allocate( int nrParameters, int outputProps ) {
parameterName = new String[nrParameters];
parameterField = new String[nrParameters];
outputPropertyName = new String[outputProps];
outputPropertyValue = new String[outputProps];
}
public Object clone() {
XsltMeta retval = (XsltMeta) super.clone();
int nrparams = parameterName.length;
int nroutputprops = outputPropertyName.length;
retval.allocate( nrparams, nroutputprops );
for ( int i = 0; i < nrparams; i++ ) {
retval.parameterName[i] = parameterName[i];
retval.parameterField[i] = parameterField[i];
}
for ( int i = 0; i < nroutputprops; i++ ) {
retval.outputPropertyName[i] = outputPropertyName[i];
retval.outputPropertyValue[i] = outputPropertyValue[i];
}
return retval;
}
public boolean useXSLField() {
return xslFileFieldUse;
}
public void setXSLField( boolean value ) {
this.xslFileFieldUse = value;
}
public void setXSLFieldIsAFile( boolean xslFieldisAFile ) {
this.xslFieldIsAFile = xslFieldisAFile;
}
public boolean isXSLFieldIsAFile() {
return xslFieldIsAFile;
}
private void readData( Node stepnode ) throws KettleXMLException {
try {
xslFilename = XMLHandler.getTagValue( stepnode, "xslfilename" );
fieldName = XMLHandler.getTagValue( stepnode, "fieldname" );
resultFieldname = XMLHandler.getTagValue( stepnode, "resultfieldname" );
xslFileField = XMLHandler.getTagValue( stepnode, "xslfilefield" );
xslFileFieldUse = "Y".equalsIgnoreCase( XMLHandler.getTagValue( stepnode, "xslfilefielduse" ) );
String isAFile = XMLHandler.getTagValue( stepnode, "xslfieldisafile" );
if ( xslFileFieldUse && Utils.isEmpty( isAFile ) ) {
xslFieldIsAFile = true;
} else {
xslFieldIsAFile = "Y".equalsIgnoreCase( isAFile );
}
xslFactory = XMLHandler.getTagValue( stepnode, "xslfactory" );
Node parametersNode = XMLHandler.getSubNode( stepnode, "parameters" );
int nrparams = XMLHandler.countNodes( parametersNode, "parameter" );
Node parametersOutputProps = XMLHandler.getSubNode( stepnode, "outputproperties" );
int nroutputprops = XMLHandler.countNodes( parametersOutputProps, "outputproperty" );
allocate( nrparams, nroutputprops );
for ( int i = 0; i < nrparams; i++ ) {
Node anode = XMLHandler.getSubNodeByNr( parametersNode, "parameter", i );
parameterField[i] = XMLHandler.getTagValue( anode, "field" );
parameterName[i] = XMLHandler.getTagValue( anode, "name" );
}
for ( int i = 0; i < nroutputprops; i++ ) {
Node anode = XMLHandler.getSubNodeByNr( parametersOutputProps, "outputproperty", i );
outputPropertyName[i] = XMLHandler.getTagValue( anode, "name" );
outputPropertyValue[i] = XMLHandler.getTagValue( anode, "value" );
}
} catch ( Exception e ) {
throw new KettleXMLException( BaseMessages.getString( PKG, "XsltMeta.Exception.UnableToLoadStepInfoFromXML" ), e );
}
}
public void setDefault() {
xslFilename = null;
fieldName = null;
resultFieldname = "result";
xslFactory = "JAXP";
xslFileField = null;
xslFileFieldUse = false;
xslFieldIsAFile = true;
int nrparams = 0;
int nroutputproperties = 0;
allocate( nrparams, nroutputproperties );
for ( int i = 0; i < nrparams; i++ ) {
parameterField[i] = "param" + i;
parameterName[i] = "param";
}
for ( int i = 0; i < nroutputproperties; i++ ) {
outputPropertyName[i] = "outputprop" + i;
outputPropertyValue[i] = "outputprop";
}
}
public void getFields( RowMetaInterface inputRowMeta, String name, RowMetaInterface[] info, StepMeta nextStep,
VariableSpace space, Repository repository, IMetaStore metaStore ) throws KettleStepException {
// Output field (String)
ValueMetaInterface v = new ValueMeta( space.environmentSubstitute( getResultfieldname() ), ValueMeta.TYPE_STRING );
v.setOrigin( name );
inputRowMeta.addValueMeta( v );
}
public String getXML() {
StringBuffer retval = new StringBuffer();
retval.append( " " + XMLHandler.addTagValue( "xslfilename", xslFilename ) );
retval.append( " " + XMLHandler.addTagValue( "fieldname", fieldName ) );
retval.append( " " + XMLHandler.addTagValue( "resultfieldname", resultFieldname ) );
retval.append( " " + XMLHandler.addTagValue( "xslfilefield", xslFileField ) );
retval.append( " " + XMLHandler.addTagValue( "xslfilefielduse", xslFileFieldUse ) );
retval.append( " " + XMLHandler.addTagValue( "xslfieldisafile", xslFieldIsAFile ) );
retval.append( " " + XMLHandler.addTagValue( "xslfactory", xslFactory ) );
retval.append( " <parameters>" ).append( Const.CR );
for ( int i = 0; i < parameterName.length; i++ ) {
retval.append( " <parameter>" ).append( Const.CR );
retval.append( " " ).append( XMLHandler.addTagValue( "field", parameterField[i] ) );
retval.append( " " ).append( XMLHandler.addTagValue( "name", parameterName[i] ) );
retval.append( " </parameter>" ).append( Const.CR );
}
retval.append( " </parameters>" ).append( Const.CR );
retval.append( " <outputproperties>" ).append( Const.CR );
for ( int i = 0; i < outputPropertyName.length; i++ ) {
retval.append( " <outputproperty>" ).append( Const.CR );
retval.append( " " ).append( XMLHandler.addTagValue( "name", outputPropertyName[i] ) );
retval.append( " " ).append( XMLHandler.addTagValue( "value", outputPropertyValue[i] ) );
retval.append( " </outputproperty>" ).append( Const.CR );
}
retval.append( " </outputproperties>" ).append( Const.CR );
return retval.toString();
}
public void readRep( Repository rep, IMetaStore metaStore, ObjectId id_step, List<DatabaseMeta> databases )
throws KettleException {
try {
xslFilename = rep.getStepAttributeString( id_step, "xslfilename" );
fieldName = rep.getStepAttributeString( id_step, "fieldname" );
resultFieldname = rep.getStepAttributeString( id_step, "resultfieldname" );
xslFileField = rep.getStepAttributeString( id_step, "xslfilefield" );
xslFileFieldUse = rep.getStepAttributeBoolean( id_step, "xslfilefielduse" );
String isAfile = rep.getStepAttributeString( id_step, "xslfieldisafile" );
if ( xslFileFieldUse && Utils.isEmpty( isAfile ) ) {
xslFieldIsAFile = true;
} else {
xslFieldIsAFile = "true".equalsIgnoreCase( isAfile );
}
xslFactory = rep.getStepAttributeString( id_step, "xslfactory" );
int nrparams = rep.countNrStepAttributes( id_step, "param_name" );
int nroutputprops = rep.countNrStepAttributes( id_step, "output_property_name" );
allocate( nrparams, nroutputprops );
for ( int i = 0; i < nrparams; i++ ) {
parameterField[i] = rep.getStepAttributeString( id_step, i, "param_field" );
parameterName[i] = rep.getStepAttributeString( id_step, i, "param_name" );
}
for ( int i = 0; i < nroutputprops; i++ ) {
outputPropertyName[i] = rep.getStepAttributeString( id_step, i, "output_property_name" );
outputPropertyValue[i] = rep.getStepAttributeString( id_step, i, "output_property_value" );
}
} catch ( Exception e ) {
throw new KettleException( BaseMessages.getString( PKG, "XsltMeta.Exception.UnexpectedErrorInReadingStepInfo" ),
e );
}
}
public void saveRep( Repository rep, IMetaStore metaStore, ObjectId id_transformation, ObjectId id_step )
throws KettleException {
try {
rep.saveStepAttribute( id_transformation, id_step, "xslfilename", xslFilename );
rep.saveStepAttribute( id_transformation, id_step, "fieldname", fieldName );
rep.saveStepAttribute( id_transformation, id_step, "resultfieldname", resultFieldname );
rep.saveStepAttribute( id_transformation, id_step, "xslfilefield", xslFileField );
rep.saveStepAttribute( id_transformation, id_step, "xslfilefielduse", xslFileFieldUse );
rep.saveStepAttribute( id_transformation, id_step, "xslfieldisafile", xslFieldIsAFile );
rep.saveStepAttribute( id_transformation, id_step, "xslfactory", xslFactory );
for ( int i = 0; i < parameterName.length; i++ ) {
rep.saveStepAttribute( id_transformation, id_step, i, "param_field", parameterField[i] );
rep.saveStepAttribute( id_transformation, id_step, i, "param_name", parameterName[i] );
}
for ( int i = 0; i < outputPropertyName.length; i++ ) {
rep.saveStepAttribute( id_transformation, id_step, i, "output_property_name", outputPropertyName[i] );
rep.saveStepAttribute( id_transformation, id_step, i, "output_property_value", outputPropertyValue[i] );
}
} catch ( Exception e ) {
throw new KettleException( BaseMessages.getString( PKG, "XsltMeta.Exception.UnableToSaveStepInfo" ) + id_step, e );
}
}
public void check( List<CheckResultInterface> remarks, TransMeta transMeta, StepMeta stepMeta, RowMetaInterface prev,
String[] input, String[] output, RowMetaInterface info, VariableSpace space, Repository repository,
IMetaStore metaStore ) {
CheckResult cr;
if ( prev != null && prev.size() > 0 ) {
cr =
new CheckResult( CheckResult.TYPE_RESULT_OK, BaseMessages.getString( PKG,
"XsltMeta.CheckResult.ConnectedStepOK", String.valueOf( prev.size() ) ), stepMeta );
remarks.add( cr );
} else {
cr =
new CheckResult( CheckResult.TYPE_RESULT_ERROR, BaseMessages.getString( PKG,
"XsltMeta.CheckResult.NoInputReceived" ), stepMeta );
remarks.add( cr );
}
// See if we have input streams leading to this step!
if ( input.length > 0 ) {
cr =
new CheckResult( CheckResultInterface.TYPE_RESULT_OK, BaseMessages.getString( PKG,
"XsltMeta.CheckResult.ExpectedInputOk" ), stepMeta );
remarks.add( cr );
} else {
cr =
new CheckResult( CheckResultInterface.TYPE_RESULT_ERROR, BaseMessages.getString( PKG,
"XsltMeta.CheckResult.ExpectedInputError" ), stepMeta );
remarks.add( cr );
}
// Check if The result field is given
if ( getResultfieldname() == null ) {
// Result Field is missing !
cr =
new CheckResult( CheckResult.TYPE_RESULT_ERROR, BaseMessages.getString( PKG,
"XsltMeta.CheckResult.ErrorResultFieldNameMissing" ), stepMeta );
remarks.add( cr );
}
// Check if XSL Filename field is provided
if ( xslFileFieldUse ) {
if ( getXSLFileField() == null ) {
// Result Field is missing !
cr =
new CheckResult( CheckResult.TYPE_RESULT_ERROR, BaseMessages.getString( PKG,
"XsltMeta.CheckResult.ErrorResultXSLFieldNameMissing" ), stepMeta );
remarks.add( cr );
} else {
// Result Field is provided !
cr =
new CheckResult( CheckResult.TYPE_RESULT_OK, BaseMessages.getString( PKG,
"XsltMeta.CheckResult.ErrorResultXSLFieldNameOK" ), stepMeta );
remarks.add( cr );
}
} else {
if ( xslFilename == null ) {
// Result Field is missing !
cr =
new CheckResult( CheckResult.TYPE_RESULT_ERROR, BaseMessages.getString( PKG,
"XsltMeta.CheckResult.ErrorXSLFileNameMissing" ), stepMeta );
remarks.add( cr );
} else {
// Check if it's exist and it's a file
String RealFilename = transMeta.environmentSubstitute( xslFilename );
File f = new File( RealFilename );
if ( f.exists() ) {
if ( f.isFile() ) {
cr =
new CheckResult( CheckResultInterface.TYPE_RESULT_OK, BaseMessages.getString( PKG,
"XsltMeta.CheckResult.FileExists", RealFilename ), stepMeta );
remarks.add( cr );
} else {
cr =
new CheckResult( CheckResultInterface.TYPE_RESULT_ERROR, BaseMessages.getString( PKG,
"XsltMeta.CheckResult.ExistsButNoFile", RealFilename ), stepMeta );
remarks.add( cr );
}
} else {
cr =
new CheckResult( CheckResultInterface.TYPE_RESULT_ERROR, BaseMessages.getString( PKG,
"XsltMeta.CheckResult.FileNotExists", RealFilename ), stepMeta );
remarks.add( cr );
}
}
}
}
public StepInterface getStep( StepMeta stepMeta, StepDataInterface stepDataInterface, int cnr, TransMeta transMeta,
Trans trans ) {
return new Xslt( stepMeta, stepDataInterface, cnr, transMeta, trans );
}
public StepDataInterface getStepData() {
return new XsltData();
}
public boolean supportsErrorHandling() {
return true;
}
}