Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/dghda/kent/ReportData.java


1   /* Copyright (C) 2001 Duane Griffin <duanegriffin@users.sourceforge.net>
2      This file is part of Kent.
3   
4      Kent is free software; you can redistribute it and/or
5      modify it under the terms of the GNU General Public License as
6      published by the Free Software Foundation; either version 2 of the
7      License, or (at your option) any later version.
8   
9      Kent is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12     General Public License for more details.
13  
14     You should have received a copy of the GNU General Public
15     License along with Kent; see the file COPYING.  If not,
16     write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17     Boston, MA 02111-1307, USA.
18  */
19  
20  package com.dghda.kent;
21  
22  import java.util.*;
23  
24  import org.w3c.dom.*;
25  
26  import org.xml.sax.*;
27  
28  /**
29     This class provides a convenient method of creating a report data document.
30     Report data documents are formatted based on their report template.
31  */
32  public class ReportData {
33    
34    /** A class which contains encapsulates a data set. */
35    public static class DataSet {
36      
37      /**
38         Creates a new data set with the given name.
39         @param name The new data set's name.
40         @param columns Names of the data columns.
41         @throws InvalidColumnException If there are no columns given.
42      */
43      public DataSet (String name, String [] columns) throws InvalidColumnException {
44        
45        // Sanity check columns
46        if (columns == null || columns.length == 0)
47          throw new InvalidColumnException ("Data set must include at least one column");
48        
49        m_Name = name;
50        m_Columns = columns;
51        for (int index = 0; index != m_Columns.length; ++index)
52          m_ColumnIndex.put (m_Columns[index], new Integer (index));
53      }
54      
55      /**
56         Creates a new data set by parsing the given DOM element.
57         @throws InvalidColumnException If the column info is invalid or inconsistent.
58      */
59      public DataSet (Element elem) throws InvalidColumnException {
60        
61        // Get & sanity check the name
62        m_Name = elem.getAttribute ("Name");
63        if (m_Name == null)
64          throw new DOMException (DOMException.SYNTAX_ERR, "No data set name specified");
65        
66        // Parse columns info
67        NodeList columns = elem.getElementsByTagName ("Column");
68        if (columns.getLength() == 0)
69          throw new InvalidColumnException ("No columns specified in data set " + m_Name);
70        
71        m_Columns = new String [columns.getLength()];
72        for (int index = 0; index != columns.getLength(); ++index) {
73          String column = XMLConstructor.getNodeText (columns.item (index));
74          m_Columns[index] = column;
75          m_ColumnIndex.put (column, new Integer (index));
76        }
77        
78        // Parse rows
79        NodeList rows = elem.getElementsByTagName ("Row");
80        for (int index = 0; index != rows.getLength(); ++index)
81          parseRow ((Element) rows.item (index));
82      }
83      
84      /** Get the data set's name. */
85      public String getName() {
86        return m_Name;
87      }
88      
89      /** Get the column headings. */
90      public String [] getColumns() {
91        return m_Columns;
92      }
93      
94      /** Returns the number of rows in the data set. */
95      public int getNumberRows() {
96        return m_Rows.size();
97      }
98      
99      /** Returns an iterator over the rows in the data set. */
100     public Iterator getRowIterator() {
101       return m_Rows.iterator();
102     }
103     
104     /**
105        Returns the value of the given column/row.
106        @param field The column to access.
107        @param row The row number to access.
108        @throws InvalidColumnException If the given field is not a column in the specified data set.
109        @throws ArrayIndexOutOfBounds If the specified row is invalid.
110     */
111     public String getDatum (String field, int row) {
112       
113       // Find the column
114       Integer index = (Integer) m_ColumnIndex.get (field);
115       if (index == null)
116         throw new InvalidColumnException ("Field " + field + " doesn't exist");
117       
118       // Get the data
119       String [] data = (String []) m_Rows.get (row);
120       return data[index.intValue()];
121     }
122     
123     /**
124        Adds a row.
125        @param data Values for the row.
126        @throws InvalidColumnException If the data doesn't match the column info for the given data set.
127     */
128     public void addRow (String [] data) throws InvalidColumnException {
129       
130       // Check the number of columns is correct
131       if (data.length != m_Columns.length)
132         throw new InvalidColumnException ("Row data must contain " + m_Columns.length + " columns");
133       
134       // Add the data
135       m_Rows.add (data);
136     }
137     
138     /** Parse a row. */
139     protected void parseRow (Element row) throws InvalidColumnException {
140       
141       // Sanity check the data matches that specified
142       NamedNodeMap attrs = row.getAttributes();
143       if (attrs.getLength() != m_Columns.length)
144         throw new InvalidColumnException ("Row data must contain " + m_Columns.length + " columns");
145       
146       // Get & add the data
147       String [] data = new String[m_Columns.length];
148       for (int index = 0; index != m_Columns.length; ++index)
149         data[index] = attrs.getNamedItem (m_Columns[index]).getNodeValue();
150       m_Rows.add (data);
151     }
152     
153     private String m_Name;
154     private String [] m_Columns;
155     private HashMap m_ColumnIndex = new HashMap();
156     private ArrayList m_Rows = new ArrayList();
157   }
158   
159   /** Constructs a new report data object. */
160   public ReportData() {
161   }
162   
163   /**
164      Constructs a new report data object by parsing the given document.
165      @param data The report data document to parse
166      @throws SAXException If the document is not valid report data
167   */
168   protected ReportData (Document data) throws SAXException {
169     
170     // Check the document is actually a report template
171     DocumentType type = data.getDoctype();
172     if (type != null && (!type.getName().equals ("KentData")))
173       throw new SAXException ("Document must be of type KentData");
174     
175     // Parse the data set elements
176     NodeList dataSets = data.getDocumentElement().getElementsByTagName ("DataSet");
177     for (int index = 0; index != dataSets.getLength(); ++index) {
178       DataSet dataSet = new DataSet ((Element) dataSets.item (index));
179       m_DataSets.put (dataSet.getName(), dataSet);
180     }
181   }
182   
183   /**
184      Constructs a new report data object by parsing the given XML document.
185      @param data The report data document to parse
186      @throws javax.xml.parsers.ParserConfigurationException If there was a configuration error creating the XML parser
187      @throws SAXException If the document is not valid report data
188   */
189   public static ReportData constructReportData (String data) throws javax.xml.parsers.ParserConfigurationException, SAXException {
190     Document doc = XMLConstructor.parseDocument (data);
191     return new ReportData (doc);
192   }
193   
194   /**
195      Adds a new data set to the report.
196      @param name The new data set's name.
197      @param columns Names of the data columns.
198      @throws InvalidColumnException If there are no columns given.
199      @throws InvalidDataSetException If the specified data set already exists.
200   */
201   public synchronized void addDataSet (String name, String [] columns) throws InvalidColumnException, InvalidDataSetException {
202     
203     // Check the data set specified doesn't already exist
204     if (m_DataSets.get (name) != null)
205       throw new InvalidDataSetException ("Data set " + name + " already exists");
206     
207     // Add the data set
208     m_DataSets.put (name, new DataSet (name, columns));
209   }
210   
211   /**
212      Adds a new, already constructed, data set to the report.
213      @param data The new data set.
214      @throws InvalidDataSetException If the specified data set already exists.
215   */
216   public synchronized void addDataSet (DataSet data) throws InvalidDataSetException {
217     
218     // Check the data set specified doesn't already exist
219     if (m_DataSets.get (data.getName()) != null)
220       throw new InvalidDataSetException ("Data set " + data.getName() + " already exists");
221     
222     // Add the data set
223     m_DataSets.put (data.getName(), data);
224   }
225   
226   /**
227      Adds a row to the specified data set.
228      @param name The data set to add the row to
229      @param data Values for the row.
230      @throws InvalidColumnException If the data doesn't match the column info for the given data set.
231      @throws InvalidDataSetException If the specified data set doesn't exist.
232   */
233   public synchronized void addRow (String name, String [] data) throws InvalidColumnException, InvalidDataSetException {
234     
235     // Get the data set
236     DataSet dataSet = (DataSet) m_DataSets.get (name);
237     if (dataSet == null)
238       throw new InvalidDataSetException ("Data set " + name + " doesn't exist");
239     
240     dataSet.addRow (data);
241   }
242   
243   /** Returns the given data set. */
244   public synchronized DataSet getDataSet (String name) {
245     return (DataSet) m_DataSets.get (name);
246   }
247   
248   /**
249      An iterator over the data sets.
250      The iterator returns a data set object.
251   */
252   public synchronized Iterator getDataSetIterator() {
253     return m_DataSets.values().iterator();
254   }
255   
256   /** Gets the number of rows in a given data set. */
257   public synchronized int getNumberRows (String dataSet) throws InvalidDataSetException {
258     
259     // Get the data set
260     DataSet data = (DataSet) m_DataSets.get (dataSet);
261     if (data == null)
262       throw new InvalidDataSetException ("Data set " + dataSet + " doesn't exist");
263     
264     return data.getNumberRows();
265   }
266   
267   /**
268      Gets the value of a specific column.
269      @param dataSet The name of the data set to get the data from.
270      @param field The column to access.
271      @param which The row number to access.
272      @returns null if the specified column doesn't exist.
273      @throws InvalidColumnException If the given field is not a column in the specified data set.
274      @throws InvalidDataSetException If the specified data set doesn't exist.
275      @throws ArrayIndexOutOfBounds If the specified row is invalid.
276   */
277   public synchronized String getColumn (String dataSet, String field, int which) throws InvalidColumnException, InvalidDataSetException {
278     
279     // Get the data set
280     DataSet data = (DataSet) m_DataSets.get (dataSet);
281     if (data == null)
282       throw new InvalidDataSetException ("Data set " + dataSet + " doesn't exist");
283     
284     return data.getDatum (field, which);
285   }
286   
287   /** Returns a document containing the report data constructed. */
288   public synchronized String getData() {
289     StringBuffer result = new StringBuffer();
290     
291     // Pre-amble
292     result.append ("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n");
293     result.append ("<KentData>\n");
294     
295     // Create each data set
296     Iterator dataSets = m_DataSets.values().iterator();
297     while (dataSets.hasNext()) {
298       DataSet dataSet = (DataSet) dataSets.next();
299       
300       // Create & add data set element
301       result.append ("  <DataSet");
302       XMLConstructor.addAttribute (result, "Name", dataSet.getName());
303       result.append (">\n");
304       
305       // Add the column info
306       String [] columns = dataSet.getColumns();
307       for (int index = 0; index != columns.length; ++index) {
308         
309         // Create & add new column element
310         result.append ("    <Column>");
311         result.append (columns[index]);
312         result.append ("</Column>\n");
313       }
314       
315       // Add each row
316       Iterator values = dataSet.getRowIterator();
317       while (values.hasNext()) {
318         String [] rowData = (String []) values.next();
319         
320         // Create new row element
321         result.append ("    <Row");
322         
323         // Add column data
324         for (int index = 0; index != columns.length; ++index)
325           XMLConstructor.addAttribute (result, columns[index], rowData[index]);
326         
327         // Add row to data set
328         result.append ("/>\n");
329       }
330       
331       result.append ("  </DataSet>\n");
332     }
333     result.append ("</KentData>\n");
334     
335     return result.toString();
336   }
337   
338   private TreeMap m_DataSets = new TreeMap();
339 }