KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > jorphan > collections > Data


1 // $Header: /home/cvs/jakarta-jmeter/src/jorphan/org/apache/jorphan/collections/Data.java,v 1.9 2004/03/24 15:23:37 mstover1 Exp $
2
/*
3  * Copyright 2001-2004 The Apache Software Foundation.
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17 */

18
19 package org.apache.jorphan.collections;
20 import java.io.Serializable JavaDoc;
21 import java.sql.ResultSet JavaDoc;
22 import java.sql.ResultSetMetaData JavaDoc;
23 import java.sql.SQLException JavaDoc;
24 import java.util.ArrayList JavaDoc;
25 import java.util.HashMap JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.List JavaDoc;
28 import java.util.Map JavaDoc;
29
30 import org.apache.jorphan.logging.LoggingManager;
31 import org.apache.jorphan.util.JOrphanUtils;
32 import org.apache.log.Logger;
33
34 /**
35  * Use this class to store database-like data. This class uses rows and
36  * columns to organize its data. It has some convenience methods that allow
37  * fast loading and retrieval of the data into and out of string arrays. It
38  * is also handy for reading CSV files.
39  *
40  * @author Michael Stover (mstover1 at apache.org)
41  * @version $Revision: 1.9 $
42  */

43 public class Data implements Serializable JavaDoc
44 {
45     private static Logger log = LoggingManager.getLoggerForClass();
46     Map JavaDoc data;
47     //Map iterators = new HashMap();
48
// Hashtable dataLine;
49
ArrayList JavaDoc header;
50     // saves current position in data Vector
51
int currentPos, size;
52
53     /**
54      * Constructor - takes no arguments.
55      */

56     public Data()
57     {
58         header = new ArrayList JavaDoc();
59         data = new HashMap JavaDoc();
60         currentPos = -1;
61         size = currentPos + 1;
62     }
63
64     /**
65      * Replaces the given header name with a new header name.
66      * @param oldHeader Old header name.
67      * @param newHeader New header name.
68      */

69     public void replaceHeader(String JavaDoc oldHeader, String JavaDoc newHeader)
70     {
71         List JavaDoc tempList;
72         int index = header.indexOf(oldHeader);
73         header.set(index, newHeader);
74         tempList = (List JavaDoc) data.remove(oldHeader);
75         data.put(newHeader, tempList);
76     }
77
78     /**
79      * Adds the rows of the given Data object to this Data object.
80      * @param d data object to be appended to this one
81      */

82     public void append(Data d)
83     {
84         boolean valid = true;
85         String JavaDoc[] headers = getHeaders();
86         String JavaDoc[] dHeaders = d.getHeaders();
87         if (headers.length != dHeaders.length)
88         {
89             valid = false;
90         }
91         else
92         {
93             for (int count = 0; count < dHeaders.length; count++)
94             {
95                 if (!header.contains(dHeaders[count]))
96                 {
97                     valid = false;
98                 }
99             }
100         }
101
102         if (valid)
103         {
104             currentPos = size;
105             d.reset();
106             while (d.next())
107             {
108                 for (int count = 0; count < headers.length; count++)
109                 {
110                     addColumnValue(
111                         headers[count],
112                         d.getColumnValue(headers[count]));
113                 }
114             }
115         }
116     }
117
118     /**
119      * Get the number of the current row.
120      * @return integer representing the current row
121      */

122     public int getCurrentPos()
123     {
124         return currentPos;
125     }
126
127     /**
128      * Removes the current row.
129      */

130     public void removeRow()
131     {
132         List JavaDoc tempList;
133         Iterator JavaDoc it = data.keySet().iterator();
134         log.debug("removing row, size = " + size);
135         if (currentPos > -1 && currentPos < size)
136         {
137             log.debug("got to here");
138             while (it.hasNext())
139             {
140                 tempList = (List JavaDoc) data.get(it.next());
141                 tempList.remove(currentPos);
142             }
143             if (currentPos > 0)
144             {
145                 currentPos--;
146             }
147             size--;
148         }
149     }
150
151     public void removeRow(int index)
152     {
153         log.debug("Removing row: " + index);
154         if (index < size)
155         {
156             setCurrentPos(index);
157             log.debug("Setting currentpos to " + index);
158             removeRow();
159         }
160     }
161
162     public void addRow()
163     {
164         String JavaDoc[] headers = getHeaders();
165         List JavaDoc tempList = new ArrayList JavaDoc();
166         for (int i = 0; i < headers.length; i++)
167         {
168             if ((tempList = (ArrayList JavaDoc) data.get(header.get(i))) == null)
169             {
170                 tempList = new ArrayList JavaDoc();
171                 data.put(headers[i], tempList);
172             }
173             tempList.add("");
174         }
175         size = tempList.size();
176         setCurrentPos(size - 1);
177     }
178
179     /**
180      * Sets the current pos. If value sent to method is not a valid number,
181      * the current position is set to one higher than the maximum.
182      * @param r position to set to.
183      */

184     public void setCurrentPos(int r)
185     {
186         currentPos = r;
187     }
188
189     /**
190      * Sorts the data using a given row as the sorting criteria. A boolean
191      * value indicates whether to sort ascending or descending.
192      *
193      * @param column name of column to use as sorting criteria.
194      * @param asc boolean value indicating whether to sort ascending or
195      * descending. True for asc, false for desc. Currently this
196      * feature is not enabled and all sorts are asc.
197      */

198     public void sort(String JavaDoc column, boolean asc)
199     {
200         sortData(column, 0, size);
201     }
202
203     private void swapRows(int row1, int row2)
204     {
205         List JavaDoc temp;
206         Object JavaDoc o;
207         Iterator JavaDoc it = data.keySet().iterator();
208         while (it.hasNext())
209         {
210             temp = (List JavaDoc) data.get(it.next());
211             o = temp.get(row1);
212             temp.set(row1, temp.get(row2));
213             temp.set(row2, o);
214         }
215     }
216
217     /**
218      * Private method that implements the quicksort algorithm to sort the rows
219      * of the Data object.
220      *
221      * @param column name of column to use as sorting criteria.
222      * @param start starting index (for quicksort algorithm).
223      * @param end ending index (for quicksort algorithm).
224      */

225     private void sortData(String JavaDoc column, int start, int end)
226     {
227         int x = start, y = end - 1;
228         String JavaDoc basis =
229             ((List JavaDoc) data.get(column)).get((int) ((x + y) / 2)).toString();
230         if (x == y)
231         {
232             return;
233         }
234
235         while (x <= y)
236         {
237             while (x < end
238                 && ((List JavaDoc) data.get(column)).get(x).toString().compareTo(basis)
239                     < 0)
240             {
241                 x++;
242             }
243
244             while (y >= (start - 1)
245                 && ((List JavaDoc) data.get(column)).get(y).toString().compareTo(basis)
246                     > 0)
247             {
248                 y--;
249             }
250
251             if (x <= y)
252             {
253                 swapRows(x, y);
254                 x++;
255                 y--;
256             }
257         }
258
259         if (x == y)
260         {
261             x++;
262         }
263
264         y = end - x;
265
266         if (x > 0)
267         {
268             sortData(column, start, x);
269         }
270
271         if (y > 0)
272         {
273             sortData(column, x, end);
274         }
275     }
276
277     /**
278      * Gets the number of rows in the Data object.
279      * @return number of rows in Data object.
280      */

281     public int size()
282     {
283         return size;
284     } // end method
285

286     /**
287      * Adds a value into the Data set at the current row, using a column name
288      * to find the column in which to insert the new value.
289      * @param column the name of the column to set.
290      * @param value value to set into column.
291      */

292     public void addColumnValue(String JavaDoc column, Object JavaDoc value)
293     {
294         ArrayList JavaDoc tempList;
295         if ((tempList = (ArrayList JavaDoc) data.get(column)) == null)
296         {
297             tempList = new ArrayList JavaDoc();
298             data.put(column, tempList);
299         }
300         int s = tempList.size();
301         if (currentPos == -1)
302         {
303             currentPos = size;
304         }
305
306         if (currentPos >= size)
307         {
308             size = currentPos + 1;
309         }
310
311         while (currentPos > s)
312         {
313             s++;
314             tempList.add(null);
315         }
316
317         if (currentPos == s)
318         {
319             tempList.add(value);
320         }
321         else
322         {
323             tempList.set(currentPos, value);
324         }
325     }
326
327     /**
328      * Returns the row number where a certain value is.
329      *
330      * @param column column to be searched for value.
331      * @param value object in Search of.
332      * @return row # where value exists.
333      */

334     public int findValue(String JavaDoc column, Object JavaDoc value)
335     {
336         List JavaDoc list = (List JavaDoc) data.get(column);
337         int ret = -1;
338         ret = list.indexOf(value);
339         return ret;
340     }
341
342     /**
343      * Sets the value in the Data set at the current row, using a column name
344      * to find the column in which to insert the new value.
345      *
346      * @param column the name of the column to set.
347      * @param value value to set into column.
348      */

349     public void setColumnValue(String JavaDoc column, Object JavaDoc value)
350     {
351         List JavaDoc tempList;
352         if ((tempList = (List JavaDoc) data.get(column)) == null)
353         {
354             tempList = new ArrayList JavaDoc();
355             data.put(column, tempList);
356         }
357
358         if (currentPos == -1)
359         {
360             currentPos = 0;
361         }
362
363         if (currentPos >= size)
364         {
365             size++;
366             tempList.add(value);
367         }
368         else if (currentPos >= tempList.size())
369         {
370             tempList.add(value);
371         }
372         else
373         {
374             tempList.set(currentPos, value);
375         }
376     }
377
378     /**
379      * Checks to see if a column exists in the Data object.
380      * @param column Name of column header to check for.
381      * @return True or False depending on whether the column exists.
382      */

383     public boolean hasHeader(String JavaDoc column)
384     {
385         return data.containsKey(column);
386     }
387
388     /**
389      * Sets the current position of the Data set to the next row.
390      * @return True if there is another row. False if there are no more rows.
391      */

392     public boolean next()
393     {
394         return (++currentPos < size);
395     }
396     
397     /**
398      * Gets a Data object from a ResultSet.
399      *
400      * @param rs ResultSet passed in from a database query
401      * @return a Data object
402      * @throws java.sql.SQLException
403      */

404     public static Data getDataFromResultSet(ResultSet JavaDoc rs) throws SQLException JavaDoc
405     {
406         ResultSetMetaData JavaDoc meta = rs.getMetaData();
407         Data data = new Data();
408
409         int numColumns = meta.getColumnCount();
410         String JavaDoc[] dbCols = new String JavaDoc[numColumns];
411         for (int i = 0; i < numColumns; i++)
412         {
413             dbCols[i] = meta.getColumnName(i + 1);
414             data.addHeader(dbCols[i]);
415         }
416         
417         while (rs.next())
418         {
419             data.next();
420             for (int i = 0; i < numColumns; i++)
421             {
422                 Object JavaDoc o = rs.getObject(i + 1);
423                 if (o instanceof byte[])
424                 {
425                     o = new String JavaDoc((byte[]) o);
426                 }
427                 data.addColumnValue(dbCols[i], o);
428             }
429         }
430         return data;
431     }
432
433     /**
434      * Sets the current position of the Data set to the previous row.
435      * @return True if there is another row. False if there are no more rows.
436      */

437     public boolean previous()
438     {
439         return (--currentPos >= 0);
440     }
441
442     /**
443      * Resets the current position of the data set to just before the first
444      * element.
445      */

446     public void reset()
447     {
448         currentPos = -1;
449     }
450
451     /**
452      * Gets the value in the current row of the given column.
453      * @param column name of the column.
454      * @return an Object which holds the value of the column.
455      */

456     public Object JavaDoc getColumnValue(String JavaDoc column)
457     {
458         try
459         {
460             if (currentPos < size)
461             {
462                 return ((List JavaDoc) data.get(column)).get(currentPos);
463             }
464             else
465             {
466                 return null;
467             }
468         }
469         catch (Exception JavaDoc e)
470         {
471             return null;
472         }
473     }
474
475     /**
476      * Gets the value in the current row of the given column.
477      * @param column index of the column (starts at 0).
478      * @return an Object which holds the value of the column.
479      */

480     public Object JavaDoc getColumnValue(int column)
481     {
482         String JavaDoc columnName = (String JavaDoc) header.get(column);
483         try
484         {
485             if (currentPos < size)
486             {
487                 return ((List JavaDoc) data.get(columnName)).get(currentPos);
488             }
489             else
490             {
491                 return null;
492             }
493         }
494         catch (Exception JavaDoc e)
495         {
496             return null;
497         }
498     }
499
500     public Object JavaDoc getColumnValue(int column, int row)
501     {
502         setCurrentPos(row);
503         return getColumnValue(column);
504     }
505
506     public void removeColumn(int col)
507     {
508         String JavaDoc columnName = (String JavaDoc) header.get(col);
509         data.remove(columnName);
510         header.remove(columnName);
511     }
512
513     /**
514      * Sets the headers for the data set. Each header represents a column
515      * of data. Each row's data can be gotten with the column header name,
516      * which will always be a string.
517      *
518      * @param h array of strings representing the column headers.
519      */

520     public void setHeaders(String JavaDoc[] h)
521     {
522         int x = 0;
523         header = new ArrayList JavaDoc(h.length);
524         for (x = 0; x < h.length; x++)
525         {
526             header.add(h[x]);
527             data.put(h[x], new ArrayList JavaDoc());
528         }
529     }
530
531     /**
532      * Returns a String array of the column headers.
533      * @return array of strings of the column headers.
534      */

535     public String JavaDoc[] getHeaders()
536     {
537         String JavaDoc[] r = new String JavaDoc[header.size()];
538         if (r.length > 0)
539         {
540             r = (String JavaDoc[]) header.toArray(r);
541         }
542         return r;
543     }
544
545     /**
546      * This method will retrieve every entry in a certain column. It returns
547      * an array of Objects from the column.
548      *
549      * @param columnName name of the column.
550      * @return array of Objects representing the data.
551      */

552     public List JavaDoc getColumnAsObjectArray(String JavaDoc columnName)
553     {
554         return (List JavaDoc) data.get(columnName);
555     }
556
557     /**
558      * This method will retrieve every entry in a certain column. It returns
559      * an array of strings from the column. Even if the data are not strings,
560      * they will be returned as strings in this method.
561      *
562      * @param columnName name of the column.
563      * @return array of Strings representing the data.
564      */

565     public String JavaDoc[] getColumn(String JavaDoc columnName)
566     {
567         String JavaDoc[] returnValue;
568         Object JavaDoc o;
569         List JavaDoc temp = (List JavaDoc) data.get(columnName);
570         if (temp != null)
571         {
572             returnValue = new String JavaDoc[temp.size()];
573             Iterator JavaDoc it = temp.iterator();
574             int index = 0;
575             while (it.hasNext())
576             {
577                 o = it.next();
578                 if (o != null)
579                 {
580                     if (o instanceof String JavaDoc)
581                     {
582                         returnValue[index++] = (String JavaDoc) o;
583                     }
584                     else
585                     {
586                         returnValue[index++] = o.toString();
587                     }
588                 }
589             }
590         }
591         else
592         {
593             returnValue = new String JavaDoc[0];
594         }
595         return returnValue;
596     }
597
598     /**
599      * Use this method to set the entire data set. It takes an array of
600      * strings. It uses the first row as the headers, and the next rows
601      * as the data elements. Delimiter represents the delimiting character(s)
602      * that separate each item in a data row.
603      *
604      * @param contents array of strings, the first element is a list of the
605      * column headers, the next elements each represent a
606      * single row of data.
607      * @param delimiter the delimiter character that separates columns within
608      * the string array.
609      */

610     public void setData(String JavaDoc[] contents, String JavaDoc delimiter)
611     {
612         setHeaders(JOrphanUtils.split(contents[0], delimiter));
613         int x = 1;
614         while (x < contents.length)
615         {
616             setLine(JOrphanUtils.split(contents[x++], delimiter));
617         }
618     }
619
620     /*
621         Deletes a header from the Data object.
622         Takes the column name as input. It will delete the entire
623         column.
624     
625     public void deleteHeader(String s)
626     {
627     
628     }*/

629
630     /**
631      * Sets the data for every row in the column.
632      */

633     public void setColumnData(String JavaDoc colName, Object JavaDoc value)
634     {
635         List JavaDoc list = this.getColumnAsObjectArray(colName);
636         while (list.size() < size())
637         {
638             list.add(value);
639         }
640     }
641
642     public void setColumnData(int col, List JavaDoc data)
643     {
644         reset();
645         Iterator JavaDoc iter = data.iterator();
646         String JavaDoc columnName = (String JavaDoc) header.get(col);
647         while (iter.hasNext())
648         {
649             next();
650             setColumnValue(columnName, iter.next());
651         }
652     }
653
654     /**
655      * Adds a header name to the Data object.
656      * @param s name of header.
657      */

658     public void addHeader(String JavaDoc s)
659     {
660         header.add(s);
661         data.put(s, new ArrayList JavaDoc(size()));
662     }
663
664     /**
665      * Sets a row of data using an array of strings as input. Each value in
666      * the array represents a column's value in that row. Assumes the order
667      * will be the same order in which the headers were added to the data set.
668      *
669      * @param line array of strings representing column values.
670      */

671     public void setLine(String JavaDoc[] line)
672     {
673         List JavaDoc tempList;
674         String JavaDoc[] h = getHeaders();
675         for (int count = 0; count < h.length; count++)
676         {
677             tempList = (List JavaDoc) data.get(h[count]);
678             if (count < line.length && line[count].length() > 0)
679             {
680                 tempList.add(line[count]);
681             }
682             else
683             {
684                 tempList.add("N/A");
685             }
686         }
687         size++;
688     }
689
690     /**
691      * Sets a row of data using an array of strings as input. Each value in
692      * the array represents a column's value in that row. Assumes the order
693      * will be the same order in which the headers were added to the data set.
694      *
695      * @param line array of strings representing column values.
696      * @param deflt default value to be placed in data if line is not as long
697      * as headers.
698      */

699     public void setLine(String JavaDoc[] line, String JavaDoc deflt)
700     {
701         List JavaDoc tempList;
702         String JavaDoc[] h = getHeaders();
703         for (int count = 0; count < h.length; count++)
704         {
705             tempList = (List JavaDoc) data.get(h[count]);
706             if (count < line.length && line[count].length() > 0)
707             {
708                 tempList.add(line[count]);
709             }
710             else
711             {
712                 tempList.add(deflt);
713             }
714         }
715         size++;
716     }
717
718     /**
719      * Returns all the data in the Data set as an array of strings. Each
720      * array gives a row of data, each column separated by tabs.
721      *
722      * @return array of strings.
723      */

724     public String JavaDoc[] getDataAsText()
725     {
726         StringBuffer JavaDoc temp = new StringBuffer JavaDoc("");
727         String JavaDoc[] line = new String JavaDoc[size + 1];
728         String JavaDoc[] elements = getHeaders();
729         for (int count = 0; count < elements.length; count++)
730         {
731             temp.append(elements[count]);
732             if (count + 1 < elements.length)
733             {
734                 temp.append("\t");
735             }
736         }
737         line[0] = temp.toString();
738         reset();
739         int index = 1;
740         while (next())
741         {
742             temp = new StringBuffer JavaDoc("");
743             for (int count = 0; count < elements.length; count++)
744             {
745                 temp.append(getColumnValue(count));
746                 if (count + 1 < elements.length)
747                 {
748                     temp.append("\t");
749                 }
750             }
751             line[index++] = temp.toString();
752         }
753         return line;
754     }
755
756     public String JavaDoc toString()
757     {
758         String JavaDoc[] contents = getDataAsText();
759         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
760         boolean first = true;
761         for (int x = 0; x < contents.length; x++)
762         {
763             if (!first)
764             {
765                 sb.append("\n");
766             }
767             else
768             {
769                 first = false;
770             }
771             sb.append(contents[x]);
772         }
773         return sb.toString();
774     }
775 }
776
Popular Tags