/* * The contents of this file are subject to the Mozilla Public License * Version 1.1 (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.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Original Code is the Kowari Metadata Store. * * The Initial Developer of the Original Code is Plugged In Software Pty * Ltd (http://www.pisoftware.com, mailto:info@pisoftware.com). Portions * created by Plugged In Software Pty Ltd are Copyright (C) 2001,2002 * Plugged In Software Pty Ltd. All Rights Reserved. * * Contributor(s): N/A. * * [NOTE: The text of this Exhibit A may differ slightly from the text * of the notices in the Source Code files of the Original Code. You * should use the text of this Exhibit A rather than the text found in the * Original Code Source Code for Your Modifications.] * */ package org.mulgara.util; // Java 2 standard packages import java.io.*; import java.sql.*; // Log4J import org.apache.log4j.*; /** * Rows within the result set. * * @author <a href="http://staff.pisoftware.com/raboczi">Simon Raboczi</a> * @author Andrew Newman * * @created 2001-07-12 * * @version $Revision: 1.9 $ * * @modified $Date: 2005/01/05 04:59:29 $ * * @maintenanceAuthor $Author: newmana $ * * @company <A href="mailto:info@PIsoftware.com">Plugged In Software</A> * * @copyright © 2001-2003 <A href="http://www.PIsoftware.com/">Plugged In * Software Pty Ltd</A> * * @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a> */ public class ResultSetRow implements Comparable<ResultSetRow>, Serializable { /** * Allow newer compiled version of the stub to operate when changes * have not occurred with the class. * NOTE : update this serialVersionUID when a method or a public member is * deleted. */ static final long serialVersionUID = 6269054577611383745L; /** Logger. */ private static final Logger logger = Logger.getLogger(ResultSetRow.class.getName()); /** * The column entries for this row. */ private Object[] columns; /** * The names of the columns. */ private String[] columnNames; /** * Create a result set row based on the metadata from the given ResultSet * object. * * @param resultSet the ResultSet that we are using to get the metadata to * create the column names. */ public ResultSetRow(ResultSet resultSet) { try { // Get the number of columns from the metadata ResultSetMetaData metadata = resultSet.getMetaData(); int noColumns = metadata.getColumnCount(); // Initialize arrays columnNames = new String[noColumns]; columns = new Object[noColumns]; // Set column names for (int index = 1; index <= noColumns; index++) { columnNames[index - 1] = metadata.getColumnName(index); } } catch (SQLException se) { logger.fatal("Failed to get columns or number of columns", se); } } /** * Create a row at the end of the result set, populated with * <code>null</code>. * * @param newColumnNames the new column names for the row. * @param newColumns the results of the row. */ public ResultSetRow(String[] newColumnNames, Object[] newColumns) { columnNames = newColumnNames; columns = newColumns; } /** * Sets new column values. * * @param newColumns entries for this row. */ public void setColumns(Object[] newColumns) { columns = newColumns; } /** * Sets the given column index with the given value. * * @param columnIndex the index into the row. * @param value the value of the column. */ public void setInt(int columnIndex, int value) { setObject(columnIndex, new Integer(value)); } /** * Sets the given column name with the given value. * * @param columnName the name of the column to set. * @param value the value of the column. */ public void setInt(String columnName, int value) { setInt(columnForName(columnName), value); } /** * Set a field to a Java {@link Object} value. In order to allow {@link * MemoryResultSet} to be {@link Serializable}, we require that all object that * appear as field values are also {@link Serializable}. * * @param columnIndex the index into the column to get the object. * @param value a {@link Serializable} object * @throws IllegalArgumentException if <var>value</var> isn't {@link * Serializable} */ public void setObject(int columnIndex, Object value) { // Validate "value" parameter if ( (value != null) && ! (value instanceof Serializable)) { throw new IllegalArgumentException("Non-serializable value: " + value); } try { columns[columnIndex - 1] = value; } catch (ArrayIndexOutOfBoundsException e) { logger.error("columnIndex: " + columnIndex, e); throw e; } } /** * Set a field based on a column name. * * @param columnName the name of the column to set. * @param value a {@link Serializable} object * @throws IllegalArgumentException if <var>value</var> isn't {@link * Serializable} */ public void setObject(String columnName, Object value) { setObject(columnForName(columnName), value); } /** * Returns an int value from the given column index - if possible. * * @param columnIndex the index in the column to return the data. * @return an int value from the given column index - if possible. * @throws SQLException if the column is not an integer. */ public int getInt(int columnIndex) throws SQLException { Object object = getObject(columnIndex); if (! (object instanceof Integer)) { throw new SQLException("Column " + columnIndex + " isn't an integer"); } return ( (Integer) object).intValue(); } /** * Returns an int value from the given column name - if possible. * * @param columnName the name of the column to return the data. * @return an int value from the given column index - if possible. * @throws SQLException if the column is not an integer. */ public int getInt(String columnName) throws SQLException { return getInt(columnForName(columnName)); } /** * Returns the object value based on the given column index. * * @param columnIndex the index into the column to get the object. * @return the object's value. */ public Object getObject(int columnIndex) { try { return columns[columnIndex - 1]; } catch (ArrayIndexOutOfBoundsException e) { logger.error("columnIndex: " + columnIndex); throw e; } } /** * Returns the object value based on the column name. * * @param columnName name of the column. * @return the object's value. */ public Object getObject(String columnName) { return getObject(columnForName(columnName)); } /** * Returns true if the object is of the same type, the same length and its * column values are equal. * * @param object the object to test for equality. * @return true if the object is of the same type, the same length and its * column values are equal. */ public boolean equals(Object object) { // The classes must match if (object == null) { return false; } if (!object.getClass().equals(ResultSetRow.class)) { return false; } // Rows must be the same length ResultSetRow row = (ResultSetRow) object; if (columns.length != row.columns.length) { return false; } // Column entries aren't allowed to mismatch for (int i = 0; i < columns.length; i++) { if ( (row.columns[i] == null) ? (columns[i] != null) : (!row.columns[i].equals(columns[i]))) { return false; } } // The rows must be equal if we got this far return true; } /** * Returns and XOR of all the column of this row. * * @return the XOR of all the columns of this row */ public int hashCode() { int hashCode = 0; for (int i = 0; i < columns.length; i++) { if (columns[i] != null) { hashCode ^= columns[i].hashCode(); } } return hashCode; } /** * Returns a string representation of the row displaying the column name and * the value stored in them. * * @return a string representation of the row displaying the column name and * the value stored in them. */ public String toString() { StringBuffer buffer = new StringBuffer(); for (int i = 0; i < columns.length; i++) { buffer.append("\t").append(columnNames[i]).append("=").append(columns[i]); } return buffer.toString(); } /** * Returns a negative number if the object is less than the given object, a * positive number if larger and 0 if equal. Accepts an object of the correct * type. * * @param row the row object to compare it. * @return a negative number if the object is less than the given object, a * positive number if larger and 0 if equal. */ @SuppressWarnings({ "unchecked", "rawtypes" }) public int compareTo(ResultSetRow row) { // Longer result sets are larger if (row.columns.length != columns.length) { return columns.length - row.columns.length; } for (int i = 0; i < columns.length; i++) { if (columns[i] == null) { // nulls come after other values return (row.columns[i] == null) ? 0 : 1; } else if (!(columns[i] instanceof Comparable)) { throw new RuntimeException( "Badly implemented code can't cope with non-Comparable " + columns[i] + " of type " + columns[i].getClass()); } int result; try { result = ((Comparable)columns[i]).compareTo(row.columns[i]); } catch (ClassCastException e) { logger.warn("Incomparable rows", e); result = columns[i].getClass().toString().compareTo(row.columns[i].getClass() .toString()); } if (result != 0) { return result; } } // The rows must be equal return 0; } /** * Returns the index of the given column name or throws an * IllegalArgumentException if not found. * * @param columnName the name of the column to search for. * @return the index into the array (beginning at 1 not 0) where the column is * located. * @throws java.lang.IllegalArgumentException if the given column name does * not exist. * @throws IllegalArgumentException EXCEPTION TO DO */ private int columnForName(String columnName) throws IllegalArgumentException { for (int i = 0; i < columnNames.length; i++) { if (columnNames[i].equals(columnName)) { return i + 1; } } throw new IllegalArgumentException("No such column " + columnName); } }