/*! ****************************************************************************** * * 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.core.row; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.math.BigDecimal; import java.net.SocketTimeoutException; import java.util.Date; import java.util.List; import org.pentaho.di.core.exception.KettleException; import org.pentaho.di.core.exception.KettleFileException; import org.pentaho.di.core.exception.KettleValueException; import org.w3c.dom.Node; /** * This interface provides methods to describe and manipulate a row's structure. The interface is similar to the * JDBC ResultSet interface in that it provides a means of getting data from a row. * <p> * Inside processRow() a step typically retrieves the structure of incoming rows by calling getInputRowMeta(), which is * provided by the BaseStep class. The step would usually clone this object and pass it to getFields() of its meta * class, to reflect any changes in row structure caused by the step itself. Now the step has RowMetaInterface objects * describing both the input and output rows. * <p> * Usually a step would look for the indexes and types of relevant fields upon first execution of processRow(). The * following methods of RowMetaInterface are particularly useful in that regard: * <p> * <i><a href="">public int indexOfValue(...)</a></i><br/> * Given a field name, determine the index of the field in the row. * <p> * <i><a href="#getFieldNames()">public String[] getFieldNames()</a></i><br/> * Returns an array of field names. The index of a field name matches the field index in the row array. * <p> * <i><a href="#searchValueMeta(java.lang.String)">public void searchValueMeta(String valueName)</a></i><br/> * Given a field name, determine the meta data for the field. * <p> * <i><a href="#getValueMeta(int index)">public vValueMetaInterface getValueMeta(...)</a></i><br/> * Given a field index, determine the meta data for the field.<br/> * <p> * <i><a href="#getValueMetaList()">public List<ValueMetaInterface> getValueMetaList()</a></i><br/> * Returns a list of all field descriptions. The index of the field description matches the field index in the row * array. * <p> */ public interface RowMetaInterface extends Cloneable { /** * Gets the value meta list. * * @return the list of value Metadata */ public List<ValueMetaInterface> getValueMetaList(); /** * Sets the value meta list. * * @param valueMetaList * the list of valueMeta to set */ public void setValueMetaList( List<ValueMetaInterface> valueMetaList ); /** * Check if a value is already present in this row with the same name. * * @param meta * the value to check for existence * @return true if a value with the same name already exists in the row */ public boolean exists( ValueMetaInterface meta ); /** * Add a metadata value, extends the array if needed. If a value with the same name already exists, it gets renamed. * * @param meta * The metadata value to add */ public void addValueMeta( ValueMetaInterface meta ); /** * Add a metadata value on a certain location in the row. If a value with the same name already exists, it gets * renamed. Remember to change the data row according to this. * * @param index * The index where the metadata value needs to be put in the row * @param meta * The metadata value to add to the row */ public void addValueMeta( int index, ValueMetaInterface meta ); /** * Get the value metadata on the specified index. * * @param index * The index to get the value metadata from * @return The value metadata specified by the index. */ public ValueMetaInterface getValueMeta( int index ); /** * Replaces a value meta entry in the row metadata with another one. * * @param index * The index in the row to replace at * @param valueMeta * the metadata to replace with */ public void setValueMeta( int index, ValueMetaInterface valueMeta ); /** * Get a String value from a row of data. Convert data if this needed. * * @param dataRow * the data row * @param index * the index * @return The string found on that position in the row * @throws KettleValueException * in case there was a problem converting the data. */ public String getString( Object[] dataRow, int index ) throws KettleValueException; /** * Get an Integer value from a row of data. Convert data if this needed. * * @param dataRow * the data row * @param index * the index * @return The integer found on that position in the row * @throws KettleValueException * in case there was a problem converting the data. */ public Long getInteger( Object[] dataRow, int index ) throws KettleValueException; /** * Get a Number value from a row of data. Convert data if this needed. * * @param dataRow * the data row * @param index * the index * @return The number found on that position in the row * @throws KettleValueException * in case there was a problem converting the data. */ public Double getNumber( Object[] dataRow, int index ) throws KettleValueException; /** * Get a Date value from a row of data. Convert data if this needed. * * @param dataRow * the data row * @param index * the index * @return The date found on that position in the row * @throws KettleValueException * in case there was a problem converting the data. */ public Date getDate( Object[] dataRow, int index ) throws KettleValueException; /** * Get a BigNumber value from a row of data. Convert data if this needed. * * @param dataRow * the data row * @param index * the index * @return The bignumber found on that position in the row * @throws KettleValueException * in case there was a problem converting the data. */ public BigDecimal getBigNumber( Object[] dataRow, int index ) throws KettleValueException; /** * Get a Boolean value from a row of data. Convert data if this needed. * * @param dataRow * the data row * @param index * the index * @return The boolean found on that position in the row * @throws KettleValueException * in case there was a problem converting the data. */ public Boolean getBoolean( Object[] dataRow, int index ) throws KettleValueException; /** * Get a Binary value from a row of data. Convert data if this needed. * * @param dataRow * the data row * @param index * the index * @return The binary found on that position in the row * @throws KettleValueException * in case there was a problem converting the data. */ public byte[] getBinary( Object[] dataRow, int index ) throws KettleValueException; /** * Clone row. * * @param objects * objects to clone * @param cloneTo * objects to clone to * @return a cloned Object[] object. * @throws KettleValueException * in case something is not quite right with the expected data */ public Object[] cloneRow( Object[] objects, Object[] cloneTo ) throws KettleValueException; /** * Clone row. * * @param objects * object to clone * @return a cloned objects to clone to * @throws KettleValueException * in case something is not quite right with the expected data */ public Object[] cloneRow( Object[] objects ) throws KettleValueException; /** * Returns the size of the metadata row. * * @return the size of the metadata row */ public int size(); /** * Returns true if there are no elements in the row metadata. * * @return true if there are no elements in the row metadata */ public boolean isEmpty(); /** * Determines whether a value in a row is null. A value is null when the object is null. As such, you can just as good * write dataRow[index]==null in your code. * * @param dataRow * The row of data * @param index * the index to reference * @return true if the value on the index is null. * @throws KettleValueException * in case there is a conversion error (only thrown in case of lazy conversion) */ public boolean isNull( Object[] dataRow, int index ) throws KettleValueException; /** * Clone this RowMetaInterface object. * * @return a copy of this RowMetaInterface object */ public RowMetaInterface clone(); /** * This method copies the row metadata and sets all values to the specified type (usually String) * * @param targetType * The target type * @return The cloned metadata * @throws if * the target type could not be loaded from the plugin registry */ public RowMetaInterface cloneToType( int targetType ) throws KettleValueException; /** * Gets the string. * * @param dataRow * the data row * @param valueName * the value name * @param defaultValue * the default value * @return the string * @throws KettleValueException * the kettle value exception */ public String getString( Object[] dataRow, String valueName, String defaultValue ) throws KettleValueException; /** * Gets the integer. * * @param dataRow * the data row * @param valueName * the value name * @param defaultValue * the default value * @return the integer * @throws KettleValueException * the kettle value exception */ public Long getInteger( Object[] dataRow, String valueName, Long defaultValue ) throws KettleValueException; /** * Gets the date. * * @param dataRow * the data row * @param valueName * the value name * @param defaultValue * the default value * @return the date * @throws KettleValueException * the kettle value exception */ public Date getDate( Object[] dataRow, String valueName, Date defaultValue ) throws KettleValueException; /** * Searches for a value with a certain name in the value meta list. * * @param valueName * The value name to search for * @return The value metadata or null if nothing was found */ public ValueMetaInterface searchValueMeta( String valueName ); /** * Searches the index of a value meta with a given name. * * @param valueName * the name of the value metadata to look for * @return the index or -1 in case we didn't find the value */ public int indexOfValue( String valueName ); /** * Add a number of fields from another row (append to the end). * * @param rowMeta * The row of metadata values to add */ public void addRowMeta( RowMetaInterface rowMeta ); /** * Merge the values of row r to this Row. The values that are not yet in the row are added unchanged. The values that * are in the row are renamed to name[2], name[3], etc. * * @param r * The row to be merged with this row */ @Deprecated public void mergeRowMeta( RowMetaInterface r ); /** * Merge the values of row r to this Row. The values that are not yet in the row are added unchanged. The values that * are in the row are renamed to name[2], name[3], etc. * * @param r * The row to be merged with this row */ public void mergeRowMeta( RowMetaInterface r, String originStepName ); /** * Get an array of the names of all the Values in the Row. * * @return an array of Strings: the names of all the Values in the Row. */ public String[] getFieldNames(); /** * Write a serialized version of this class (Row Metadata) to the specified outputStream. * * @param outputStream * the outputstream to write to * @throws KettleFileException * in case a I/O error occurs */ public void writeMeta( DataOutputStream outputStream ) throws KettleFileException; /** * Write a serialized version of the supplied data to the outputStream (based on the metadata but not the metadata * itself). * * @param outputStream * the outputstream to write to * @param data * the data to write after the metadata * @throws KettleFileException * in case a I/O error occurs */ public void writeData( DataOutputStream outputStream, Object[] data ) throws KettleFileException; /** * De-serialize a row of data (no metadata is read) from an input stream. * * @param inputStream * the inputstream to read from * @return a new row of data * @throws KettleFileException * in case a I/O error occurs * @throws SocketTimeoutException * In case there is a timeout during reading. */ public Object[] readData( DataInputStream inputStream ) throws KettleFileException, SocketTimeoutException; /** * Clear the row metadata. */ public void clear(); /** * Remove a value with a certain name from the row metadata. * * @param string * the name of the value metadata to remove * @throws KettleValueException * in case the value couldn't be found in the row metadata */ public void removeValueMeta( String string ) throws KettleValueException; /** * Remove a value metadata object on a certain index in the row. * * @param index * the index to remove the value metadata from */ public void removeValueMeta( int index ); /** * Get the string representation of the data in a row of data. * * @param row * the row of data to convert to string * @return the row of data in string form * @throws KettleValueException * in case of a conversion error */ public String getString( Object[] row ) throws KettleValueException; /** * Get an array of strings showing the name of the values in the row padded to a maximum length, followed by the types * of the values. * * @param maxlen * The length to which the name will be padded. * @return an array of strings: the names and the types of the fieldnames in the row. */ public String[] getFieldNamesAndTypes( int maxlen ); /** * Compare 2 rows with each other using certain values in the rows and also considering the specified ascending * clauses of the value metadata. * * @param rowData1 * The first row of data * @param rowData2 * The second row of data * @param fieldnrs * the fields to compare on (in that order) * @return 0 if the rows are considered equal, -1 is data1 is smaller, 1 if data2 is smaller. * @throws KettleValueException * the kettle value exception */ public int compare( Object[] rowData1, Object[] rowData2, int[] fieldnrs ) throws KettleValueException; /** * Compare 2 rows with each other for equality using certain values in the rows and also considering the case * sensitivity flag. * * @param rowData1 * The first row of data * @param rowData2 * The second row of data * @param fieldnrs * the fields to compare on (in that order) * @return true if the rows are considered equal, false if they are not. * @throws KettleValueException * the kettle value exception */ public boolean equals( Object[] rowData1, Object[] rowData2, int[] fieldnrs ) throws KettleValueException; /** * Compare 2 rows with each other using certain values in the rows and also considering the specified ascending * clauses of the value metadata. * * @param rowData1 * The first row of data * @param rowData2 * The second row of data * @param fieldnrs1 * The indexes of the values to compare in the first row * @param fieldnrs2 * The indexes of the values to compare with in the second row * @return 0 if the rows are considered equal, -1 is data1 is smaller, 1 if data2 is smaller. * @throws KettleValueException * the kettle value exception */ public int compare( Object[] rowData1, Object[] rowData2, int[] fieldnrs1, int[] fieldnrs2 ) throws KettleValueException; /** * Compare 2 rows with each other using certain values in the rows and also considering the specified ascending * clauses of the value metadata. * * @param rowData1 * The first row of data * @param rowMeta2 * the metadat of the second row of data * @param rowData2 * The second row of data * @param fieldnrs1 * The indexes of the values to compare in the first row * @param fieldnrs2 * The indexes of the values to compare with in the second row * @return 0 if the rows are considered equal, -1 is data1 is smaller, 1 if data2 is smaller. * @throws KettleValueException * the kettle value exception */ public int compare( Object[] rowData1, RowMetaInterface rowMeta2, Object[] rowData2, int[] fieldnrs1, int[] fieldnrs2 ) throws KettleValueException; /** * Compare 2 rows with each other using all values in the rows and also considering the specified ascending clauses of * the value metadata. * * @param rowData1 * The first row of data * @param rowData2 * The second row of data * @return 0 if the rows are considered equal, -1 is data1 is smaller, 1 if data2 is smaller. * @throws KettleValueException * the kettle value exception */ public int compare( Object[] rowData1, Object[] rowData2 ) throws KettleValueException; /** * Calculate a hashCode of the content (not the index) of the data specified NOTE: This method uses a simple XOR of * the individual hashCodes which can result in a lot of collisions for similar types of data (e.g. [A,B] == [B,A] and * is not suitable for normal use. It is kept to provide backward compatibility with CombinationLookup.lookupValues() * * @param rowData * The data to calculate a hashCode with * @return the calculated hashCode * @throws KettleValueException * in case there is a data conversion error * @deprecated */ @Deprecated public int oldXORHashCode( Object[] rowData ) throws KettleValueException; /** * Calculates a simple hashCode of all the native data objects in the supplied row. This method will return a better * distribution of values for rows of numbers or rows with the same values in different positions. NOTE: This method * performs against the native values, not the values returned by ValueMeta. This means that if you have two rows with * different primitive values ['2008-01-01:12:30'] and ['2008-01-01:00:00'] that use a format object to change the * value (as Date yyyy-MM-dd), the hashCodes will be different resulting in the two rows not being considered equal * via the hashCode even though compare() or equals() might consider them to be. * * @param rowData * The data to calculate a hashCode with * @return the calculated hashCode * @throws KettleValueException * in case there is a data conversion error */ public int hashCode( Object[] rowData ) throws KettleValueException; /** * Calculates a hashcode of the converted value of all objects in the supplied row. This method returns distinct * values for nulls of different data types and will return the same hashCode for different native values that have a * ValueMeta converting them into the same value (e.g. ['2008-01-01:12:30'] and ['2008-01-01:00:00'] as Date * yyyy-MM-dd) * * @param rowData * The data to calculate a hashCode with * @return the calculated hashCode * @throws KettleValueException * in case there is a data conversion error */ public int convertedValuesHashCode( Object[] rowData ) throws KettleValueException; /** * To string meta. * * @return a string with a description of all the metadata values of the complete row of metadata */ public String toStringMeta(); /** * Gets the meta xml. * * @return an XML representation of the row metadata * @throws IOException * Thrown in case there is an (Base64/GZip) encoding problem */ public String getMetaXML() throws IOException; /** * Gets the data xml. * * @param rowData * the row of data to serialize as XML * @return an XML representation of the row data * @throws IOException * Thrown in case there is an (Base64/GZip) encoding problem */ public String getDataXML( Object[] rowData ) throws IOException; /** * Convert an XML node into binary data using the row metadata supplied. * * @param node * The data row node * @return a row of data de-serialized from XML * @throws KettleException * Thrown in case there is an (Base64/GZip) decoding problem */ public Object[] getRow( Node node ) throws KettleException; }