org.pentaho.di.trans.steps.xmloutput.XMLOutput.java Source code

Java tutorial

Introduction

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

import java.io.File;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.apache.commons.vfs.FileObject;
import org.pentaho.di.core.Const;
import org.pentaho.di.core.ResultFile;
import org.pentaho.di.core.exception.KettleException;
import org.pentaho.di.core.exception.KettleStepException;
import org.pentaho.di.core.row.RowMetaInterface;
import org.pentaho.di.core.row.ValueMetaInterface;
import org.pentaho.di.core.vfs.KettleVFS;
import org.pentaho.di.core.xml.XMLHandler;
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.di.trans.steps.xmloutput.XMLField.ContentType;

/**
 * Converts input rows to one or more XML files.
 *
 * @author Matt
 * @since 14-jan-2006
 */
public class XMLOutput extends BaseStep implements StepInterface {
    private XMLOutputMeta meta;

    private XMLOutputData data;

    public XMLOutput(StepMeta stepMeta, StepDataInterface stepDataInterface, int copyNr, TransMeta transMeta,
            Trans trans) {
        super(stepMeta, stepDataInterface, copyNr, transMeta, trans);
    }

    public boolean processRow(StepMetaInterface smi, StepDataInterface sdi) throws KettleException {
        meta = (XMLOutputMeta) smi;
        data = (XMLOutputData) sdi;

        Object[] r;
        boolean result = true;

        r = getRow(); // This also waits for a row to be finished.

        if (first && meta.isDoNotOpenNewFileInit()) {
            // no more input to be expected...
            // In this case, no file was opened.
            if (r == null) {
                setOutputDone();
                return false;
            }

            if (openNewFile()) {
                data.OpenedNewFile = true;
            } else {
                logError("Couldn't open file " + meta.getFileName());
                setErrors(1L);
                return false;
            }
        }

        if ((r != null && getLinesOutput() > 0 && meta.getSplitEvery() > 0
                && (getLinesOutput() % meta.getSplitEvery()) == 0)) {
            // Done with this part or with everything.
            closeFile();

            // Not finished: open another file...
            if (r != null) {
                if (!openNewFile()) {
                    logError("Unable to open new file (split #" + data.splitnr + "...");
                    setErrors(1);
                    return false;
                }
            }
        }

        if (r == null) { // no more input to be expected...

            setOutputDone();
            return false;
        }

        writeRowToFile(getInputRowMeta(), r);

        data.outputRowMeta = getInputRowMeta().clone();
        meta.getFields(data.outputRowMeta, getStepname(), null, null, this, repository, metaStore);
        putRow(data.outputRowMeta, r); // in case we want it to go further...

        if (checkFeedback(getLinesOutput())) {
            logBasic("linenr " + getLinesOutput());
        }

        return result;
    }

