org.pentaho.di.trans.steps.csvinput.CsvInputMeta.java Source code

Java tutorial

Introduction

Here is the source code for org.pentaho.di.trans.steps.csvinput.CsvInputMeta.java

Source

/*! ******************************************************************************
 *
 * Pentaho Data Integration
 *
 * Copyright (C) 2002-2013 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.csvinput;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.vfs.FileObject;
import org.pentaho.di.core.CheckResult;
import org.pentaho.di.core.CheckResultInterface;
import org.pentaho.di.core.Const;
import org.pentaho.di.core.KettleAttributeInterface;
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.row.value.ValueMetaFactory;
import org.pentaho.di.core.variables.VariableSpace;
import org.pentaho.di.core.vfs.KettleVFS;
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.resource.ResourceDefinition;
import org.pentaho.di.resource.ResourceEntry;
import org.pentaho.di.resource.ResourceEntry.ResourceType;
import org.pentaho.di.resource.ResourceNamingInterface;
import org.pentaho.di.resource.ResourceReference;
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.StepInjectionMetaEntry;
import org.pentaho.di.trans.step.StepInterface;
import org.pentaho.di.trans.step.StepMeta;
import org.pentaho.di.trans.step.StepMetaInjectionInterface;
import org.pentaho.di.trans.step.StepMetaInterface;
import org.pentaho.di.trans.steps.textfileinput.InputFileMetaInterface;
import org.pentaho.di.trans.steps.textfileinput.TextFileInputField;
import org.pentaho.di.trans.steps.textfileinput.TextFileInputMeta;
import org.pentaho.metastore.api.IMetaStore;
import org.w3c.dom.Node;

/**
 * @since 2007-07-05
 * @author matt
 * @version 3.0
 */

