org.pentaho.di.trans.steps.propertyoutput.PropertyOutputMeta.java Source code

Java tutorial

Introduction

Here is the source code for org.pentaho.di.trans.steps.propertyoutput.PropertyOutputMeta.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.propertyoutput;

import java.text.SimpleDateFormat;
import java.util.Date;
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.database.DatabaseMeta;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.exception.KettleXMLException;
import org.pentaho.di.core.row.RowMetaInterface;
import org.pentaho.di.core.row.ValueMetaInterface;
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.ResourceNamingInterface;
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;

/**
 * Output rows to Properties file and create a file.
 *
 * @author Samatar
 * @since 13-Apr-2008
 */

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

    private String keyfield;
    private String valuefield;

    private boolean addToResult;

    /** The base name of the output file */
    private String fileName;

    /* Specification if file name is in field */

    private boolean fileNameInField;

    private String fileNameField;

    /** The file extention in case of a generated filename */
    private String extension;

    /** Flag: add the stepnr in the filename */
    private boolean stepNrInFilename;

    /** Flag: add the partition number in the filename */
    private boolean partNrInFilename;

    /** Flag: add the date in the filename */
    private boolean dateInFilename;

    /** Flag: add the time in the filename */
    private boolean timeInFilename;

    /** Flag: create parent folder if needed */
    private boolean createparentfolder;

    /** Comment to add in file */
    private String comment;

    /** Flag append in file **/
    private boolean append;

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

    public Object clone() {

        PropertyOutputMeta retval = (PropertyOutputMeta) super.clone();
        return retval;

    }

    /**
     * @return Returns the extension.
     */
    public String getExtension() {
        return extension;
    }

    /**
     * @param extension
     *          The extension to set.
     */
    public void setExtension(String extension) {
        this.extension = extension;
    }

    /**
     * @return Returns the fileName.
     */
    public String getFileName() {
        return fileName;
    }

    /**
     * @return Is the file name coded in a field?
     */
    public boolean isFileNameInField() {
        return fileNameInField;
    }

    /**
     * @param fileNameInField
     *          Is the file name coded in a field?
     */
    public void setFileNameInField(boolean fileNameInField) {
        this.fileNameInField = fileNameInField;
    }

    /**
     * @return The field name that contains the output file name.
     */
    public String getFileNameField() {
        return fileNameField;
    }

    /**
     * @param fileNameField
     *          Name of the field that contains the file name
     */
    public void setFileNameField(String fileNameField) {
        this.fileNameField = fileNameField;
    }

    /**
     * @return Returns the stepNrInFilename.
     */
    public boolean isStepNrInFilename() {
        return stepNrInFilename;
    }

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

    /**
     * @return Returns the timeInFilename.
     */
    public boolean isTimeInFilename() {
        return timeInFilename;
    }

    /**
     * @return Returns the dateInFilename.
     */
    public boolean isDateInFilename() {
        return dateInFilename;
    }

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

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

    /**
     * @param fileName
     *          The fileName to set.
     */
    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    /**
     * @return Returns the Add to result filesname flag.
     */
    public boolean addToResult() {
        return addToResult;
    }

    /**
     * @param addToResult
     *          The Add file to result to set.
     */
    public void setAddToResult(boolean addToResult) {
        this.addToResult = addToResult;
    }

    /**
     * @return Returns the create parent folder flag.
     */
    public boolean isCreateParentFolder() {
        return createparentfolder;
    }

    /**
     * @param createparentfolder
     *          The create parent folder flag to set.
     */
    public void setCreateParentFolder(boolean createparentfolder) {
        this.createparentfolder = createparentfolder;
    }

    /**
     * @return Returns the append flag.
     */
    public boolean isAppend() {
        return append;
    }

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

    public String getComment() {
        return comment;
    }

    public void setComment(String commentin) {
        this.comment = commentin;
    }

    public String[] getFiles(VariableSpace space) {
        int copies = 1;
        int parts = 1;

        if (stepNrInFilename) {
            copies = 3;
        }

        if (partNrInFilename) {
            parts = 3;
        }

        int nr = copies * parts;
        if (nr > 1) {
            nr++;
        }

        String[] retval = new String[nr];

        int i = 0;
        for (int copy = 0; copy < copies; copy++) {
            for (int part = 0; part < parts; part++) {

                retval[i] = buildFilename(space, copy);
                i++;

            }
        }
        if (i < nr) {
            retval[i] = "...";
        }

        return retval;
    }

    public String buildFilename(VariableSpace space, int stepnr) {

        SimpleDateFormat daf = new SimpleDateFormat();

        // Replace possible environment variables...
        String retval = space.environmentSubstitute(fileName);

        Date now = new Date();

        if (dateInFilename) {
            daf.applyPattern("yyyMMdd");
            String d = daf.format(now);
            retval += "_" + d;
        }
        if (timeInFilename) {
            daf.applyPattern("HHmmss");
            String t = daf.format(now);
            retval += "_" + t;
        }
        if (stepNrInFilename) {
            retval += "_" + stepnr;
        }

        if (extension != null && extension.length() != 0) {
            retval += "." + extension;
        }

        return retval;
    }

    private void readData(Node stepnode) throws KettleXMLException {
        try {

            keyfield = XMLHandler.getTagValue(stepnode, "keyfield");
            valuefield = XMLHandler.getTagValue(stepnode, "valuefield");
            comment = XMLHandler.getTagValue(stepnode, "comment");

            fileName = XMLHandler.getTagValue(stepnode, "file", "name");

            createparentfolder = "Y"
                    .equalsIgnoreCase(XMLHandler.getTagValue(stepnode, "file", "create_parent_folder"));
            extension = XMLHandler.getTagValue(stepnode, "file", "extention");
            stepNrInFilename = "Y".equalsIgnoreCase(XMLHandler.getTagValue(stepnode, "file", "split"));
            partNrInFilename = "Y".equalsIgnoreCase(XMLHandler.getTagValue(stepnode, "file", "haspartno"));
            dateInFilename = "Y".equalsIgnoreCase(XMLHandler.getTagValue(stepnode, "file", "add_date"));
            timeInFilename = "Y".equalsIgnoreCase(XMLHandler.getTagValue(stepnode, "file", "add_time"));
            addToResult = "Y".equalsIgnoreCase(XMLHandler.getTagValue(stepnode, "file", "AddToResult"));
            append = "Y".equalsIgnoreCase(XMLHandler.getTagValue(stepnode, "file", "append"));
            fileName = XMLHandler.getTagValue(stepnode, "file", "name");
            fileNameInField = "Y".equalsIgnoreCase(XMLHandler.getTagValue(stepnode, "fileNameInField"));
            fileNameField = XMLHandler.getTagValue(stepnode, "fileNameField");

        } catch (Exception e) {
            throw new KettleXMLException("Unable to load step info from XML", e);
        }
    }

    public void setDefault() {
        append = false;
        createparentfolder = false;
        // Items ...
        keyfield = null;
        valuefield = null;
        comment = null;
    }

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

        // Items ...

        retval.append("    " + XMLHandler.addTagValue("keyfield", keyfield));
        retval.append("    " + XMLHandler.addTagValue("valuefield", valuefield));
        retval.append("    " + XMLHandler.addTagValue("comment", comment));

        retval.append("    " + XMLHandler.addTagValue("fileNameInField", fileNameInField));
        retval.append("    " + XMLHandler.addTagValue("fileNameField", fileNameField));
        retval.append("    <file>" + Const.CR);

        retval.append("      " + XMLHandler.addTagValue("name", fileName));
        retval.append("      " + XMLHandler.addTagValue("extention", extension));
        retval.append("      " + XMLHandler.addTagValue("split", stepNrInFilename));
        retval.append("      " + XMLHandler.addTagValue("haspartno", partNrInFilename));
        retval.append("      " + XMLHandler.addTagValue("add_date", dateInFilename));
        retval.append("      " + XMLHandler.addTagValue("add_time", timeInFilename));

        retval.append("      " + XMLHandler.addTagValue("create_parent_folder", createparentfolder));
        retval.append("    " + XMLHandler.addTagValue("addtoresult", addToResult));
        retval.append("    " + XMLHandler.addTagValue("append", append));
        retval.append("      </file>" + Const.CR);

        return retval.toString();
    }

    public void readRep(Repository rep, IMetaStore metaStore, ObjectId id_step, List<DatabaseMeta> databases)
            throws KettleException {
        try {

            keyfield = rep.getStepAttributeString(id_step, "keyfield");
            valuefield = rep.getStepAttributeString(id_step, "valuefield");
            comment = rep.getStepAttributeString(id_step, "comment");

            fileName = rep.getStepAttributeString(id_step, "file_name");
            extension = rep.getStepAttributeString(id_step, "file_extention");
            stepNrInFilename = rep.getStepAttributeBoolean(id_step, "file_add_stepnr");
            partNrInFilename = rep.getStepAttributeBoolean(id_step, "file_add_partnr");
            dateInFilename = rep.getStepAttributeBoolean(id_step, "file_add_date");
            timeInFilename = rep.getStepAttributeBoolean(id_step, "file_add_time");

            createparentfolder = rep.getStepAttributeBoolean(id_step, "create_parent_folder");
            addToResult = rep.getStepAttributeBoolean(id_step, "addtoresult");
            append = rep.getStepAttributeBoolean(id_step, "append");
            fileNameInField = rep.getStepAttributeBoolean(id_step, "fileNameInField");
            fileNameField = rep.getStepAttributeString(id_step, "fileNameField");

        } 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, "keyfield", keyfield);
            rep.saveStepAttribute(id_transformation, id_step, "valuefield", valuefield);
            rep.saveStepAttribute(id_transformation, id_step, "comment", comment);

            rep.saveStepAttribute(id_transformation, id_step, "file_name", fileName);
            rep.saveStepAttribute(id_transformation, id_step, "file_extention", extension);
            rep.saveStepAttribute(id_transformation, id_step, "file_add_stepnr", stepNrInFilename);
            rep.saveStepAttribute(id_transformation, id_step, "file_add_partnr", partNrInFilename);
            rep.saveStepAttribute(id_transformation, id_step, "file_add_date", dateInFilename);
            rep.saveStepAttribute(id_transformation, id_step, "file_add_time", timeInFilename);

            rep.saveStepAttribute(id_transformation, id_step, "create_parent_folder", createparentfolder);
            rep.saveStepAttribute(id_transformation, id_step, "addtoresult", addToResult);
            rep.saveStepAttribute(id_transformation, id_step, "append", append);
            rep.saveStepAttribute(id_transformation, id_step, "fileNameInField", fileNameInField);
            rep.saveStepAttribute(id_transformation, id_step, "fileNameField", fileNameField);
        } catch (Exception e) {
            throw new KettleException("Unable to save step information to the repository for id_step=" + 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;
        // Now see what we can find as previous step...
        if (prev != null && prev.size() > 0) {
            cr = new CheckResult(CheckResult.TYPE_RESULT_OK,
                    BaseMessages.getString(PKG, "PropertyOutputMeta.CheckResult.FieldsReceived", "" + prev.size()),
                    stepMeta);
            remarks.add(cr);
        } else {
            cr = new CheckResult(CheckResult.TYPE_RESULT_ERROR,
                    BaseMessages.getString(PKG, "PropertyOutputMeta.CheckResult.NoFields"), stepMeta);
            remarks.add(cr);
        }

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

        // Check if filename is given
        if (!Const.isEmpty(fileName)) {
            cr = new CheckResult(CheckResult.TYPE_RESULT_OK,
                    BaseMessages.getString(PKG, "PropertyOutputMeta.CheckResult.FilenameOk"), stepMeta);
            remarks.add(cr);
        } else {
            cr = new CheckResult(CheckResult.TYPE_RESULT_ERROR,
                    BaseMessages.getString(PKG, "PropertyOutputMeta.CheckResult.FilenameError"), stepMeta);
            remarks.add(cr);
        }

        // Check for Key field

        ValueMetaInterface v = prev.searchValueMeta(keyfield);
        if (v == null) {
            cr = new CheckResult(CheckResultInterface.TYPE_RESULT_ERROR,
                    BaseMessages.getString(PKG, "PropertyOutputMeta.CheckResult.KeyFieldMissing"), stepMeta);
            remarks.add(cr);
        } else {
            cr = new CheckResult(CheckResultInterface.TYPE_RESULT_OK,
                    BaseMessages.getString(PKG, "PropertyOutputMeta.CheckResult.KeyFieldOk"), stepMeta);
            remarks.add(cr);
        }

        // Check for Value field

        v = prev.searchValueMeta(valuefield);
        if (v == null) {
            cr = new CheckResult(CheckResultInterface.TYPE_RESULT_ERROR,
                    BaseMessages.getString(PKG, "PropertyOutputMeta.CheckResult.ValueFieldMissing"), stepMeta);
            remarks.add(cr);
        } else {
            cr = new CheckResult(CheckResultInterface.TYPE_RESULT_OK,
                    BaseMessages.getString(PKG, "PropertyOutputMeta.CheckResult.ValueFieldOk"), stepMeta);
            remarks.add(cr);
        }

    }

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

    /**
     * @return the keyfield
     */
    public String getKeyField() {
        return keyfield;
    }

    /**
     * @return the valuefield
     */
    public String getValueField() {
        return valuefield;
    }

    /**
     * @param KeyField
     *          the keyfield to set
     */
    public void setKeyField(String KeyField) {
        this.keyfield = KeyField;
    }

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

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

    public boolean supportsErrorHandling() {
        return true;
    }

    /**
     * Since the exported transformation that runs this will reside in a ZIP file, we can't reference files relatively. So
     * what this does is turn the name of files into absolute paths OR it simply includes the resource in the ZIP file.
     * For now, we'll simply turn it into an absolute path and pray that the file is on a shared drive or something like
     * that.
     *
     * @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...
            //
            // From : ${Internal.Transformation.Filename.Directory}/../foo/bar.data
            // To : /home/matt/test/files/foo/bar.data
            //
            // In case the name of the file comes from previous steps, forget about this!
            if (!fileNameInField) {
                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);
        }
    }

}