|
From: <mic...@us...> - 2003-12-03 18:54:10
|
Update of /cvsroot/babeldoc/modules/jfreereports/src/com/babeldoc/utils In directory sc8-pr-cvs1:/tmp/cvs-serv28497/jfreereports/src/com/babeldoc/utils Added Files: XMLTableModel.java XMLTableModelTest.java Log Message: Initial commit after moving to modules directory --- NEW FILE: XMLTableModel.java --- /* ==================================================================== * The Apache Software License, Version 1.1 * * Copyright (c) 2000 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Apache" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact ap...@ap.... * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation. For more * information on the Apache Software Foundation, please see * <http://www.apache.org/>. * * Portions of this software are based upon public domain software * originally written at the National Center for Supercomputing Applications, * University of Illinois, Urbana-Champaign. * ==================================================================== * * Babeldoc: The Universal Document Processor * * $Header: /cvsroot/babeldoc/modules/jfreereports/src/com/babeldoc/utils/XMLTableModel.java,v 1.1 2003/12/03 18:54:05 michaelansley Exp $ * $DateTime$ * $Author: michaelansley $ * */ package com.babeldoc.utils; import com.babeldoc.core.LogService; import com.babeldoc.core.I18n; import java.lang.reflect.Constructor; import java.util.HashMap; import java.util.Map; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableModel; import javax.xml.transform.TransformerException; import org.apache.xpath.objects.XNumber; import org.apache.xpath.XPathAPI; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.dom4j.io.DOMWriter; import org.dom4j.DocumentException; /** * A class to provide an AbstractTableModel implementation for data held in * XML format. * * @author mikea * */ public class XMLTableModel extends AbstractTableModel implements TableModel { /** static: log service */ private static LogService log = LogService.getInstance(XMLTableModel.class.getName()); /** constant: document mime type */ public static final String XML_MIME_TYPE = "text/xml"; /** instance: root path for data */ public String QUERY_RESULTS = ""; /** instance: element identifier for rows */ public String ROW = "row"; /** constant: element identifier for row numbers, * TODO: should be configurable by the user */ public static final String ROW_NUMBER = "row-number"; /** instance: element identifier for columns */ public String COLUMN = "column"; /** constant: element identifier for column names, * TODO: should be configurable by the user */ public static final String COLUMN_NAME = "column-name"; /** constant: element identifier for column numbers, * TODO: should be configurable by the user */ public static final String COLUMN_NUMBER = "column-number"; /** constant: element identifier for column class identifiers, * TODO: should be configurable by the user */ public static final String COLUMN_CLASS = "column-class"; /** constant: the default column class identifier */ public static final String DEFAULT_CLASS_NAME = "java.lang.String"; /** constant: the default column class */ public static final Class DEFAULT_CLASS = java.lang.String.class; /** instance: the data */ private Document xmlData; /** instance: cache of the column count */ private int columnCount = -1; /** instance: cache of the row count */ private int rowCount = -1; /** instance: cache of the column classes */ private Class[] columnClasses; /** instance: cache of the column names */ private String[] columnNames; /** instance: cache of the column ordinal positions keyed on name */ private Map columnNumbers = new HashMap(); /** * The default constructor * */ public XMLTableModel() { xmlData = null; } /** * Constructor with data document and root path to data * * @param data the data document * @param rootPath the string representation of the path to the * data within the document * */ public XMLTableModel(org.dom4j.Document data, String rootPath) throws org.dom4j.DocumentException { QUERY_RESULTS = rootPath; xmlData = transformToDOM(data); columnClasses = new Class[getColumnCount()]; columnNames = new String[getColumnCount()]; } /** * Set the data document and clear the cached information * * @param info */ public void setDocument(org.dom4j.Document doc, String rootPath) throws org.dom4j.DocumentException { QUERY_RESULTS = rootPath; xmlData = transformToDOM(doc); columnCount = -1; rowCount = -1; columnClasses = new Class[getColumnCount()]; columnNames = new String[getColumnCount()]; columnNumbers = new HashMap(); } /* (non-Javadoc) * @see javax.swing.table.TableModel#getColumnCount() */ public int getColumnCount() { if (xmlData == null) return (0); if (columnCount >= 0) return (columnCount); // This is the xpath for the count of columns in the first row String xpath = "count(" + QUERY_RESULTS + "/" + ROW + "[@row-number=\"0\"]/" + COLUMN + ")"; XNumber n; try { n = (XNumber) XPathAPI.eval(xmlData, xpath); } catch (TransformerException e) { log.logError(e); return (-1); } columnCount = new Double(n.num()).intValue(); return (columnCount); } /* (non-Javadoc) * @see javax.swing.table.TableModel#getRowCount() */ public int getRowCount() { if (xmlData == null) return (0); if (rowCount >= 0) return (rowCount); // This is the xpath for the count of columns in the first row String xpath = "count(" + QUERY_RESULTS + "/" + ROW + ")"; XNumber n; try { n = (XNumber) XPathAPI.eval(xmlData, xpath); } catch (TransformerException e) { log.logError(e); return (-1); } // Get the result value from the node and cache rowCount = new Double(n.num()).intValue(); return (rowCount); } /* (non-Javadoc) * @see javax.swing.table.TableModel#getValueAt(int, int) */ public Object getValueAt(int rowIndex, int columnIndex) { if (xmlData == null) return (null); // This is the xpath for a cell in an XML data document from the SqlQuery // pipeline stage String xpath = QUERY_RESULTS + "/" + ROW + "[@" + ROW_NUMBER + "=\"" + rowIndex + "\"]/" + COLUMN + "[@" + COLUMN_NUMBER + "=\"" + (columnIndex + 1) + "\"]"; Node n; try { n = XPathAPI.selectSingleNode(xmlData, xpath); } catch (TransformerException e) { log.logError(e); return null; } NamedNodeMap attrs = n.getAttributes(); String className = attrs.getNamedItem(COLUMN_CLASS).getNodeValue(); if (className == null || className.equals("")) { className = DEFAULT_CLASS_NAME; } Object v; try { Class c = Class.forName(className); Constructor cons = c.getConstructor(new Class[] {String.class}); if (n.getFirstChild() == null) { v = null; } else { v = cons.newInstance(new Object[] {n.getFirstChild().getNodeValue()}); } } catch (Exception e) { log.logWarn(e.getMessage()); v = new String("[" + I18n.get("jfr.104", className) + "]"); } return v; } /** * Convert the document to w3c format * * @param info */ private org.w3c.dom.Document transformToDOM(org.dom4j.Document doc) throws DocumentException { DOMWriter writer = new DOMWriter(); return writer.write(doc); } /** * Returns the class of the column specified * * @param columnIndex the column being queried * @return the Object.class, or null if the position is not valid */ public Class getColumnClass(int columnIndex) { if ((columnIndex < 0) || (columnIndex >= columnClasses.length)) return (null); // Invalid index Class c = columnClasses[columnIndex]; if (c == null) { if (xmlData == null) return (null); // This is the xpath for a cell in an XML data document from the SqlQuery // pipeline stage String xpath = QUERY_RESULTS + "/" + ROW + "[@row-number=\"0\"]/" + COLUMN + "[@" + COLUMN_NUMBER + "=\"" + (columnIndex + 1) + "\"]"; Node n; try { n = XPathAPI.selectSingleNode(xmlData, xpath); } catch (TransformerException e) { log.logError(e); return null; } if (n == null) return (null); // Column position not found NamedNodeMap attrs = n.getAttributes(); String className = attrs.getNamedItem(COLUMN_CLASS).getNodeValue(); if (className == null || className.equals("")) { className = DEFAULT_CLASS_NAME; } try { c = Class.forName(className); } catch (ClassNotFoundException e) { log.logWarn(e.getMessage()); c = DEFAULT_CLASS; } columnClasses[columnIndex] = c; } return (c); } /** * Returns the column name for the column index specified * * @param column the column being queried * @return a string containing the name of <code>column</code> or * an empty string if not found */ public String getColumnName(int column) { String name; if ((column < 0) || (column >= columnNames.length)) return (""); // Invalid index name = columnNames[column]; if (name == null) { if (xmlData == null) return (null); // This is the xpath for a cell in an XML data document from the SqlQuery // pipeline stage String xpath = QUERY_RESULTS + "/" + ROW + "[@row-number=\"0\"]/" + COLUMN + "[@" + COLUMN_NUMBER + "=\"" + (column + 1) + "\"]"; Node n; try { n = XPathAPI.selectSingleNode(xmlData, xpath); } catch (TransformerException e) { log.logError(e); return null; } if (n == null) return (""); // Column position not found NamedNodeMap attrs = n.getAttributes(); name = attrs.getNamedItem(COLUMN_NAME).getNodeValue(); columnNames[column] = name; } return (name); } /** * Returns a column index given its name. * * @param columnName string containing name of column to be located * @return the column with <code>columnName</code>, or -1 if not found */ public int findColumn(String columnName) { if (xmlData == null) return (-1); Integer columnNumber = (Integer) columnNumbers.get(columnName); if (columnNumber == null) { // This is the xpath for the count of columns in the first row String xpath = QUERY_RESULTS + "/" + ROW + "[@row-number=\"0\"]/" + COLUMN + "[@" + COLUMN_NAME + "=\"" + columnName + "\"]"; Node n; try { n = XPathAPI.selectSingleNode(xmlData, xpath); } catch (TransformerException e) { log.logError(e); return -1; } if (n == null) return (-1); // Column name not found NamedNodeMap attrs = n.getAttributes(); columnNumber = new Integer(attrs.getNamedItem(COLUMN_NUMBER).getNodeValue()); columnNumbers.put(columnName, columnNumber); } return (columnNumber.intValue() - 1); } public String getColumnID() { return COLUMN; } public void setColumnID(String column) { COLUMN = column; } public String getRowID() { return ROW; } public void setRowID(String row) { ROW = row; } } --- NEW FILE: XMLTableModelTest.java --- /* * Created on 28-Nov-2003 * * To change the template for this generated file go to * Window>Preferences>Java>Code Generation>Code and Comments */ package com.babeldoc.utils; import junit.framework.TestCase; import org.dom4j.Document; import org.dom4j.DocumentHelper; /** * @author mikea * * To change the template for this generated type comment go to * Window>Preferences>Java>Code Generation>Code and Comments */ public class XMLTableModelTest extends TestCase { private XMLTableModelTest() { String strDoc = new String("<?xml version=\"1.0\" encoding=\"UTF-8\"?>" + "<queryresults>" + " <query query-name=\"query1\" query-number=\"0\">" + " <row row-number=\"0\">" + " <column column-name=\"quiz\" column-number=\"1\" column-class=\"java.lang.String\">Yes</column>" + " <column column-name=\"company_name\" column-number=\"2\" column-class=\"java.lang.String\">Peter Abel</column>" + " <column column-name=\"last_name\" column-number=\"3\" column-class=\"java.lang.String\">Abel</column>" + " <column column-name=\"first_name\" column-number=\"4\" column-class=\"java.lang.String\">Peter</column>" + " <column column-name=\"main_phone\" column-number=\"5\" column-class=\"java.lang.String\">(888)555-8188</column>" + " <column column-name=\"fk_seminar_code\" column-number=\"6\" column-class=\"java.lang.String\">001</column>" + " <column column-name=\"seminar_tmpl_name\" column-number=\"7\" column-class=\"java.lang.String\">Annual Update</column>" + " <column column-name=\"start_date\" column-number=\"8\" column-class=\"java.lang.String\">11/17/1999</column>" + " <column column-name=\"hotel_place\" column-number=\"9\" column-class=\"java.lang.String\">Corte, CA</column>" + " <column column-name=\"amount_paid\" column-number=\"10\" column-class=\"java.math.BigDecimal\">200.000000</column>" + " <column column-name=\"id_booking\" column-number=\"11\" column-class=\"java.lang.Integer\">65703</column>" + " <column column-name=\"shipping_address\" column-number=\"12\" column-class=\"java.lang.String\"></column>" + " <column column-name=\"city\" column-number=\"13\" column-class=\"java.lang.String\">Oakland</column>" + " <column column-name=\"attended\" column-number=\"14\" column-class=\"java.lang.String\">No</column>" + " </row>" + " <row row-number=\"1\">" + " <column column-name=\"quiz\" column-number=\"1\" column-class=\"java.lang.String\">Yes</column>" + " <column column-name=\"company_name\" column-number=\"2\" column-class=\"java.lang.String\">David Bartley</column>" + " <column column-name=\"last_name\" column-number=\"3\" column-class=\"java.lang.String\">Bartley</column>" + " <column column-name=\"first_name\" column-number=\"4\" column-class=\"java.lang.String\">David</column>" + " <column column-name=\"main_phone\" column-number=\"5\" column-class=\"java.lang.String\">(888)555-7703</column>" + " <column column-name=\"fk_seminar_code\" column-number=\"6\" column-class=\"java.lang.String\">001</column>" + " <column column-name=\"seminar_tmpl_name\" column-number=\"7\" column-class=\"java.lang.String\">Annual Update</column>" + " <column column-name=\"start_date\" column-number=\"8\" column-class=\"java.lang.String\">11/18/1999</column>" + " <column column-name=\"hotel_place\" column-number=\"9\" column-class=\"java.lang.String\">Corte, CA</column>" + " <column column-name=\"amount_paid\" column-number=\"10\" column-class=\"java.math.BigDecimal\">165.000000</column>" + " <column column-name=\"id_booking\" column-number=\"11\" column-class=\"java.lang.Integer\">50989</column>" + " <column column-name=\"shipping_address\" column-number=\"12\" column-class=\"java.lang.String\"></column>" + " <column column-name=\"city\" column-number=\"13\" column-class=\"java.lang.String\">Novato</column>" + " <column column-name=\"attended\" column-number=\"14\" column-class=\"java.lang.String\">Yes</column>" + " </row>" + " </query>" + "</queryresults>" ); Document doc; XMLTableModel tm; try { doc = DocumentHelper.parseText(strDoc); tm = new XMLTableModel(doc, "/queryresults/query"); // Column and row counts System.out.println("Column count: " + tm.getColumnCount()); System.out.println("Row count: " + tm.getRowCount()); // Column names and ordinals for (int i = 0; i < tm.getColumnCount(); i++) { String name = tm.getColumnName(i); System.out.println("Position: " + i + ", Name: " + name + ", Ordinal: " + tm.findColumn(name) + ", Class: " + tm.getColumnClass(i).getName()); } // Find a non-existent column name System.out.println(tm.findColumn("XXX")); // Find a non-existent column position System.out.println(tm.getColumnName(15)); // Find a non-existent column class System.out.println(tm.getColumnClass(15)); // getValueAt for (int row = 0; row < tm.getRowCount(); row++) { for (int col = 0; col < tm.getColumnCount(); col++) { String name = tm.getColumnName(col); Object o = tm.getValueAt(row, col); String value; if (o == null) { value = "null"; } else { value = o.toString(); } System.out.println("Row: " + row + ", Column: " + name + ", Value: " + value); } } } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { System.getProperties().list(System.out); XMLTableModelTest test = new XMLTableModelTest(); } } |