Java tutorial
/*! ****************************************************************************** * * 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); } } }