Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
   *    This program is free software; you can redistribute it and/or modify
   *    it under the terms of the GNU General Public License as published by
   *    the Free Software Foundation; either version 2 of the License, or
   *    (at your option) any later version.
   *
   *    This program is distributed in the hope that it will be useful,
   *    but WITHOUT ANY WARRANTY; without even the implied warranty of
   *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  *    GNU General Public License for more details.
  *
  *    You should have received a copy of the GNU General Public License
  *    along with this program; if not, write to the Free Software
  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
 /*
  *    WekaScoringData.java
  *    Copyright 2007 Pentaho Corporation.  All rights reserved. 
  *
  */
 
 package org.pentaho.di.arff;
 
 import java.io.File;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 import  org.pentaho.di.core.Const;
 import  org.pentaho.di.core.exception.KettleStepException;
 import  org.pentaho.di.core.exception.KettleValueException;
 import  org.pentaho.di.core.row.RowMetaInterface;
 import  org.pentaho.di.core.row.ValueMetaInterface;
 import  org.pentaho.di.trans.step.BaseStepData;
 import  org.pentaho.di.trans.step.StepDataInterface;
 import  org.pentaho.dm.commons.ArffMeta;
 
Holds temporary data and has routines for writing the ARFF file. This class writes rows to a temporary file while, at the same time, collects values for nominal attributes in an array of Maps. Once the last row has been processed, the ARFF header is written and then the temporary file is appended.