public class CsvInputMeta extends BaseStepMeta
        implements StepMetaInterface, InputFileMetaInterface, StepMetaInjectionInterface {
    private static Class<?> PKG = CsvInput.class; // for i18n purposes, needed by Translator2!!

    private String filename;

    private String filenameField;

    private boolean includingFilename;

    private String rowNumField;

    private boolean headerPresent;

    private String delimiter;
    private String enclosure;

    private String bufferSize;

    private boolean lazyConversionActive;

    private TextFileInputField[] inputFields;

    private boolean isaddresult;

    private boolean runningInParallel;

    private String encoding;

    private boolean newlinePossibleInFields;

    public CsvInputMeta() {
        super(); // allocate BaseStepMeta
        allocate(0);
    }

    public void loadXML(Node stepnode, List<DatabaseMeta> databases, IMetaStore metaStore)
            throws KettleXMLException {
        readData(stepnode);
    }

    public Object clone() {
        Object retval = super.clone();
        return retval;
    }

    public void setDefault() {
        delimiter = ",";
        enclosure = "\"";
        headerPresent = true;
        lazyConversionActive = true;
        isaddresult = false;
        bufferSize = "50000";

        TextFileInputField field = new TextFileInputField();
        field.setName("field");
        field.setType(ValueMetaInterface.TYPE_STRING);

        inputFields = new TextFileInputField[] { field, };
    }

    private void readData(Node stepnode) throws KettleXMLException {
        try {
            filename = XMLHandler.getTagValue(stepnode, getXmlCode("FILENAME"));
            filenameField = XMLHandler.getTagValue(stepnode, getXmlCode("FILENAME_FIELD"));
            rowNumField = XMLHandler.getTagValue(stepnode, getXmlCode("ROW_NUM_FIELD"));
            includingFilename = "Y"
                    .equalsIgnoreCase(XMLHandler.getTagValue(stepnode, getXmlCode("INCLUDE_FILENAME")));
            delimiter = XMLHandler.getTagValue(stepnode, getXmlCode("DELIMITER"));
            enclosure = XMLHandler.getTagValue(stepnode, getXmlCode("ENCLOSURE"));
            bufferSize = XMLHandler.getTagValue(stepnode, getXmlCode("BUFFERSIZE"));
            headerPresent = "Y".equalsIgnoreCase(XMLHandler.getTagValue(stepnode, getXmlCode("HEADER_PRESENT")));
            lazyConversionActive = "Y"
                    .equalsIgnoreCase(XMLHandler.getTagValue(stepnode, getXmlCode("LAZY_CONVERSION")));
            isaddresult = "Y".equalsIgnoreCase(XMLHandler.getTagValue(stepnode, getXmlCode("ADD_FILENAME_RESULT")));
            runningInParallel = "Y".equalsIgnoreCase(XMLHandler.getTagValue(stepnode, getXmlCode("PARALLEL")));
            String nlp = XMLHandler.getTagValue(stepnode, getXmlCode("NEWLINE_POSSIBLE"));
            if (Const.isEmpty(nlp)) {
                if (runningInParallel) {
                    newlinePossibleInFields = false;
                } else {
                    newlinePossibleInFields = true;
                }
            } else {
                newlinePossibleInFields = "Y".equalsIgnoreCase(nlp);
            }
            encoding = XMLHandler.getTagValue(stepnode, getXmlCode("ENCODING"));

            Node fields = XMLHandler.getSubNode(stepnode, getXmlCode("FIELDS"));
            int nrfields = XMLHandler.countNodes(fields, getXmlCode("FIELD"));

            allocate(nrfields);

            for (int i = 0; i < nrfields; i++) {
                inputFields[i] = new TextFileInputField();

                Node fnode = XMLHandler.getSubNodeByNr(fields, getXmlCode("FIELD"), i);

                inputFields[i].setName(XMLHandler.getTagValue(fnode, getXmlCode("FIELD_NAME")));
                inputFields[i].setType(ValueMeta.getType(XMLHandler.getTagValue(fnode, getXmlCode("FIELD_TYPE"))));
                inputFields[i].setFormat(XMLHandler.getTagValue(fnode, getXmlCode("FIELD_FORMAT")));
                inputFields[i].setCurrencySymbol(XMLHandler.getTagValue(fnode, getXmlCode("FIELD_CURRENCY")));
                inputFields[i].setDecimalSymbol(XMLHandler.getTagValue(fnode, getXmlCode("FIELD_DECIMAL")));
                inputFields[i].setGroupSymbol(XMLHandler.getTagValue(fnode, getXmlCode("FIELD_GROUP")));
                inputFields[i]
                        .setLength(Const.toInt(XMLHandler.getTagValue(fnode, getXmlCode("FIELD_LENGTH")), -1));
                inputFields[i].setPrecision(
                        Const.toInt(XMLHandler.getTagValue(fnode, getXmlCode("FIELD_PRECISION")), -1));
                inputFields[i].setTrimType(
                        ValueMeta.getTrimTypeByCode(XMLHandler.getTagValue(fnode, getXmlCode("FIELD_TRIM_TYPE"))));
            }
        } catch (Exception e) {
            throw new KettleXMLException("Unable to load step info from XML", e);
        }
    }

    public void allocate(int nrFields) {
        inputFields = new TextFileInputField[nrFields];
    }

    public String getXML() {
        StringBuffer retval = new StringBuffer(500);

        retval.append("    ").append(XMLHandler.addTagValue(getXmlCode("FILENAME"), filename));
        retval.append("    ").append(XMLHandler.addTagValue(getXmlCode("FILENAME_FIELD"), filenameField));
        retval.append("    ").append(XMLHandler.addTagValue(getXmlCode("ROW_NUM_FIELD"), rowNumField));
        retval.append("    ").append(XMLHandler.addTagValue(getXmlCode("INCLUDE_FILENAME"), includingFilename));
        retval.append("    ").append(XMLHandler.addTagValue(getXmlCode("DELIMITER"), delimiter));
        retval.append("    ").append(XMLHandler.addTagValue(getXmlCode("ENCLOSURE"), enclosure));
        retval.append("    ").append(XMLHandler.addTagValue(getXmlCode("HEADER_PRESENT"), headerPresent));
        retval.append("    ").append(XMLHandler.addTagValue(getXmlCode("BUFFERSIZE"), bufferSize));
        retval.append("    ").append(XMLHandler.addTagValue(getXmlCode("LAZY_CONVERSION"), lazyConversionActive));
        retval.append("    ").append(XMLHandler.addTagValue(getXmlCode("ADD_FILENAME_RESULT"), isaddresult));
        retval.append("    ").append(XMLHandler.addTagValue(getXmlCode("PARALLEL"), runningInParallel));
        retval.append("    ")
                .append(XMLHandler.addTagValue(getXmlCode("NEWLINE_POSSIBLE"), newlinePossibleInFields));
        retval.append("    ").append(XMLHandler.addTagValue(getXmlCode("ENCODING"), encoding));

        retval.append("    ").append(XMLHandler.openTag(getXmlCode("FIELDS"))).append(Const.CR);
        for (int i = 0; i < inputFields.length; i++) {
            TextFileInputField field = inputFields[i];

            retval.append("      ").append(XMLHandler.openTag(getXmlCode("FIELD"))).append(Const.CR);
            retval.append("        ").append(XMLHandler.addTagValue(getXmlCode("FIELD_NAME"), field.getName()));
            retval.append("        ").append(
                    XMLHandler.addTagValue(getXmlCode("FIELD_TYPE"), ValueMeta.getTypeDesc(field.getType())));
            retval.append("        ").append(XMLHandler.addTagValue(getXmlCode("FIELD_FORMAT"), field.getFormat()));
            retval.append("        ")
                    .append(XMLHandler.addTagValue(getXmlCode("FIELD_CURRENCY"), field.getCurrencySymbol()));
            retval.append("        ")
                    .append(XMLHandler.addTagValue(getXmlCode("FIELD_DECIMAL"), field.getDecimalSymbol()));
            retval.append("        ")
                    .append(XMLHandler.addTagValue(getXmlCode("FIELD_GROUP"), field.getGroupSymbol()));
            retval.append("        ").append(XMLHandler.addTagValue(getXmlCode("FIELD_LENGTH"), field.getLength()));
            retval.append("        ")
                    .append(XMLHandler.addTagValue(getXmlCode("FIELD_PRECISION"), field.getPrecision()));
            retval.append("        ").append(XMLHandler.addTagValue(getXmlCode("FIELD_TRIM_TYPE"),
                    ValueMeta.getTrimTypeCode(field.getTrimType())));
            retval.append("      ").append(XMLHandler.closeTag(getXmlCode("FIELD"))).append(Const.CR);
        }
        retval.append("    ").append(XMLHandler.closeTag(getXmlCode("FIELDS"))).append(Const.CR);

        return retval.toString();
    }

    public void readRep(Repository rep, IMetaStore metaStore, ObjectId id_step, List<DatabaseMeta> databases)
            throws KettleException {
        try {
            filename = rep.getStepAttributeString(id_step, getRepCode("FILENAME"));
            filenameField = rep.getStepAttributeString(id_step, getRepCode("FILENAME_FIELD"));
            rowNumField = rep.getStepAttributeString(id_step, getRepCode("ROW_NUM_FIELD"));
            includingFilename = rep.getStepAttributeBoolean(id_step, getRepCode("INCLUDE_FILENAME"));
            delimiter = rep.getStepAttributeString(id_step, getRepCode("DELIMITER"));
            enclosure = rep.getStepAttributeString(id_step, getRepCode("ENCLOSURE"));
            headerPresent = rep.getStepAttributeBoolean(id_step, getRepCode("HEADER_PRESENT"));
            bufferSize = rep.getStepAttributeString(id_step, getRepCode("BUFFERSIZE"));
            lazyConversionActive = rep.getStepAttributeBoolean(id_step, getRepCode("LAZY_CONVERSION"));
            isaddresult = rep.getStepAttributeBoolean(id_step, getRepCode("ADD_FILENAME_RESULT"));
            runningInParallel = rep.getStepAttributeBoolean(id_step, getRepCode("PARALLEL"));
            newlinePossibleInFields = rep.getStepAttributeBoolean(id_step, 0, getRepCode("NEWLINE_POSSIBLE"),
                    !runningInParallel);
            encoding = rep.getStepAttributeString(id_step, getRepCode("ENCODING"));

            int nrfields = rep.countNrStepAttributes(id_step, getRepCode("FIELD_NAME"));

            allocate(nrfields);

            for (int i = 0; i < nrfields; i++) {
                inputFields[i] = new TextFileInputField();

                inputFields[i].setName(rep.getStepAttributeString(id_step, i, getRepCode("FIELD_NAME")));
                inputFields[i].setType(
                        ValueMeta.getType(rep.getStepAttributeString(id_step, i, getRepCode("FIELD_TYPE"))));
                inputFields[i].setFormat(rep.getStepAttributeString(id_step, i, getRepCode("FIELD_FORMAT")));
                inputFields[i]
                        .setCurrencySymbol(rep.getStepAttributeString(id_step, i, getRepCode("FIELD_CURRENCY")));
                inputFields[i]
                        .setDecimalSymbol(rep.getStepAttributeString(id_step, i, getRepCode("FIELD_DECIMAL")));
                inputFields[i].setGroupSymbol(rep.getStepAttributeString(id_step, i, getRepCode("FIELD_GROUP")));
                inputFields[i].setLength((int) rep.getStepAttributeInteger(id_step, i, getRepCode("FIELD_LENGTH")));
                inputFields[i]
                        .setPrecision((int) rep.getStepAttributeInteger(id_step, i, getRepCode("FIELD_PRECISION")));
                inputFields[i].setTrimType(ValueMeta
                        .getTrimTypeByCode(rep.getStepAttributeString(id_step, i, getRepCode("FIELD_TRIM_TYPE"))));
            }
        } catch (Exception e) {
            throw new KettleException("Unexpected error reading step information from the repository", e);
        }
    }

    public void saveRep(Repository rep, IMetaStore metaStore, ObjectId id_transformation, ObjectId id_step)
            throws KettleException {
        try {
            rep.saveStepAttribute(id_transformation, id_step, getRepCode("FILENAME"), filename);
            rep.saveStepAttribute(id_transformation, id_step, getRepCode("FILENAME_FIELD"), filenameField);
            rep.saveStepAttribute(id_transformation, id_step, getRepCode("ROW_NUM_FIELD"), rowNumField);
            rep.saveStepAttribute(id_transformation, id_step, getRepCode("INCLUDE_FILENAME"), includingFilename);
            rep.saveStepAttribute(id_transformation, id_step, getRepCode("DELIMITER"), delimiter);
            rep.saveStepAttribute(id_transformation, id_step, getRepCode("ENCLOSURE"), enclosure);
            rep.saveStepAttribute(id_transformation, id_step, getRepCode("BUFFERSIZE"), bufferSize);
            rep.saveStepAttribute(id_transformation, id_step, getRepCode("HEADER_PRESENT"), headerPresent);
            rep.saveStepAttribute(id_transformation, id_step, getRepCode("LAZY_CONVERSION"), lazyConversionActive);
            rep.saveStepAttribute(id_transformation, id_step, getRepCode("ADD_FILENAME_RESULT"), isaddresult);
            rep.saveStepAttribute(id_transformation, id_step, getRepCode("PARALLEL"), runningInParallel);
            rep.saveStepAttribute(id_transformation, id_step, getRepCode("NEWLINE_POSSIBLE"),
                    newlinePossibleInFields);
            rep.saveStepAttribute(id_transformation, id_step, getRepCode("ENCODING"), encoding);

            for (int i = 0; i < inputFields.length; i++) {
                TextFileInputField field = inputFields[i];

                rep.saveStepAttribute(id_transformation, id_step, i, getRepCode("FIELD_NAME"), field.getName());
                rep.saveStepAttribute(id_transformation, id_step, i, getRepCode("FIELD_TYPE"),
                        ValueMeta.getTypeDesc(field.getType()));
                rep.saveStepAttribute(id_transformation, id_step, i, getRepCode("FIELD_FORMAT"), field.getFormat());
                rep.saveStepAttribute(id_transformation, id_step, i, getRepCode("FIELD_CURRENCY"),
                        field.getCurrencySymbol());
                rep.saveStepAttribute(id_transformation, id_step, i, getRepCode("FIELD_DECIMAL"),
                        field.getDecimalSymbol());
                rep.saveStepAttribute(id_transformation, id_step, i, getRepCode("FIELD_GROUP"),
                        field.getGroupSymbol());
                rep.saveStepAttribute(id_transformation, id_step, i, getRepCode("FIELD_LENGTH"), field.getLength());
                rep.saveStepAttribute(id_transformation, id_step, i, getRepCode("FIELD_PRECISION"),
                        field.getPrecision());
                rep.saveStepAttribute(id_transformation, id_step, i, getRepCode("FIELD_TRIM_TYPE"),
                        ValueMeta.getTrimTypeCode(field.getTrimType()));
            }
        } catch (Exception e) {
            throw new KettleException("Unable to save step information to the repository for id_step=" + id_step,
                    e);
        }
    }

    public void getFields(RowMetaInterface rowMeta, String origin, RowMetaInterface[] info, StepMeta nextStep,
            VariableSpace space, Repository repository, IMetaStore metaStore) throws KettleStepException {
        try {
            rowMeta.clear(); // Start with a clean slate, eats the input

            for (int i = 0; i < inputFields.length; i++) {
                TextFileInputField field = inputFields[i];

                ValueMetaInterface valueMeta = ValueMetaFactory.createValueMeta(field.getName(), field.getType());
                valueMeta.setConversionMask(field.getFormat());
                valueMeta.setLength(field.getLength());
                valueMeta.setPrecision(field.getPrecision());
                valueMeta.setConversionMask(field.getFormat());
                valueMeta.setDecimalSymbol(field.getDecimalSymbol());
                valueMeta.setGroupingSymbol(field.getGroupSymbol());
                valueMeta.setCurrencySymbol(field.getCurrencySymbol());
                valueMeta.setTrimType(field.getTrimType());
                if (lazyConversionActive) {
                    valueMeta.setStorageType(ValueMetaInterface.STORAGE_TYPE_BINARY_STRING);
                }
                valueMeta.setStringEncoding(space.environmentSubstitute(encoding));

                // In case we want to convert Strings...
                // Using a copy of the valueMeta object means that the inner and outer representation format is the same.
                // Preview will show the data the same way as we read it.
                // This layout is then taken further down the road by the metadata through the transformation.
                //
                ValueMetaInterface storageMetadata = ValueMetaFactory.cloneValueMeta(valueMeta,
                        ValueMetaInterface.TYPE_STRING);
                storageMetadata.setStorageType(ValueMetaInterface.STORAGE_TYPE_NORMAL);
                storageMetadata.setLength(-1, -1); // we don't really know the lengths of the strings read in advance.
                valueMeta.setStorageMetadata(storageMetadata);

                valueMeta.setOrigin(origin);

                rowMeta.addValueMeta(valueMeta);
            }

            if (!Const.isEmpty(filenameField) && includingFilename) {
                ValueMetaInterface filenameMeta = new ValueMeta(filenameField, ValueMetaInterface.TYPE_STRING);
                filenameMeta.setOrigin(origin);
                if (lazyConversionActive) {
                    filenameMeta.setStorageType(ValueMetaInterface.STORAGE_TYPE_BINARY_STRING);
                    filenameMeta.setStorageMetadata(new ValueMeta(filenameField, ValueMetaInterface.TYPE_STRING));
                }
                rowMeta.addValueMeta(filenameMeta);
            }

            if (!Const.isEmpty(rowNumField)) {
                ValueMetaInterface rowNumMeta = new ValueMeta(rowNumField, ValueMetaInterface.TYPE_INTEGER);
                rowNumMeta.setLength(10);
                rowNumMeta.setOrigin(origin);
                rowMeta.addValueMeta(rowNumMeta);
            }
        } catch (Exception e) {
            throw new KettleStepException(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(CheckResultInterface.TYPE_RESULT_OK,
                    BaseMessages.getString(PKG, "CsvInputMeta.CheckResult.NotReceivingFields"), stepMeta);
            remarks.add(cr);
        } else {
            cr = new CheckResult(CheckResultInterface.TYPE_RESULT_ERROR,
                    BaseMessages.getString(PKG, "CsvInputMeta.CheckResult.StepRecevingData", prev.size() + ""),
                    stepMeta);
            remarks.add(cr);
        }

        // See if we have input streams leading to this step!
        if (input.length > 0) {
            cr = new CheckResult(CheckResultInterface.TYPE_RESULT_ERROR,
                    BaseMessages.getString(PKG, "CsvInputMeta.CheckResult.StepRecevingData2"), stepMeta);
            remarks.add(cr);
        } else {
            cr = new CheckResult(CheckResultInterface.TYPE_RESULT_OK,
                    BaseMessages.getString(PKG, "CsvInputMeta.CheckResult.NoInputReceivedFromOtherSteps"),
                    stepMeta);
            remarks.add(cr);
        }
    }

    public StepInterface getStep(StepMeta stepMeta, StepDataInterface stepDataInterface, int cnr, TransMeta tr,
            Trans trans) {
        return new CsvInput(stepMeta, stepDataInterface, cnr, tr, trans);
    }

    public StepDataInterface getStepData() {
        return new CsvInputData();
    }

    /**
     * @return the delimiter
     */
    public String getDelimiter() {
        return delimiter;
    }

    /**
     * @param delimiter
     *          the delimiter to set
     */
    public void setDelimiter(String delimiter) {
        this.delimiter = delimiter;
    }

    /**
     * @return the filename
     */
    public String getFilename() {
        return filename;
    }

    /**
     * @param filename
     *          the filename to set
     */
    public void setFilename(String filename) {
        this.filename = filename;
    }

    /**
     * @return the bufferSize
     */
    public String getBufferSize() {
        return bufferSize;
    }

    /**
     * @param bufferSize
     *          the bufferSize to set
     */
    public void setBufferSize(String bufferSize) {
        this.bufferSize = bufferSize;
    }

    /**
     * @return true if lazy conversion is turned on: conversions are delayed as long as possible, perhaps to never occur
     *         at all.
     */
    public boolean isLazyConversionActive() {
        return lazyConversionActive;
    }

    /**
     * @param lazyConversionActive
     *          true if lazy conversion is to be turned on: conversions are delayed as long as possible, perhaps to never
     *          occur at all.
     */
    public void setLazyConversionActive(boolean lazyConversionActive) {
        this.lazyConversionActive = lazyConversionActive;
    }

    /**
     * @return the headerPresent
     */
    public boolean isHeaderPresent() {
        return headerPresent;
    }

    /**
     * @param headerPresent
     *          the headerPresent to set
     */
    public void setHeaderPresent(boolean headerPresent) {
        this.headerPresent = headerPresent;
    }

    /**
     * @return the enclosure
     */
    public String getEnclosure() {
        return enclosure;
    }

    /**
     * @param enclosure
     *          the enclosure to set
     */
    public void setEnclosure(String enclosure) {
        this.enclosure = enclosure;
    }

    @Override
    public List<ResourceReference> getResourceDependencies(TransMeta transMeta, StepMeta stepInfo) {
        List<ResourceReference> references = new ArrayList<ResourceReference>(5);

        ResourceReference reference = new ResourceReference(stepInfo);
        references.add(reference);
        if (!Const.isEmpty(filename)) {
            // Add the filename to the references, including a reference to this
            // step meta data.
            //
            reference.getEntries()
                    .add(new ResourceEntry(transMeta.environmentSubstitute(filename), ResourceType.FILE));
        }
        return references;
    }

    /**
     * @return the inputFields
     */
    public TextFileInputField[] getInputFields() {
        return inputFields;
    }

    /**
     * @param inputFields
     *          the inputFields to set
     */
    public void setInputFields(TextFileInputField[] inputFields) {
        this.inputFields = inputFields;
    }

    public int getFileFormatTypeNr() {
        return TextFileInputMeta.FILE_FORMAT_MIXED; // TODO: check this
    }

    public String[] getFilePaths(VariableSpace space) {
        return new String[] { space.environmentSubstitute(filename), };
    }

    public int getNrHeaderLines() {
        return 1;
    }

    public boolean hasHeader() {
        return isHeaderPresent();
    }

    public String getErrorCountField() {
        return null;
    }

    public String getErrorFieldsField() {
        return null;
    }

    public String getErrorTextField() {
        return null;
    }

    public String getEscapeCharacter() {
        return null;
    }

    public String getFileType() {
        return "CSV";
    }

    public String getSeparator() {
        return delimiter;
    }

    public boolean includeFilename() {
        return false;
    }

    public boolean includeRowNumber() {
        return false;
    }

    public boolean isErrorIgnored() {
        return false;
    }

    public boolean isErrorLineSkipped() {
        return false;
    }

    /**
     * @return the filenameField
     */
    public String getFilenameField() {
        return filenameField;
    }

    /**
     * @param filenameField
     *          the filenameField to set
     */
    public void setFilenameField(String filenameField) {
        this.filenameField = filenameField;
    }

    /**
     * @return the includingFilename
     */
    public boolean isIncludingFilename() {
        return includingFilename;
    }

    /**
     * @param includingFilename
     *          the includingFilename to set
     */
    public void setIncludingFilename(boolean includingFilename) {
        this.includingFilename = includingFilename;
    }

    /**
     * @return the rowNumField
     */
    public String getRowNumField() {
        return rowNumField;
    }

    /**
     * @param rowNumField
     *          the rowNumField to set
     */
    public void setRowNumField(String rowNumField) {
        this.rowNumField = rowNumField;
    }

    /**
     * @param isaddresult
     *          The isaddresult to set.
     */
    public void setAddResultFile(boolean isaddresult) {
        this.isaddresult = isaddresult;
    }

    /**
     * @return Returns isaddresult.
     */
    public boolean isAddResultFile() {
        return isaddresult;
    }

    /**
     * @return the runningInParallel
     */
    public boolean isRunningInParallel() {
        return runningInParallel;
    }

    /**
     * @param runningInParallel
     *          the runningInParallel to set
     */
    public void setRunningInParallel(boolean runningInParallel) {
        this.runningInParallel = runningInParallel;
    }

    /**
     * @return the encoding
     */
    public String getEncoding() {
        return encoding;
    }

    /**
     * @param encoding
     *          the encoding to set
     */
    public void setEncoding(String encoding) {
        this.encoding = encoding;
    }

    /**
     * @param space
     *          the variable space to use
     * @param definitions
     * @param resourceNamingInterface
     * @param repository
     *          The repository to optionally load other resources from (to be converted to XML)
     * @param metaStore
     *          the metaStore in which non-kettle metadata could reside.
     *
     * @return the filename of the exported resource
     */
    public String exportResources(VariableSpace space, Map<String, ResourceDefinition> definitions,
            ResourceNamingInterface resourceNamingInterface, Repository repository, IMetaStore metaStore)
            throws KettleException {
        try {
            // The object that we're modifying here is a copy of the original!
            // So let's change the filename from relative to absolute by grabbing the file object...
            // In case the name of the file comes from previous steps, forget about this!
            //
            if (Const.isEmpty(filenameField)) {
                // From : ${Internal.Transformation.Filename.Directory}/../foo/bar.csv
                // To : /home/matt/test/files/foo/bar.csv
                //
                FileObject fileObject = KettleVFS.getFileObject(space.environmentSubstitute(filename), space);

                // If the file doesn't exist, forget about this effort too!
                //
                if (fileObject.exists()) {
                    // Convert to an absolute path...
                    //
                    filename = resourceNamingInterface.nameResource(fileObject, space, true);

                    return filename;
                }
            }
            return null;
        } catch (Exception e) {
            throw new KettleException(e);
        }
    }

    public boolean supportsErrorHandling() {
        return true;
    }

    public StepMetaInjectionInterface getStepMetaInjectionInterface() {

        return this;
    }

    public void injectStepMetadataEntries(List<StepInjectionMetaEntry> metadata) {
        for (StepInjectionMetaEntry entry : metadata) {
            KettleAttributeInterface attr = findAttribute(entry.getKey());

            // Set top level attributes...
            //
            if (entry.getValueType() != ValueMetaInterface.TYPE_NONE) {
                if (attr.getKey().equals("FILENAME")) {
                    filename = (String) entry.getValue();
                } else if (attr.getKey().equals("FILENAME_FIELD")) {
                    filenameField = (String) entry.getValue();
                } else if (attr.getKey().equals("ROW_NUM_FIELD")) {
                    rowNumField = (String) entry.getValue();
                } else if (attr.getKey().equals("HEADER_PRESENT")) {
                    headerPresent = (Boolean) entry.getValue();
                } else if (attr.getKey().equals("DELIMITER")) {
                    delimiter = (String) entry.getValue();
                } else if (attr.getKey().equals("ENCLOSURE")) {
                    enclosure = (String) entry.getValue();
                } else if (attr.getKey().equals("BUFFERSIZE")) {
                    bufferSize = (String) entry.getValue();
                } else if (attr.getKey().equals("LAZY_CONVERSION")) {
                    lazyConversionActive = (Boolean) entry.getValue();
                } else if (attr.getKey().equals("PARALLEL")) {
                    runningInParallel = (Boolean) entry.getValue();
                } else if (attr.getKey().equals("NEWLINE_POSSIBLE")) {
                    newlinePossibleInFields = (Boolean) entry.getValue();
                } else if (attr.getKey().equals("ADD_FILENAME_RESULT")) {
                    isaddresult = (Boolean) entry.getValue();
                } else if (attr.getKey().equals("ENCODING")) {
                    encoding = (String) entry.getValue();
                } else {
                    throw new RuntimeException("Unhandled metadata injection of attribute: " + attr.toString()
                            + " - " + attr.getDescription());
                }
            } else {
                if (attr.getKey().equals("FIELDS")) {
                    // This entry contains a list of lists...
                    // Each list contains a single CSV input field definition (one line in the dialog)
                    //
                    List<StepInjectionMetaEntry> inputFieldEntries = entry.getDetails();
                    inputFields = new TextFileInputField[inputFieldEntries.size()];
                    for (int row = 0; row < inputFieldEntries.size(); row++) {
                        StepInjectionMetaEntry inputFieldEntry = inputFieldEntries.get(row);
                        TextFileInputField inputField = new TextFileInputField();

                        List<StepInjectionMetaEntry> fieldAttributes = inputFieldEntry.getDetails();
                        for (int i = 0; i < fieldAttributes.size(); i++) {
                            StepInjectionMetaEntry fieldAttribute = fieldAttributes.get(i);
                            KettleAttributeInterface fieldAttr = findAttribute(fieldAttribute.getKey());

                            String attributeValue = (String) fieldAttribute.getValue();
                            if (fieldAttr.getKey().equals("FIELD_NAME")) {
                                inputField.setName(attributeValue);
                            } else if (fieldAttr.getKey().equals("FIELD_TYPE")) {
                                inputField.setType(ValueMeta.getType(attributeValue));
                            } else if (fieldAttr.getKey().equals("FIELD_FORMAT")) {
                                inputField.setFormat(attributeValue);
                            } else if (fieldAttr.getKey().equals("FIELD_LENGTH")) {
                                inputField
                                        .setLength(attributeValue == null ? -1 : Integer.parseInt(attributeValue));
                            } else if (fieldAttr.getKey().equals("FIELD_PRECISION")) {
                                inputField.setPrecision(
                                        attributeValue == null ? -1 : Integer.parseInt(attributeValue));
                            } else if (fieldAttr.getKey().equals("FIELD_CURRENCY")) {
                                inputField.setCurrencySymbol(attributeValue);
                            } else if (fieldAttr.getKey().equals("FIELD_DECIMAL")) {
                                inputField.setDecimalSymbol(attributeValue);
                            } else if (fieldAttr.getKey().equals("FIELD_GROUP")) {
                                inputField.setGroupSymbol(attributeValue);
                            } else if (fieldAttr.getKey().equals("FIELD_TRIM_TYPE")) {
                                inputField.setTrimType(ValueMeta.getTrimTypeByCode(attributeValue));
                            } else {
                                throw new RuntimeException("Unhandled metadata injection of attribute: "
                                        + fieldAttr.toString() + " - " + fieldAttr.getDescription());
                            }
                        }

                        inputFields[row] = inputField;
                    }
                }
            }
        }
    }

    public List<StepInjectionMetaEntry> extractStepMetadataEntries() throws KettleException {
        return null;
    }

    /**
     * Describe the metadata attributes that can be injected into this step metadata object.
     *
     * @throws KettleException
     */
    public List<StepInjectionMetaEntry> getStepInjectionMetadataEntries() throws KettleException {
        return getStepInjectionMetadataEntries(PKG);
    }

    /**
     * @return the newlinePossibleInFields
     */
    public boolean isNewlinePossibleInFields() {
        return newlinePossibleInFields;
    }

    /**
     * @param newlinePossibleInFields
     *          the newlinePossibleInFields to set
     */
    public void setNewlinePossibleInFields(boolean newlinePossibleInFields) {
        this.newlinePossibleInFields = newlinePossibleInFields;
    }

}