All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.datastax.data.dataset.provider.sql.WebRowSetDataProvider Maven / Gradle / Ivy

The newest version!
package com.datastax.data.dataset.provider.sql;

import com.datastax.data.dataset.DataColumn;
import com.datastax.data.dataset.DataProvider;
import com.datastax.data.dataset.DataRow;
import com.datastax.data.dataset.DataTable;
import com.datastax.data.dataset.event.TableChangeEvent;
import com.datastax.data.dataset.provider.LoadTask;
import com.datastax.data.dataset.provider.SaveTask;
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;
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 javax.sql.RowSetMetaData;
import javax.sql.rowset.RowSetMetaDataImpl;
import javax.swing.*;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URL;
import java.sql.SQLException;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;


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 tagStack = new Stack();
                /**
                 * 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 keyColumnsStack = new Stack();
                /**
                 * 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> typeMap = new HashMap>();
                /**
                 * Contains the data value parsed from the characters method. This is simply a string.
                 * The setValue 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 SAXException {
                    
                }
                
                public void startCDATA()
                throws SAXException {
                }
                
                public void endCDATA()  throws SAXException {
                }
                
                public void startEntity(String name)
                throws SAXException {
                }
                
                public void endEntity(String name)
                throws SAXException {
                }
                
                public void startDTD(
                        String name, String publicId, String systemId)
                        throws SAXException {
                }
                
                public void endDTD()
                throws SAXException {
                }
                
                /**
                 * Updates the data variable with the given characters using the default character set
                 * @inheritDoc
                 */
                public void characters(char[] ch, int start, int length) throws SAXException {
                    //Remember that characters may be called multiple times for the same
                    //element, so if data is null then the characters delivered here are
                    //the data, otherwise append the characters to data
                    if (data == null) {
                        data = new String(ch, start, length);
                    } else {
                        data = data + new String(ch, start, length);
                    }
                    data = data.trim();
                }
                
                /**
                 * Helper method that updates the current row at the given column with the given value.
                 * This code actually determines the column type for the designated column, and uses that
                 * information to transform the value into the proper data type. Data MAY be null
                 * @param columnIndex
                 * @param value
                 * @throws Exception
                 */
                private void setValue(int columnIndex, String value) throws Exception {
                    //TODO Take into account the possiblity of a collision, and notify listeners if necessary
                    if (wasNull || value == null) {
                        rowValues[columnIndex - 1] = null;
                    } else {
                        switch (metaData.getColumnType(columnIndex)) {
                            case Types.TINYINT:
                                rowValues[columnIndex - 1] = Byte.valueOf(value.trim());
                                break;
                            case Types.SMALLINT:
                                rowValues[columnIndex - 1] = Short.valueOf(value.trim());
                                break;
                            case Types.INTEGER:
                                rowValues[columnIndex - 1] = Integer.valueOf(value.trim());
                                break;
                            case Types.BIGINT:
                                rowValues[columnIndex - 1] = Long.valueOf(value.trim());
                                break;
                            case Types.REAL:
                                rowValues[columnIndex - 1] = Float.valueOf(value.trim());
                                break;
                            case Types.FLOAT:
                            case Types.DOUBLE:
                                rowValues[columnIndex - 1] = Double.valueOf(value.trim());
                                break;
                            case Types.DECIMAL:
                            case Types.NUMERIC:
                                rowValues[columnIndex - 1] = new BigDecimal(value.trim());
                                break;
                            case Types.BOOLEAN:
                            case Types.BIT:
                                rowValues[columnIndex - 1] = Boolean.valueOf(value.trim());
                                break;
                            case Types.CHAR:
                            case Types.VARCHAR:
                            case Types.LONGVARCHAR:
                                rowValues[columnIndex - 1] = value;
                                break;
                            case Types.VARBINARY:
                            case Types.LONGVARBINARY:
                            case Types.BINARY:
                                byte[] bytes = Base64.decode(value);
                                rowValues[columnIndex - 1] = bytes;
                                break;
                            case Types.DATE:
                            case Types.TIME:
                            case Types.TIMESTAMP:
                                rowValues[columnIndex - 1] = new Timestamp(Long.parseLong(value.trim()));
                                break;
                            case Types.ARRAY:
                            case Types.BLOB:
                            case Types.CLOB:
                            case Types.DATALINK:
                            case Types.DISTINCT:
                            case Types.JAVA_OBJECT:
                            case Types.OTHER:
                            case Types.REF:
                            case Types.STRUCT:
                                //what to do with this?
                                break;
                            default :
                                //do nothing
                        }
                    }
                }
                
                /**
                 * @inheritDoc
                 */
                public void endDocument() throws SAXException {
                    doLoad(table, dataToLoad);
                    if (completionRunnable != null) {
                        SwingUtilities.invokeLater(completionRunnable);
                    }
                }
                
                /**
                 * @inheritDoc
                 */
                public void endElement(String uri, String localName, String qName) throws SAXException {
                    if (tagStack.size() == 0) {
                        return;
                    }
                    //get the last tag seen
                    String tag = tagStack.pop();
                    //handle each tag. Handle the data tags first since those will be called most frequently
                    try {
                        if (tag.equals("null")) {
                            wasNull = true;
                        } else if (tag.equals("columnvalue")) {
                            //set the current column value
                            setValue(columnIndex++, wasNull ? null : data);
                        } else if (tag.equals("updatevalue")) {
                            //set the update column value (the column to
                            //apply the update to is the previous
                            //columnIndex)
                            setValue(columnIndex-1, wasNull ? null : data);
                        } else if (tag.equals("currentrow")) {
                            RowLoadItem loadItem = new RowLoadItem();
                            loadItem.values = new Object[rowValues.length];
                            System.arraycopy(rowValues, 0, loadItem.values, 0, rowValues.length);
                            loadItem.status = DataRow.DataRowStatus.UNCHANGED;
                            dataToLoad.add(loadItem);
                        } else if (tag.equals("insertrow")) {
                            RowLoadItem loadItem = new RowLoadItem();
                            loadItem.values = new Object[rowValues.length];
                            System.arraycopy(rowValues, 0, loadItem.values, 0, rowValues.length);
                            loadItem.status = DataRow.DataRowStatus.INSERTED;
                        } else if (tag.equals("deleterow")) {
                            RowLoadItem loadItem = new RowLoadItem();
                            loadItem.values = new Object[rowValues.length];
                            System.arraycopy(rowValues, 0, loadItem.values, 0, rowValues.length);
                            loadItem.status = DataRow.DataRowStatus.DELETED;
                        } else if (tag.equals("modifyrow")) {
                            RowLoadItem loadItem = new RowLoadItem();
                            loadItem.values = new Object[rowValues.length];
                            System.arraycopy(rowValues, 0, loadItem.values, 0, rowValues.length);
                            loadItem.status = DataRow.DataRowStatus.UPDATED;
                        }  else if (tag.equals("column")) {
                            //in key-columns
                            if (!wasNull) {
                                keyColumnsStack.push(new Integer(data.trim()));
                            }
                        } else if (tag.equals("type")) {
                            mapType = wasNull ? null : data;
                        } else if (tag.equals("class")) {
                            mapClass = wasNull ? null : data;
                            //add the type and class to the typeMap
                            typeMap.put(mapType, mapClass == null ? null : Class.forName(mapClass));
                        } else if (tag.equals("table-name")) {
                            if (inProperties) {
//                                        setTableName(wasNull ? null : data);
                            } else if (inMetaData) {
                                metaData.setTableName(columnIndex, wasNull ? null : data);
                            }
                        } else if (tag.equals("column-count")) {
                            metaData.setColumnCount(wasNull ? 0 : Integer.parseInt(data.trim()));
                        } else if (tag.equals("column-index")) {
                            columnIndex = Integer.parseInt(data.trim());
                        } else if (tag.equals("key-columns")) {
                            int[] kc = new int[keyColumnsStack.size()];
                            int i = 0;
                            for (Integer col : keyColumnsStack) {
                                kc[i++] = col.intValue();
                            }
//                            try {
//                                        setKeyColumns(kc);
//                            } catch (Exception e) {
//                                e.printStackTrace();
//                                        LOG.error("Failed to set the key columns, even after parsing. Columns were " + keyColumnsStack, e);
//                            }
                        } else if (tag.equals("map")) {
                            //if the tag was a map tag, then put the map
                            // elements into the map
//                                    setTypeMap(typeMap);
                        } else if (tag.equals("auto-increment")) {
                            metaData.setAutoIncrement(columnIndex, wasNull ? false : Boolean.parseBoolean(data));
                        } else if (tag.equals("case-sensitive")) {
                            metaData.setCaseSensitive(columnIndex, wasNull ? false : Boolean.parseBoolean(data));
                        } else if (tag.equals("currency")) {
                            metaData.setCurrency(columnIndex, wasNull ? false : Boolean.parseBoolean(data.trim()));
                        } else if (tag.equals("nullable")) {
                            metaData.setNullable(columnIndex, wasNull ? 0 : Integer.parseInt(data.trim()));
                        } else if (tag.equals("signed")) {
                            metaData.setSigned(columnIndex, wasNull ? false : Boolean.parseBoolean(data.trim()));
                        } else if (tag.equals("searchable")) {
                            metaData.setSearchable(columnIndex, wasNull ? false : Boolean.parseBoolean(data.trim()));
                        } else if (tag.equals("column-display-size")) {
                            metaData.setColumnDisplaySize(columnIndex, wasNull ? 255 : Integer.parseInt(data.trim()));
                        } else if (tag.equals("column-label")) {
                            metaData.setColumnLabel(columnIndex, wasNull ? null : data);
                        } else if (tag.equals("column-name")) {
                            metaData.setColumnName(columnIndex, data);
                        } else if (tag.equals("schema-name")) {
                            metaData.setSchemaName(columnIndex, wasNull ? null : data);
                        } else if (tag.equals("column-precision")) {
                            metaData.setPrecision(columnIndex, wasNull ? 0 : Integer.parseInt(data.trim()));
                        } else if (tag.equals("column-scale")) {
                            metaData.setScale(columnIndex, wasNull ? 0 : Integer.parseInt(data.trim()));
                        } else if (tag.equals("catalog-name")) {
                            metaData.setCatalogName(columnIndex, wasNull ? null : data);
                        } else if (tag.equals("column-type")) {
                            metaData.setColumnType(columnIndex, wasNull ? Types.VARCHAR : Integer.parseInt(data.trim()));
                        } else if (tag.equals("column-type-name")) {
                            metaData.setColumnTypeName(columnIndex, wasNull ? null : data);
                        } else if (tag.equals("metadata")) {
                            //drop all of the columns in the data table
                            //and rebuild them based on this meta-data
                            SwingUtilities.invokeAndWait(new Runnable() {
                                public void run() {
                                    table.clear();
                                    DataColumn[] cols = table.getColumns().toArray(new DataColumn[table.getColumns().size()]);
                                    for (DataColumn col : cols) {
                                        table.dropColumn(col.getName());
                                    }
                                    
                                    //time to rebuild
                                    try {
                                        for (int i=0; i= 100) {
                        doLoad(table, dataToLoad);
                        dataToLoad = new LinkedList();
                    }
                }
                
                /**
                 * @inheritDoc
                 */
                public void startDocument() throws SAXException {
//                            LOG.debug("Start of Document");
                }
                
                public void startElement(String uri, String localName, String qName, Attributes attributes)	throws SAXException {
                    //reset the wasNull flag
                    wasNull = false;
                    //push the element name onto the stack. In this way, when
                    // the characters method is called, I know what kind of data
                    //I'm dealing with.
                    String tag = qName.toLowerCase();
                    tagStack.push(tag);
                    try {
                        if (tag.equals("properties")) {
                            inProperties = true;
                            inMetaData = false;
                            inData = false;
                        } else if (tag.equals("metadata")) {
                            inProperties = false;
                            inMetaData = true;
                            inData = false;
                            metaData = new RowSetMetaDataImpl();
                        } else if (tag.equals("data")) {
                            inProperties = false;
                            inMetaData = false;
                            inData = true;
                            //construct the rowValues array
                            rowValues = new Object[metaData.getColumnCount()];
                        } else if (tag.equals("currentrow")) {
                            columnIndex = 1;
                            reinitRowValues();
                            currentRow++;
                        } else if (tag.equals("insertrow")) {
                            columnIndex = 1;
                            reinitRowValues();
                            currentRow++;
                        } else if (tag.equals("deleterow")) {
                            columnIndex = 1;
                            reinitRowValues();
                            currentRow++;
                        } else if (tag.equals("modifyrow")) {
                            columnIndex = 1;
                            reinitRowValues();
                            currentRow++;
                        }
                    } catch (Exception e) {
			LOG.log(Level.WARNING, "Error", e);
                    }
                }
                
                /**
                 * Utility method that clears out the rowValues array
                 */
                private void reinitRowValues() {
                    for (int i=0; i loadItems = (List)item.data;
                    for (RowLoadItem loadItem : loadItems) {
                        
                        DataRow row = table.appendRowNoEvent();
                        List cols = table.getColumns();
                        for (int i=0; i tag has been seen.
                     * This flag is reset to false whenever a new tag is started, but is set to true when
                     * the end of the  tag is found.
                     * Also, A single variable contains the results of the character data for the current tag.
                     * This variable is read after the end tag is found. You will find that all work is
                     * done after the entire element has been read (after the end tag).
                     */
                    
                    WebRowSetXMLHandler handler = new WebRowSetXMLHandler(table);
                    SAXParser parser = FACTORY.newSAXParser();
                    XMLReader xmlReader = parser.getXMLReader();
                    xmlReader.setProperty(
                            "http://xml.org/sax/properties/lexical-handler",
                            handler
                            );
                    
                    parser.parse(new InputSource(reader), handler );
                } catch (Exception e) {
		    LOG.log(Level.WARNING, "Error", e);
                    throw new SQLException("Error while parsing a the xml document for a WebRowSetDataProvider");
                }
            }
        };
        
        
    }
/*
    public static void main(String... args) {
        DataSource ds = new DataSource();
        DataTable dt = ds.createTable();
        dt.setName("Rowset");
        DataProvider dp = new WebRowSetDataProvider();
        dt.setDataProvider(dp);
        JFrame frame = new JFrame();
    //   JTable table = new JTable();
 //
        //Binding b = BindingFactory.bind(table, dt);
 
        TabularDataModelAdapter adapter = new TabularDataModelAdapter(dt);
 
 
     //   JNTable table = new JNTable();
   //     new DirectTableBinding(table.getTable(),adapter);
 
        frame.getContentPane().setLayout(new BorderLayout());
        frame.getContentPane().add(new JScrollPane(table), BorderLayout.CENTER);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(800,600);
        frame.setVisible(true);
        dt.load();
//        dt.loadAndWait();
//        System.out.println(dt.getRows().size());
//        List cols = dt.getColumns();
//        for (DataColumn col : cols) {
//            System.out.println(col.getName());
//        }
    }
 
 */
    
    public URL getUrl() {
        return url;
    }
    
    public void setUrl(URL url) {
        this.url = url;
    }
    
    public Runnable getCompletionRunnable() {
        return completionRunnable;
    }
    
    public void setCompletionRunnable(Runnable completionRunnable) {
        this.completionRunnable = completionRunnable;
    }
    
    public Runnable getMetadataCompleteRunnable() {
        return metadataCompleteRunnable;
    }
    
    public void setMetadataCompleteRunnable(Runnable metadataCompleteRunnable) {
        this.metadataCompleteRunnable = metadataCompleteRunnable;
    }
    
    
    
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy