alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

What this is

This file is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Other links

The source code

// $Header: /home/cvs/jakarta-jmeter/src/jorphan/org/apache/jorphan/collections/Data.java,v 1.9 2004/03/24 15:23:37 mstover1 Exp $
/*
 * Copyright 2001-2004 The Apache Software Foundation.
 *
 * 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.apache.jorphan.collections;
import java.io.Serializable;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.jorphan.logging.LoggingManager;
import org.apache.jorphan.util.JOrphanUtils;
import org.apache.log.Logger;

/**
 * Use this class to store database-like data.  This class uses rows and
 * columns to organize its data.  It has some convenience methods that allow
 * fast loading and retrieval of the data into and out of string arrays.  It
 * is also handy for reading CSV files.
 * 
 * @author Michael Stover (mstover1 at apache.org)
 * @version $Revision: 1.9 $
 */
public class Data implements Serializable
{
    private static Logger log = LoggingManager.getLoggerForClass();
    Map data;
    //Map iterators = new HashMap();
    // Hashtable dataLine;
    ArrayList header;
    // saves current position in data Vector
    int currentPos, size;

    /**
     * Constructor - takes no arguments.
     */
    public Data()
    {
        header = new ArrayList();
        data = new HashMap();
        currentPos = -1;
        size = currentPos + 1;
    }

    /**
     * Replaces the given header name with a new header name.
     * @param oldHeader Old header name.
     * @param newHeader New header name.
     */
    public void replaceHeader(String oldHeader, String newHeader)
    {
        List tempList;
        int index = header.indexOf(oldHeader);
        header.set(index, newHeader);
        tempList = (List) data.remove(oldHeader);
        data.put(newHeader, tempList);
    }

    /**
     * Adds the rows of the given Data object to this Data object.
     * @param d data object to be appended to this one
     */
    public void append(Data d)
    {
        boolean valid = true;
        String[] headers = getHeaders();
        String[] dHeaders = d.getHeaders();
        if (headers.length != dHeaders.length)
        {
            valid = false;
        }
        else
        {
            for (int count = 0; count < dHeaders.length; count++)
            {
                if (!header.contains(dHeaders[count]))
                {
                    valid = false;
                }
            }
        }

        if (valid)
        {
            currentPos = size;
            d.reset();
            while (d.next())
            {
                for (int count = 0; count < headers.length; count++)
                {
                    addColumnValue(
                        headers[count],
                        d.getColumnValue(headers[count]));
                }
            }
        }
    }

    /**
     * Get the number of the current row.
     * @return  integer representing the current row
     */
    public int getCurrentPos()
    {
        return currentPos;
    }

    /**
     * Removes the current row.
     */
    public void removeRow()
    {
        List tempList;
        Iterator it = data.keySet().iterator();
        log.debug("removing row, size = " + size);
        if (currentPos > -1 && currentPos < size)
        {
            log.debug("got to here");
            while (it.hasNext())
            {
                tempList = (List) data.get(it.next());
                tempList.remove(currentPos);
            }
            if (currentPos > 0)
            {
                currentPos--;
            }
            size--;
        }
    }

    public void removeRow(int index)
    {
        log.debug("Removing row: " + index);
        if (index < size)
        {
            setCurrentPos(index);
            log.debug("Setting currentpos to " + index);
            removeRow();
        }
    }

    public void addRow()
    {
        String[] headers = getHeaders();
        List tempList = new ArrayList();
        for (int i = 0; i < headers.length; i++)
        {
            if ((tempList = (ArrayList) data.get(header.get(i))) == null)
            {
                tempList = new ArrayList();
                data.put(headers[i], tempList);
            }
            tempList.add("");
        }
        size = tempList.size();
        setCurrentPos(size - 1);
    }

    /**
     * Sets the current pos. If value sent to method is not a valid number,
     * the current position is set to one higher than the maximum.
     * @param  r position to set to.
     */
    public void setCurrentPos(int r)
    {
        currentPos = r;
    }

    /**
     * Sorts the data using a given row as the sorting criteria.  A boolean
     * value indicates whether to sort ascending or descending.
     * 
     * @param column name of column to use as sorting criteria.
     * @param asc    boolean value indicating whether to sort ascending or
     *               descending.  True for asc, false for desc.  Currently this
     *               feature is not enabled and all sorts are asc.
     */
    public void sort(String column, boolean asc)
    {
        sortData(column, 0, size);
    }

    private void swapRows(int row1, int row2)
    {
        List temp;
        Object o;
        Iterator it = data.keySet().iterator();
        while (it.hasNext())
        {
            temp = (List) data.get(it.next());
            o = temp.get(row1);
            temp.set(row1, temp.get(row2));
            temp.set(row2, o);
        }
    }

    /**
     * Private method that implements the quicksort algorithm to sort the rows
     * of the Data object.
     * 
     * @param column  name of column to use as sorting criteria.
     * @param start   starting index (for quicksort algorithm).
     * @param end     ending index (for quicksort algorithm).
     */
    private void sortData(String column, int start, int end)
    {
        int x = start, y = end - 1;
        String basis =
            ((List) data.get(column)).get((int) ((x + y) / 2)).toString();
        if (x == y)
        {
            return;
        }

        while (x <= y)
        {
            while (x < end
                && ((List) data.get(column)).get(x).toString().compareTo(basis)
                    < 0)
            {
                x++;
            }

            while (y >= (start - 1)
                && ((List) data.get(column)).get(y).toString().compareTo(basis)
                    > 0)
            {
                y--;
            }

            if (x <= y)
            {
                swapRows(x, y);
                x++;
                y--;
            }
        }

        if (x == y)
        {
            x++;
        }

        y = end - x;

        if (x > 0)
        {
            sortData(column, start, x);
        }

        if (y > 0)
        {
            sortData(column, x, end);
        }
    }

    /**
     * Gets the number of rows in the Data object.
     * @return  number of rows in Data object.
     */
    public int size()
    {
        return size;
    } // end method

    /**
     * Adds a value into the Data set at the current row, using a column name
     * to find the column in which to insert the new value.
     * @param column the name of the column to set.
     * @param value  value to set into column.
     */
    public void addColumnValue(String column, Object value)
    {
        ArrayList tempList;
        if ((tempList = (ArrayList) data.get(column)) == null)
        {
            tempList = new ArrayList();
            data.put(column, tempList);
        }
        int s = tempList.size();
        if (currentPos == -1)
        {
            currentPos = size;
        }

        if (currentPos >= size)
        {
            size = currentPos + 1;
        }

        while (currentPos > s)
        {
            s++;
            tempList.add(null);
        }

        if (currentPos == s)
        {
            tempList.add(value);
        }
        else
        {
            tempList.set(currentPos, value);
        }
    }

    /**
     * Returns the row number where a certain value is.
     * 
     * @param column column to be searched for value.
     * @param value  object in Search of.
     * @return row # where value exists.
     */
    public int findValue(String column, Object value)
    {
        List list = (List) data.get(column);
        int ret = -1;
        ret = list.indexOf(value);
        return ret;
    }

    /**
     * Sets the value in the Data set at the current row, using a column name
     * to find the column in which to insert the new value.
     * 
     * @param column the name of the column to set.
     * @param value  value to set into column.
     */
    public void setColumnValue(String column, Object value)
    {
        List tempList;
        if ((tempList = (List) data.get(column)) == null)
        {
            tempList = new ArrayList();
            data.put(column, tempList);
        }

        if (currentPos == -1)
        {
            currentPos = 0;
        }

        if (currentPos >= size)
        {
            size++;
            tempList.add(value);
        }
        else if (currentPos >= tempList.size())
        {
            tempList.add(value);
        }
        else
        {
            tempList.set(currentPos, value);
        }
    }

    /**
     * Checks to see if a column exists in the Data object.
     * @param  column Name of column header to check for.
     * @return True or False depending on whether the column exists.
     */
    public boolean hasHeader(String column)
    {
        return data.containsKey(column);
    }

    /**
     * Sets the current position of the Data set to the next row.
     * @return  True if there is another row.  False if there are no more rows.
     */
    public boolean next()
    {
        return (++currentPos < size);
    }
    
    /**
     * Gets a Data object from a ResultSet.
     *
     * @param  rs ResultSet passed in from a database query
     * @return    a Data object
     * @throws    java.sql.SQLException
     */
    public static Data getDataFromResultSet(ResultSet rs) throws SQLException
    {
        ResultSetMetaData meta = rs.getMetaData();
        Data data = new Data();

        int numColumns = meta.getColumnCount();
        String[] dbCols = new String[numColumns];
        for (int i = 0; i < numColumns; i++)
        {
            dbCols[i] = meta.getColumnName(i + 1);
            data.addHeader(dbCols[i]);
        }
        
        while (rs.next())
        {
            data.next();
            for (int i = 0; i < numColumns; i++)
            {
                Object o = rs.getObject(i + 1);
                if (o instanceof byte[])
                {
                    o = new String((byte[]) o);
                }
                data.addColumnValue(dbCols[i], o);
            }
        }
        return data;
    }

    /**
     * Sets the current position of the Data set to the previous row.
     * @return  True if there is another row.  False if there are no more rows.
     */
    public boolean previous()
    {
        return (--currentPos >= 0);
    }

    /**
     * Resets the current position of the data set to just before the first
     * element.
     */
    public void reset()
    {
        currentPos = -1;
    }

    /**
     * Gets the value in the current row of the given column.
     * @param column name of the column.
     * @return       an Object which holds the value of the column.
     */
    public Object getColumnValue(String column)
    {
        try
        {
            if (currentPos < size)
            {
                return ((List) data.get(column)).get(currentPos);
            }
            else
            {
                return null;
            }
        }
        catch (Exception e)
        {
            return null;
        }
    }

    /**
     * Gets the value in the current row of the given column.
     * @param column index of the column (starts at 0).
     * @return       an Object which holds the value of the column.
     */
    public Object getColumnValue(int column)
    {
        String columnName = (String) header.get(column);
        try
        {
            if (currentPos < size)
            {
                return ((List) data.get(columnName)).get(currentPos);
            }
            else
            {
                return null;
            }
        }
        catch (Exception e)
        {
            return null;
        }
    }

    public Object getColumnValue(int column, int row)
    {
        setCurrentPos(row);
        return getColumnValue(column);
    }

    public void removeColumn(int col)
    {
        String columnName = (String) header.get(col);
        data.remove(columnName);
        header.remove(columnName);
    }

    /**
     * Sets the headers for the data set.  Each header represents a column
     * of data.  Each row's data can be gotten with the column header name,
     * which will always be a string.
     * 
     * @param h array of strings representing the column headers.
     */
    public void setHeaders(String[] h)
    {
        int x = 0;
        header = new ArrayList(h.length);
        for (x = 0; x < h.length; x++)
        {
            header.add(h[x]);
            data.put(h[x], new ArrayList());
        }
    }

    /**
     * Returns a String array of the column headers.
     * @return array of strings of the column headers.
     */
    public String[] getHeaders()
    {
        String[] r = new String[header.size()];
        if (r.length > 0)
        {
            r = (String[]) header.toArray(r);
        }
        return r;
    }

    /**
     * This method will retrieve every entry in a certain column.  It returns
     * an array of Objects from the column.
     * 
     * @param columnName name of the column.
     * @return           array of Objects representing the data.
     */
    public List getColumnAsObjectArray(String columnName)
    {
        return (List) data.get(columnName);
    }

    /**
     * This method will retrieve every entry in a certain column.  It returns
     * an array of strings from the column. Even if the data are not strings,
     * they will be returned as strings in this method.
     * 
     * @param columnName name of the column.
     * @return           array of Strings representing the data.
     */
    public String[] getColumn(String columnName)
    {
        String[] returnValue;
        Object o;
        List temp = (List) data.get(columnName);
        if (temp != null)
        {
            returnValue = new String[temp.size()];
            Iterator it = temp.iterator();
            int index = 0;
            while (it.hasNext())
            {
                o = it.next();
                if (o != null)
                {
                    if (o instanceof String)
                    {
                        returnValue[index++] = (String) o;
                    }
                    else
                    {
                        returnValue[index++] = o.toString();
                    }
                }
            }
        }
        else
        {
            returnValue = new String[0];
        }
        return returnValue;
    }