    private void writeRowToFile(RowMetaInterface rowMeta, Object[] r) throws KettleException {
        try {
            if (first) {
                data.formatRowMeta = rowMeta.clone();

                first = false;

                data.fieldnrs = new int[meta.getOutputFields().length];
                for (int i = 0; i < meta.getOutputFields().length; i++) {
                    data.fieldnrs[i] = data.formatRowMeta.indexOfValue(meta.getOutputFields()[i].getFieldName());
                    if (data.fieldnrs[i] < 0) {
                        throw new KettleException("Field [" + meta.getOutputFields()[i].getFieldName()
                                + "] couldn't be found in the input stream!");
                    }

                    // Apply the formatting settings to the valueMeta object...
                    //
                    ValueMetaInterface valueMeta = data.formatRowMeta.getValueMeta(data.fieldnrs[i]);
                    XMLField field = meta.getOutputFields()[i];
                    valueMeta.setConversionMask(field.getFormat());
                    valueMeta.setLength(field.getLength(), field.getPrecision());
                    valueMeta.setDecimalSymbol(field.getDecimalSymbol());
                    valueMeta.setGroupingSymbol(field.getGroupingSymbol());
                    valueMeta.setCurrencySymbol(field.getCurrencySymbol());
                }
            }

            if (meta.getOutputFields() == null || meta.getOutputFields().length == 0) {
                /*
                 * Write all values in stream to text file.
                 */

                // OK, write a new row to the XML file:
                data.writer.write((" <" + meta.getRepeatElement() + ">").toCharArray());

                for (int i = 0; i < data.formatRowMeta.size(); i++) {
                    // Put a space between the XML elements of the row
                    //
                    if (i > 0) {
                        data.writer.write(' ');
                    }

                    ValueMetaInterface valueMeta = data.formatRowMeta.getValueMeta(i);
                    Object valueData = r[i];

                    writeField(valueMeta, valueData, valueMeta.getName());
                }
            } else {
                /*
                 * Only write the fields specified!
                 */
                // Write a new row to the XML file:
                data.writer.write((" <" + meta.getRepeatElement()).toCharArray());

                // First do the attributes...
                //
                for (int i = 0; i < meta.getOutputFields().length; i++) {
                    XMLField xmlField = meta.getOutputFields()[i];
                    if (xmlField.getContentType() == ContentType.Attribute) {
                        ValueMetaInterface valueMeta = data.formatRowMeta.getValueMeta(data.fieldnrs[i]);
                        Object valueData = r[data.fieldnrs[i]];

                        String elementName = xmlField.getElementName();
                        if (Const.isEmpty(elementName)) {
                            elementName = xmlField.getFieldName();
                        }
                        data.writer.write(
                                (" " + elementName + "=\"" + valueMeta.getString(valueData) + "\"").toCharArray());
                    }
                }

                data.writer.write(">".toCharArray());

                // Now write the elements
                //
                for (int i = 0; i < meta.getOutputFields().length; i++) {
                    XMLField outputField = meta.getOutputFields()[i];
                    if (outputField.getContentType() == ContentType.Element) {
                        if (i > 0) {
                            data.writer.write(' '); // a space between
                            // elements
                        }

                        ValueMetaInterface valueMeta = data.formatRowMeta.getValueMeta(data.fieldnrs[i]);
                        Object valueData = r[data.fieldnrs[i]];

                        String elementName = outputField.getElementName();
                        if (Const.isEmpty(elementName)) {
                            elementName = outputField.getFieldName();
                        }

                        if (!(valueMeta.isNull(valueData) && meta.isOmitNullValues())) {
                            writeField(valueMeta, valueData, elementName);
                        }
                    }
                }
            }

            data.writer.write((" </" + meta.getRepeatElement() + ">").toCharArray());
            data.writer.write(Const.CR.toCharArray());
        } catch (Exception e) {
            throw new KettleException(
                    "Error writing XML row :" + e.toString() + Const.CR + "Row: " + getInputRowMeta().getString(r),
                    e);
        }

        incrementLinesOutput();
    }

    private void writeField(ValueMetaInterface valueMeta, Object valueData, String element)
            throws KettleStepException {
        try {
            String str = XMLHandler.addTagValue(element, valueMeta.getString(valueData), false);
            if (str != null) {
                data.writer.write(str.toCharArray());
            }
        } catch (Exception e) {
            throw new KettleStepException("Error writing line :", e);
        }
    }

    public String buildFilename(boolean ziparchive) {
        return meta.buildFilename(this, getCopy(), data.splitnr, ziparchive);
    }