Author(s):
Mark Hall (mhall{[at]}pentaho.org)
Version:
1.0
 
 public class ArffOutputData extends BaseStepData implements StepDataInterface {
 
   // the output data format
   protected RowMetaInterface m_outputRowMeta;
 
   // indexes of fields being output
   protected int[] m_outputFieldIndexes;

  
True if sparse data is to be output
 
   protected boolean m_outputSparseInstances;

  
Index of the field used to set the weight for each instance (-1 means equal weights)
 
   protected int m_weightFieldIndex = -1;
 
   // meta data for the ARFF fields
   protected ArffMeta[] m_arffMeta;
 
   // array of treemaps to hold nominal values
   protected Map<StringString>[] m_nominalVals;
 
   protected File m_tempFile;
   protected File m_headerFile;
   protected OutputStream m_dataOut;
   protected OutputStream m_headerOut;
 
   protected byte[] m_separator = ",".getBytes();
   protected byte[] m_newLine = "\n".getBytes();
   protected byte[] m_missing = "?".getBytes();
   protected byte[] m_leftCurly = "{".getBytes();
   protected byte[] m_spaceLeftCurly = " {".getBytes();
   protected byte[] m_rightCurly = "}".getBytes();
 
   // Is there a specific character encoding being used?
   protected boolean m_hasEncoding;
 
   // byte buffer for fast copy
   static final int BUFF_SIZE = 100000;
  static final byte[] m_buffer = new byte[];
  public ArffOutputData() {
    super();
  }

  
Get the meta data for the output format

Returns:
a RowMetaInterface value
  public RowMetaInterface getOutputRowMeta() {
    return ;
  }

  
Set the meta data for the output format

Parameters:
rmi a RowMetaInterface value
  public void setOutputRowMeta(RowMetaInterface rmi) {
     = rmi;
  }

  
Set whether an encoding is in use.

Parameters:
e true if an encoding is in use
  public void setHasEncoding(boolean e) {
     = e;
  }

  
Returns true if a specific character encoding is in use.

Returns:
true if an encoding other than the default encoding is in use.
  public boolean getHasEncoding() {
    return ;
  }

  
Set the binary line terminator to use

Parameters:
nl the line terminator
  public void setBinaryNewLine(byte[] nl) {
     = nl;
  }

  
Set the binary separator to use

Parameters:
s binary field separator
  public void setBinarySeparator(byte[] s) {
     = s;
  }

  
Set the binary missing value to use

Parameters:
m binary missing value
  public void setBinaryMissing(byte[] m) {
     = m;
  }

  
Set the indexes of the fields to output to the ARFF file

Parameters:
outputFieldIndexes array of indexes
arffMeta array of arff metas
  @SuppressWarnings("unchecked")
  public void setOutputFieldIndexes(int[] outputFieldIndexes,
      ArffMeta[] arffMeta) {
     = outputFieldIndexes;
     = arffMeta;
    // initialize any necessary tree maps
    for (int i = 0; i < .i++) {
      if ([i] >= 0) {
        if ([i].getArffType() == ArffMeta.NOMINAL) {
          [i] = new TreeMap<StringString>();
          if (!Const.isEmpty([i].getNominalVals())) {
            // transfer over the user supplied nominal values
            List<StringvList = ArffMeta.stringToVals([i]
                .getNominalVals());
            // need to maintain the order specified (so that we can check
            // for zero index for sparse format, and because we assume
            // the supplied order is what the user wants)
            [i] = new LinkedHashMap<StringString>();
            for (String v : vList) {
              [i].put(vv);
            }
          }
        }
      }
    }
  }

  
Set the index of the field whose values will be used to set the weight for each instance.

Parameters:
index the index of the field to use to set instance-level weights.
  public void setWeightFieldIndex(int index) {
     = index;
  }

  
Set whether to output instances in sparse format

Parameters:
s true if instances are to be output in sparse format
  public void setOutputSparseInstances(boolean s) {
  }

  
Open files ready to write to

Parameters:
filename the name of the ARFF file to write to
Throws:
IOException if an error occurs
  public void openFiles(String filenamethrows IOException {
    if (filename.startsWith("file:")) {
      try {
        filename.replace(" ""%20");
         = new File(new java.net.URI(filename));
      } catch (Exception ex) {
        throw new IOException("Malformed URI for arff file");
      }
    } else {
       = new File(filename);
    }
    // m_headerFile = filename;
     = new BufferedOutputStream(os);
    // tempfile to write the data to.
    // at the end of the stream we will write the
    // header to the requested file name and then
    // append this temp file to the end of it.
    String tempPrefix = "" + Math.random() + "arffOut";
     = File.createTempFile(tempPrefixnull);
     = new BufferedOutputStream(os2);
  }

  
Convert a String to an array of bytes using an (optional) encoding.

Parameters:
encoding the character encoding to use
string the String to convert
Returns:
the String as an array of bytes
Throws:
KettleValueException if an error occurs
  private byte[] convertStringToBinaryString(String encodingString string)
      throws KettleValueException {
    if (!getHasEncoding()) {
      return string.getBytes();
    }
    try {
      return string.getBytes(encoding);
    } catch (UnsupportedEncodingException e) {
      throw new KettleValueException("Unable to convert String to "
          + "Binary with specified string " + "encoding [" + encoding + "]"e);
    }
  }

  
Convert and write a row of data to the ARFF file.

Parameters:
r the Kettle row
encoding an (optional) character encoding to use
Throws:
IOException if an error occurs
KettleStepException if an error occurs
  public void writeRow(Object[] rString encodingthrows IOException,
      KettleStepException {
    // write data to temp file and update header hash
    // trees (if necessary)
      byte[] lcurly = null;
      if (!Const.isEmpty(encoding)) {
        lcurly = "{".getBytes(encoding);
      } else {
        lcurly = ;
      }
      .write(lcurly);
    }
    int sparseIndex = 0;
    boolean separatorNeeded = false;
    for (int i = 0; i < .i++) {
      if (i != 0 && separatorNeeded) {
        .write();
      }
      if ([i] >= 0) {
        separatorNeeded = writeField(isparseIndex,
            r[[i]], encoding);
        sparseIndex++;
      }
    }
      byte[] rcurly = null;
      if (!Const.isEmpty(encoding)) {
        rcurly = "}".getBytes(encoding);
      } else {
        rcurly = ;
      }
      .write(rcurly);
    }
    // write the weight value (if necessary)
    if ( != -1) {
    }
  }
  private void writeWeight(int indexObject valueString encoding)
      throws KettleStepException {
    try {
      ValueMetaInterface v = .getValueMeta(index);
      // write it as long as it's not null!!
      String temp = v.getString(value);
      if (temp != null && temp.length() > 0) {
        .write();
        .write();
        // writeField(index, value, encoding);
        byte[] str;
        str = v.getBinaryString(value);
        .write(str);
        .write();
      }
    } catch (Exception ex) {
      throw new KettleStepException("Problem writing weight field content "
          + "to file"ex);
    }
  }

  
Write a field to the ARFF file

Parameters:
index the index (from the output field indexes) of the field to write
sparseIndex the real index (for used in sparse output)
value the actual Kettle value
encoding an (optional) character encoding to use
Returns:
true if a field was written
Throws:
KettleStepException if an error occurs
  private boolean writeField(int indexint sparseIndexObject value,
      String encodingthrows KettleStepException {
    try {
      ValueMetaInterface v = 
          .getValueMeta([index]);
      if () {
        if (checkSparseWrite(indexvvalue)) {
          byte[] sparseBytes;
          String idx = "" + sparseIndex + " ";
          if (!Const.isEmpty(encoding)) {
            sparseBytes = idx.getBytes(encoding);
          } else {
            sparseBytes = idx.getBytes();
          }
          .write(sparseBytes);
        } else {
          return false;
        }
      }
      byte[] str;
      str = formatField(indexvvalueencoding);
      .write(str);
    } catch (Exception ex) {
      throw new KettleStepException("Problem writing field content "
          + "to file"ex);
    }
    return true;
  }
  private boolean checkSparseWrite(int index, ValueMetaInterface vObject value)
      throws KettleValueException {
    if ([index].getArffType() == ArffMeta.NOMINAL
        || [index].getArffType() == ArffMeta.STRING) {
      String svalue = (value instanceof String) ? (Stringvalue : v
          .getString(value);
      if ([index] != null) {
        if ([index].size() == 0) {
          // we need at least the zero'th value to be supplied by the ueser
          // so that we know when not to output a value
          throw new KettleValueException(
              "Can't output sparse instance containing nominal "
                  + "attributes without knowing at least what what the zero'th "
                  + "value for each nominal value is apriori!");
        }
        Set<Strings = [index].keySet();
        Iterator<Stringi = s.iterator();
        String zeroS = i.next();
        if (!svalue.equals(zeroS)) {
          return true;
        }
      }
    } else if ([index].getArffType() == ArffMeta.DATE
        || [index].getArffType() == ArffMeta.NUMERIC) {
      double numVal = v.getNumber(value);
      if (numVal != 0) {
        return true;
      }
    }
    return false;
  }

  
Format a Kettle value for writing.

Parameters:
index the index of the value to format
v ValueMetaInterface for the field in question
value the actual value
encoding an (optional) character encoding
Returns:
the formatted value as an array of bytes
Throws:
KettleValueException if an error occurs
  private byte[] formatField(int index, ValueMetaInterface vObject value,
      String encodingthrows KettleValueException {
    // Check for missing value (null or empty string)
    // This seems to only consider empty string ("")
    // to be a null/missing value if the actual type
    // is String; for other types it returns false if
    // the value is "" (Kettle 3.0).
    if (v.isNull(value)) {
      return ;
    }
    if ([index].getArffType() == ArffMeta.NOMINAL
        || [index].getArffType() == ArffMeta.STRING) {
      String svalue = (value instanceof String) ? (Stringvalue : v
          .getString(value);
      if ([index].getArffType() == ArffMeta.NOMINAL) {
        // check to see if we've seen this value before, if not
        // then update the hash tree. Note that we enclose in
        // quotes (if necessary) *after* inserting into the
        // hash table so that the header values are kept in
        // sorted order in the situation when there are
        // a mixture of values that need quoting and those
        // that do not.
        if (![index].containsKey(svalue)) {
          [index].put(svaluesvalue);
        }
      }
      svalue = Utils.quote(svalue);
      return convertStringToBinaryString(encoding,
          Const.trimToType(svaluev.getTrimType()));
    } else if ([index].getArffType() == ArffMeta.DATE) {
      // isNull bug workaround
      String temp = v.getString(value);
      if (temp == null || temp.length() == 0) {
        return ;
      }
      temp = Utils.quote(temp);
      return convertStringToBinaryString(encoding,
          Const.trimToType(tempv.getTrimType()));
    } else if ([index].getKettleType() == ValueMetaInterface.TYPE_BOOLEAN) {
      // isNull bug workaround
      String temp = v.getString(value);
      if (temp == null || temp.length() == 0) {
        return ;
      }
      if (v.getBoolean(value)) {
        temp = "1";
      } else {
        temp = "0";
      }
      return convertStringToBinaryString(encoding,
          Const.trimToType(tempv.getTrimType()));
    } else {
      // isNull bug workaround
      String temp = v.getString(value);
      if (temp == null || temp.length() == 0) {
        return ;
      }
      return v.getBinaryString(value);
    }
  }

  
Writes the ARFF header and appends the temporary file

Parameters:
relationName the ARFF relation name
encoding an (optional) character encoding
Throws:
KettleStepException if an error occurs
  public void finishOutput(String relationNameString encoding)
      throws KettleStepException {
    if ( == null) {
      // can't do anything
      return;
    }
    relationName = Utils.quote(relationName);
    relationName = "@relation " + relationName;
    byte[] rn = null;
    byte[] atAtt = null;
    byte[] atData = null;
    if ( && encoding != null) {
      if (Const.isEmpty(encoding)) {
        rn = relationName.getBytes();
        atAtt = "@attribute ".getBytes();
        atData = "@data".getBytes();
      } else {
        try {
          rn = relationName.getBytes(encoding);
          atAtt = "@attribute ".getBytes(encoding);
          atData = "@data".getBytes(encoding);
        } catch (UnsupportedEncodingException e) {
          throw new KettleStepException("Unable to write header with "
              + "specified string encoding [" + encoding + "]"e);
        }
      }
    } else {
      rn = relationName.getBytes();
      atAtt = "@attribute ".getBytes();
      atData = "@data".getBytes();
    }
    try {
      // write the header
      .write(rn);
      // now write the attributes
      for (int i = 0; i < .i++) {
        if ([i] >= 0) {
          if ([i].getArffType() == ArffMeta.NOMINAL) {
            .write(atAtt);
            writeBinaryNominalAttString(iencoding);
          } else if ([i].getArffType() == ArffMeta.STRING) {
            .write(atAtt);
            writeBinaryStringAttString(iencoding);
          } else if ([i].getArffType() == ArffMeta.NUMERIC) {
            .write(atAtt);
            writeBinaryNumericAttString(iencoding);
          } else {
            .write(atAtt);
            writeBinaryDateAttString(iencoding);
          }
        }
      }
      .write(atData);
      .flush();
      .close();
    } catch (IOException ex) {
      throw new KettleStepException("Problem writing values to " + "file."ex);
    } finally {
      try {
        closeFiles();
      } catch (IOException ex) {
        throw new KettleStepException("Problem closing files..."ex);
      }
    }
    // now append the temporary file to the header file
    InputStream is = null;
    OutputStream os = null;
    try {
      is = new FileInputStream();
      // open the header file for appending
      os = new FileOutputStream(true);
      while (true) {
        synchronized () {
          int amountRead = is.read();
          if (amountRead == -1) {
            break;
          }
          os.write(, 0, amountRead);
        }
      }
    } catch (IOException ex) {
      throw new KettleStepException("Problem copying temp file"ex);
    } finally {
      try {
        if (is != null) {
          is.close();
          // Try and clean up by deleting the temp file
          .delete();
        }
        if (os != null) {
          os.close();
        }
      } catch (IOException ex) {
        throw new KettleStepException("Problem closing files..."ex);
      }
    }
  }

  
Writes an attribute declaration for a numeric attribute

Parameters:
index the index of the attribute/field
encoding an (optional) character encoding
Throws:
IOException if an error occurs
KettleStepException if an error occurs
  private void writeBinaryNumericAttString(int indexString encoding)
      throws IOException, KettleStepException {
    byte[] attName = null;
    byte[] attType = null;
    if ( && encoding != null) {
      if (Const.isEmpty(encoding)) {
        attName = Utils.quote([index].getFieldName()).getBytes();
        attType = " numeric".getBytes();
      } else {
        try {
          attName = Utils.quote([index].getFieldName()).getBytes(
              encoding);
          attType = " numeric".getBytes(encoding);
        } catch (UnsupportedEncodingException e) {
          throw new KettleStepException("Unable to write header with "
              + "specified string encoding [" + encoding + "]"e);
        }
      }
    } else {
      attName = Utils.quote([index].getFieldName()).getBytes();
      attType = " numeric".getBytes();
    }
    .write(attName);
    .write(attType);
  }
  private void writeBinaryStringAttString(int indexString encoding)
      throws IOException, KettleStepException {
    byte[] attName = null;
    byte[] attType = null;
    if ( && encoding != null) {
      if (Const.isEmpty(encoding)) {
        attName = Utils.quote([index].getFieldName()).getBytes();
        attType = " string".getBytes();
      } else {
        try {
          attName = Utils.quote([index].getFieldName()).getBytes(
              encoding);
          attType = " string".getBytes(encoding);
        } catch (UnsupportedEncodingException e) {
          throw new KettleStepException("Unable to write header with "
              + "specified string encoding [" + encoding + "]"e);
        }
      }
    } else {
      attName = Utils.quote([index].getFieldName()).getBytes();
      attType = " string".getBytes();
    }
    .write(attName);
    .write(attType);
  }

  
Writes an attribute declaration for a date attribute

Parameters:
index the index of the attribute/field
encoding an (optional) character encoding
Throws:
IOException if an error occurs
KettleStepException if an error occurs
  private void writeBinaryDateAttString(int indexString encoding)
      throws IOException, KettleStepException {
    byte[] attName = null;
    byte[] attType = null;
    byte[] dateFormat = null;
    ValueMetaInterface v = 
        .getValueMeta([index]);
    String dateF = v.getDateFormat().toPattern();
    dateF = Utils.quote(dateF);
    if ( && encoding != null) {
      if (Const.isEmpty(encoding)) {
        attName = Utils.quote([index].getFieldName()).getBytes();
        attType = " date ".getBytes();
        dateFormat = dateF.getBytes();
      } else {
        try {
          attName = Utils.quote([index].getFieldName()).getBytes(
              encoding);
          attType = " date ".getBytes(encoding);
          dateFormat = dateF.getBytes(encoding);
        } catch (UnsupportedEncodingException e) {
          throw new KettleStepException("Unable to write header with "
              + "specified string encoding [" + encoding + "]"e);
        }
      }
    } else {
      attName = Utils.quote([index].getFieldName()).getBytes();
      attType = " date ".getBytes();
      dateFormat = dateF.getBytes();
    }
    .write(attName);
    .write(attType);
    .write(dateFormat);
  }

  
Writes an attribute declaration for a nominal attribute

Parameters:
index the index of the attribute/field
encoding an (optional) character encoding
Throws:
IOException if an error occurs
KettleStepException if an error occurs
  private void writeBinaryNominalAttString(int indexString encoding)
      throws IOException, KettleStepException {
    byte[] attName = null;
    byte[] lcurly = null;
    byte[] rcurly = null;
    if ( && encoding != null) {
      if (Const.isEmpty(encoding)) {
        attName = Utils.quote([index].getFieldName()).getBytes();
        lcurly = ;
        rcurly = ;
      } else {
        try {
          attName = Utils.quote([index].getFieldName()).getBytes(
              encoding);
          lcurly = " {".getBytes(encoding);
          rcurly = "}".getBytes(encoding);
        } catch (UnsupportedEncodingException e) {
          throw new KettleStepException("Unable to write header with "
              + "specified string encoding [" + encoding + "]"e);
        }
      }
    } else {
      attName = Utils.quote([index].getFieldName()).getBytes();
      lcurly = ;
      rcurly = ;
    }
    .write(attName);
    .write(lcurly);
    // get keys from corresponding hash tree
    Set<StringkeySet = [index].keySet();
    Iterator<Stringksi = keySet.iterator();
    byte[] nomVal = null;
    while (ksi.hasNext()) {
      String next = ksi.next();
      next = Utils.quote(next);
      if ( && encoding != null) {
        if (Const.isEmpty(encoding)) {
          nomVal = next.getBytes();
        } else {
          nomVal = next.getBytes(encoding);
        }
      } else {
        nomVal = next.getBytes();
      }
      .write(nomVal);
      if (ksi.hasNext()) {
        .write();
      }
    }
    .write(rcurly);
  }

  
Flush and close all files

Throws:
IOException if an error occurs
  public void closeFiles() throws IOException {
    if ( != null) {
      .flush();
      .close();
       = null;
    }
    if ( != null) {
      .flush();
      .close();
       = null;
    }
  }
New to GrepCode? Check out our FAQ X