/*
* $Id: WebRowSetDataProvider.java,v 1.6.2.1 2006/01/13 02:00:59 rbair Exp $
*
* Created on March 21, 2005, 9:52 AM
* Copyright 2005 Sun Microsystems, Inc., 4150 Network Circle,
* Santa Clara, California 95054, U.S.A. All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
package org.jdesktop.databuffer.provider.sql;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.math.BigDecimal;
import java.net.URL;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Stack;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sql.RowSetMetaData;
import javax.sql.rowset.RowSetMetaDataImpl;
import javax.swing.SwingUtilities;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.jdesktop.databuffer.DataColumn;
import org.jdesktop.databuffer.DataProvider;
import org.jdesktop.databuffer.DataRow;
import org.jdesktop.databuffer.DataTable;
import org.jdesktop.databuffer.event.TableChangeEvent;
import org.jdesktop.databuffer.provider.LoadTask;
import org.jdesktop.databuffer.provider.SaveTask;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.DefaultHandler;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
/**
* Takes webrowset XML and uses it to populate a DataTable. This particular
* DataProvider will drop all of the columns from the DataTable and add new
* columns back in based on the meta data in the XML.
*
* @author Richard Bair
*/
public class WebRowSetDataProvider extends DataProvider {
/** The Logger */
private static final Logger LOG = Logger.getLogger(WebRowSetDataProvider.class.getName());
/**
* A static instance of the Factory used to parse documents in this WebRowSet implementation
*/
private static final SAXParserFactory FACTORY = SAXParserFactory.newInstance();
private URL url;
private Runnable completionRunnable;
private Runnable metadataCompleteRunnable;
/**
* Static initialization code for the FACTORY. Currently setting validating to false.
*/
static {
FACTORY.setValidating(false);
}
/** Creates a new instance of WebRowSetDataProvider */
public WebRowSetDataProvider() {
}
protected SaveTask createSaveTask(DataTable[] tables) {
return new SaveTask(tables) {
protected void saveData(DataTable[] tables) throws Exception {}
};
}
final class RowLoadItem {
public Object[] values;
public DataRow.DataRowStatus status;
}
protected LoadTask createLoadTask(DataTable[] tables) {
return new LoadTask(tables) {
class WebRowSetXMLHandler extends DefaultHandler implements LexicalHandler {
DataTable table;
/**
* List to keep track of rows that need to be loaded
*/
private List dataToLoad = new LinkedList();
/**
* Stack to keep track of which tags have been seen
*/
private Stack<String> tagStack = new Stack<String>();
/**
* Set to true if we have seen an opening "properties" tag, but not a closing.
* inProperties, inMetaData, and inData are mutually exclusive
*/
private boolean inProperties = false;
/**
* Set to true if we have seen an opening "metadata" tag, but not a closing.
* inProperties, inMetaData, and inData are mutually exclusive
*/
private boolean inMetaData = false;
/**
* Set to true if we have seen an opening "data" tag, but not a closing.
* inProperties, inMetaData, and inData are mutually exclusive
*/
private boolean inData = false;
/**
* The meta data object being updated. This metaData object is modified until the
* closing "metadata" tag is found. Then the ShopLogicWebRowSet's meta data is updated
* in one fell stroke
*/
private RowSetMetaData metaData = null;
/**
* Keeps track of which column we are currently dealing with. This is used both by the
* metadata parsing code, and the data parsing code
*/
private int columnIndex = 1;
/**
* This is a stack of keyColumns parsed. After being parsed and added to this stack, they are
* added to an int[] and set in the WebRowSet.
*/
private Stack<Integer> keyColumnsStack = new Stack<Integer>();
/**
* Keeps track of the "type" value while parsing the type map.
*/
private String mapType;
/**
* Keeps track of the "class" value while parsing the type map.
*/
private String mapClass;
/**
* This is the map of types, as parsed from the file. After the closing "map" tag is found, the
* WebRowSet is updated.
*/
private Map<String,Class<?>> typeMap = new HashMap<String,Class<?>>();
/**
* Contains the data value parsed from the <code>characters</code> method. This is simply a string.
* The <code>setValue</code> method is responsible for parsing this into an int, bool, etc.
*/
private String data;
/**
* Keeps track of whether the last tag read was null.
*/
private boolean wasNull;
/**
* This String is used while in the data portion of parsing. It is used as the first part of they
* key in the cache for a row.
*/
private String tableName = "";
/**
* This list maintains the rowValues as parsed from the file. After they are all parsed,
* they are passed to the row.
*/
private Object[] rowValues;
/**
* The index of the current row being processed. This is 1 based
*/
private int currentRow = 0;
public WebRowSetXMLHandler(DataTable table) {
this.table = table;
}
public void comment(char[] ch, int start, int length)
throws SAXEx