    /**
     * Use this method to set the entire data set.  It takes an array of
     * strings.  It uses the first row as the headers, and the next rows
     * as the data elements.  Delimiter represents the delimiting character(s)
     * that separate each item in a data row.
     * 
     * @param contents  array of strings, the first element is a list of the
     *                  column headers, the next elements each represent a
     *                  single row of data.
     * @param delimiter the delimiter character that separates columns within
     *                  the string array.
     */
    public void setData(String[] contents, String delimiter)
    {
        setHeaders(JOrphanUtils.split(contents[0], delimiter));
        int x = 1;
        while (x < contents.length)
        {
            setLine(JOrphanUtils.split(contents[x++], delimiter));
        }
    }

    /*
        Deletes a header from the Data object.
        Takes the column name as input.  It will delete the entire
        column.
    
    public void deleteHeader(String s)
    {
    
    }*/

    /**
     * Sets the data for every row in the column.
     */
    public void setColumnData(String colName, Object value)
    {
        List list = this.getColumnAsObjectArray(colName);
        while (list.size() < size())
        {
            list.add(value);
        }
    }

    public void setColumnData(int col, List data)
    {
        reset();
        Iterator iter = data.iterator();
        String columnName = (String) header.get(col);
        while (iter.hasNext())
        {
            next();
            setColumnValue(columnName, iter.next());
        }
    }

    /**
     * Adds a header name to the Data object.
     * @param s name of header.
     */
    public void addHeader(String s)
    {
        header.add(s);
        data.put(s, new ArrayList(size()));
    }

    /**
     * Sets a row of data using an array of strings as input.  Each value in
     * the array represents a column's value in that row.  Assumes the order
     * will be the same order in which the headers were added to the data set.
     * 
     * @param line array of strings representing column values.
     */
    public void setLine(String[] line)
    {
        List tempList;
        String[] h = getHeaders();
        for (int count = 0; count < h.length; count++)
        {
            tempList = (List) data.get(h[count]);
            if (count < line.length && line[count].length() > 0)
            {
                tempList.add(line[count]);
            }
            else
            {
                tempList.add("N/A");
            }
        }
        size++;
    }

    /**
     * Sets a row of data using an array of strings as input.  Each value in
     * the array represents a column's value in that row.  Assumes the order
     * will be the same order in which the headers were added to the data set.
     * 
     * @param line  array of strings representing column values.
     * @param deflt default value to be placed in data if line is not as long
     * as headers.
     */
    public void setLine(String[] line, String deflt)
    {
        List tempList;
        String[] h = getHeaders();
        for (int count = 0; count < h.length; count++)
        {
            tempList = (List) data.get(h[count]);
            if (count < line.length && line[count].length() > 0)
            {
                tempList.add(line[count]);
            }
            else
            {
                tempList.add(deflt);
            }
        }
        size++;
    }

    /**
     * Returns all the data in the Data set as an array of strings.  Each
     * array gives a row of data, each column separated by tabs.
     * 
     * @return array of strings.
     */
    public String[] getDataAsText()
    {
        StringBuffer temp = new StringBuffer("");
        String[] line = new String[size + 1];
        String[] elements = getHeaders();
        for (int count = 0; count < elements.length; count++)
        {
            temp.append(elements[count]);
            if (count + 1 < elements.length)
            {
                temp.append("\t");
            }
        }
        line[0] = temp.toString();
        reset();
        int index = 1;
        while (next())
        {
            temp = new StringBuffer("");
            for (int count = 0; count < elements.length; count++)
            {
                temp.append(getColumnValue(count));
                if (count + 1 < elements.length)
                {
                    temp.append("\t");
                }
            }
            line[index++] = temp.toString();
        }
        return line;
    }

    public String toString()
    {
        String[] contents = getDataAsText();
        StringBuffer sb = new StringBuffer();
        boolean first = true;
        for (int x = 0; x < contents.length; x++)
        {
            if (!first)
            {
                sb.append("\n");
            }
            else
            {
                first = false;
            }
            sb.append(contents[x]);
        }
        return sb.toString();
    }
}
... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.