    public boolean openNewFile() {
        boolean retval = false;
        data.writer = null;

        try {
            if (meta.isServletOutput()) {
                data.writer = getTrans().getServletPrintWriter();
                if (meta.getEncoding() != null && meta.getEncoding().length() > 0) {
                    data.writer.write(XMLHandler.getXMLHeader(meta.getEncoding()).toCharArray());
                } else {
                    data.writer.write(XMLHandler.getXMLHeader(Const.XML_ENCODING).toCharArray());
                }
            } else {

                FileObject file = KettleVFS.getFileObject(buildFilename(true), getTransMeta());

                if (meta.isAddToResultFiles()) {
                    // Add this to the result file names...
                    ResultFile resultFile = new ResultFile(ResultFile.FILE_TYPE_GENERAL, file,
                            getTransMeta().getName(), getStepname());
                    resultFile.setComment("This file was created with a xml output step");
                    addResultFile(resultFile);
                }

                OutputStream outputStream;
                if (meta.isZipped()) {
                    OutputStream fos = KettleVFS.getOutputStream(file, false);
                    data.zip = new ZipOutputStream(fos);
                    File entry = new File(buildFilename(false));
                    ZipEntry zipentry = new ZipEntry(entry.getName());
                    zipentry.setComment("Compressed by Kettle");
                    data.zip.putNextEntry(zipentry);
                    outputStream = data.zip;
                } else {
                    OutputStream fos = KettleVFS.getOutputStream(file, false);
                    outputStream = fos;
                }
                if (meta.getEncoding() != null && meta.getEncoding().length() > 0) {
                    logBasic("Opening output stream in encoding: " + meta.getEncoding());
                    data.writer = new OutputStreamWriter(outputStream, meta.getEncoding());
                    data.writer.write(XMLHandler.getXMLHeader(meta.getEncoding()).toCharArray());
                } else {
                    logBasic("Opening output stream in default encoding : " + Const.XML_ENCODING);
                    data.writer = new OutputStreamWriter(outputStream);
                    data.writer.write(XMLHandler.getXMLHeader(Const.XML_ENCODING).toCharArray());
                }
            }

            // Add the name space if defined
            StringBuffer nameSpace = new StringBuffer();
            if ((meta.getNameSpace() != null) && (!"".equals(meta.getNameSpace()))) {
                nameSpace.append(" xmlns=\"");
                nameSpace.append(meta.getNameSpace());
                nameSpace.append("\"");
            }

            // OK, write the header & the parent element:
            data.writer.write(("<" + meta.getMainElement() + nameSpace.toString() + ">" + Const.CR).toCharArray());

            retval = true;
        } catch (Exception e) {
            logError("Error opening new file : " + e.toString());
        }
        // System.out.println("end of newFile(), splitnr="+splitnr);

        data.splitnr++;

        return retval;
    }

    private boolean closeFile() {
        boolean retval = false;
        if (data.OpenedNewFile) {
            try {
                // Close the parent element
                data.writer.write(("</" + meta.getMainElement() + ">" + Const.CR).toCharArray());

                // System.out.println("Closed xml file...");

                data.writer.close();

                if (meta.isZipped()) {
                    // System.out.println("close zip entry ");
                    data.zip.closeEntry();
                    // System.out.println("finish file...");
                    data.zip.finish();
                    data.zip.close();
                }

                retval = true;
            } catch (Exception e) {
                // Ignore errors
            }
        }
        return retval;
    }

    public boolean init(StepMetaInterface smi, StepDataInterface sdi) {
        meta = (XMLOutputMeta) smi;
        data = (XMLOutputData) sdi;

        if (super.init(smi, sdi)) {
            data.splitnr = 0;
            if (!meta.isDoNotOpenNewFileInit()) {
                if (openNewFile()) {
                    data.OpenedNewFile = true;
                    return true;
                } else {
                    logError("Couldn't open file " + meta.getFileName());
                    setErrors(1L);
                    stopAll();
                }
            } else {
                return true;
            }
        }
        return false;
    }

    public void dispose(StepMetaInterface smi, StepDataInterface sdi) {
        meta = (XMLOutputMeta) smi;
        data = (XMLOutputData) sdi;

        closeFile();

        super.dispose(smi, sdi);
    }

}