Package org.apache.harmony.sql.internal.rowset

Source Code of org.apache.harmony.sql.internal.rowset.CachedRowSetWriter

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.harmony.sql.internal.rowset;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.sql.RowSetInternal;
import javax.sql.RowSetWriter;
import javax.sql.rowset.CachedRowSet;
import javax.sql.rowset.spi.SyncProviderException;

public class CachedRowSetWriter implements RowSetWriter {

    private CachedRowSet originalRowSet;

    private CachedRowSetImpl currentRowSet;

    private Connection originalConnection;

    private String tableName;

    private String[] colNames;

    private int columnCount;

    public void setConnection(Connection conn) {
        originalConnection = conn;
    }

    public Connection getConnection() {
        return originalConnection;
    }

    /**
     * TODO add transaction
     */
    public boolean writeData(RowSetInternal theRowSet) throws SQLException {
        initial(theRowSet);
        // analyse every row and do responsible task.
        currentRowSet.beforeFirst();// currentRowSet.first();
        originalRowSet.beforeFirst();// originalRowSet.first();
        while (currentRowSet.next()) {
            if (currentRowSet.rowInserted()) {
                insertCurrentRow();
            } else if (currentRowSet.rowDeleted()) {
                if (isConflictExistForCurrentRow()) {
                    // TODO: conflict exists, should throw SyncProviderException
                    throw new SyncProviderException();
                }

                deleteCurrentRow();

            } else if (currentRowSet.rowUpdated()) {
                if (isConflictExistForCurrentRow()) {
                    // TODO: conflict exists, should throw SyncProviderException
                    throw new SyncProviderException();
                }
               
                updateCurrentRow();
            }
        }
        // TODO release resource
        return true;
    }

    /**
     * Insert the RowSet's current row to DB
     *
     * @throws SQLException
     */
    @SuppressWarnings("nls")
    private void insertCurrentRow() throws SQLException {
        /*
         * the first step: generate the insert SQL
         */
        StringBuffer insertSQL = new StringBuffer("INSERT INTO " + tableName
                + "(");
        StringBuffer insertColNames = new StringBuffer();
        StringBuffer insertPlaceholder = new StringBuffer();
        Object[] insertColValues = new Object[columnCount];

        int updateCount = 0;
        for (int i = 1; i <= columnCount; i++) {
            boolean isColUpdate = currentRowSet.columnUpdated(i);
            if (isColUpdate) {
                insertColNames.append(colNames[i - 1] + ",");
                insertPlaceholder.append("?,");
                insertColValues[updateCount] = currentRowSet.getObject(i);
                updateCount++;
            }
        }
        if (updateCount == 0) {
            return;
        }

        insertSQL.append(subStringN(insertColNames.toString(), 1));
        insertSQL.append(") values (");
        insertSQL.append(subStringN(insertPlaceholder.toString(), 1));
        insertSQL.append(")");

        /*
         * the second step: execute SQL
         */
        PreparedStatement preSt = getConnection().prepareStatement(
                insertSQL.toString());
        for (int i = 0; i < updateCount; i++) {
            preSt.setObject(i + 1, insertColValues[i]);
        }
        try {
            preSt.executeUpdate();
        } catch (SQLException e) {
            // TODO generate SyncProviderException
            throw new SyncProviderException();
        } finally {
            preSt.close();
        }
    }

    /**
     * Delete the current row from DB
     *
     * @throws SQLException
     */
    private void deleteCurrentRow() throws SQLException {
        /*
         * the first step: generate the delete SQL
         */
        StringBuffer deleteSQL = new StringBuffer("DELETE FROM " + tableName //$NON-NLS-1$
                + " WHERE "); //$NON-NLS-1$
        deleteSQL.append(generateQueryCondition());

        /*
         * the second step: execute SQL
         */
        PreparedStatement preSt = getConnection().prepareStatement(
                deleteSQL.toString());
        fillParamInPreStatement(preSt, 1);
        preSt.executeUpdate();
    }

    /**
     * Update the current row to DB
     *
     * @throws SQLException
     */
    @SuppressWarnings("nls")
    private void updateCurrentRow() throws SQLException {
        /*
         * the first step: generate the delete SQL
         */
        StringBuffer updateSQL = new StringBuffer("UPDATE " + tableName
                + " SET ");
        StringBuffer updateCols = new StringBuffer();
        Object[] updateColValues = new Object[columnCount];
        int[] updateColIndexs = new int[columnCount];

        int updateCount = 0;
        for (int i = 1; i <= columnCount; i++) {
            boolean isColUpdate = currentRowSet.columnUpdated(i);
            if (isColUpdate) {
                updateCols.append(colNames[i - 1] + " = ?, ");
                updateColValues[updateCount] = currentRowSet.getObject(i);
                updateColIndexs[updateCount] = i;
                updateCount++;
            }
        }
        if (updateCount == 0) {
            return;
        }
        updateSQL.append(subStringN(updateCols.toString(), 2));
        updateSQL.append(" WHERE ");
        updateSQL.append(generateQueryCondition());

        /*
         * the second step: execute SQL
         */
        PreparedStatement preSt = getConnection().prepareStatement(
                updateSQL.toString());
        // the SET part of SQL
        for (int i = 0; i < updateCount; i++) {
            if (updateColValues[i] == null) {
                preSt.setNull(i + 1, currentRowSet.getMetaData().getColumnType(
                        updateColIndexs[i]));
            } else {
                preSt.setObject(i + 1, updateColValues[i]);
            }
        }
        // the WHERE part of SQL
        fillParamInPreStatement(preSt, updateCount + 1);
        try {
            preSt.executeUpdate();
        } catch (SQLException e) {
            // TODO generate SyncProviderException
            throw new SyncProviderException();
        } finally {
            preSt.close();
        }
    }

    private void initial(RowSetInternal theRowSet) throws SQLException {
        currentRowSet = (CachedRowSetImpl) theRowSet;
        // initial environment
        originalRowSet = (CachedRowSet) currentRowSet.getOriginal();
        // originalConnection = currentRowSet.getConnection();
        tableName = currentRowSet.getTableName();
        columnCount = currentRowSet.getMetaData().getColumnCount();
        colNames = new String[columnCount];
        for (int i = 1; i <= columnCount; i++) {
            colNames[i - 1] = currentRowSet.getMetaData().getColumnName(i);
        }
    }

    /**
     * Compare the current row's data between database and CachedRowSet to check
     * whether it has been changed in database.
     *
     * @return if conflict exists, return true; else, return false
     * @throws SQLException
     */
    private boolean isConflictExistForCurrentRow() throws SQLException {
        boolean isExist = true;
        originalRowSet.absolute(currentRowSet.getRow()); // the original data

        StringBuffer querySQL = new StringBuffer("SELECT COUNT(*) FROM " //$NON-NLS-1$
                + tableName + " WHERE "); //$NON-NLS-1$
        querySQL.append(generateQueryCondition());

        PreparedStatement preSt = getConnection().prepareStatement(
                querySQL.toString());
        fillParamInPreStatement(preSt, 1);
        ResultSet queryRs = preSt.executeQuery();
        if (queryRs.next()) {
            if (queryRs.getInt(1) == 1) {
                isExist = false;
            }
        }
        queryRs.close();
        preSt.close();

        return isExist;
    }

    /**
     * Generate the query condition after the keyword "WHERE" in SQL. Expression
     * likes as: COLUMN1 = ? AND COLUMN2 = ?
     *
     * @return the SQL query expression
     */
    @SuppressWarnings("nls")
    private String generateQueryCondition() throws SQLException {
        StringBuffer queryCondtion = new StringBuffer(" ");
        for (int i = 0; i < colNames.length; i++) {
            if (originalRowSet.getObject(i + 1) == null) {
                queryCondtion.append(colNames[i] + " is null ");
            } else {
                queryCondtion.append(colNames[i] + " = ? ");
            }
            if (i != colNames.length - 1) {
                queryCondtion.append(" and ");
            }
        }
        return queryCondtion.toString();
    }

    /**
     * Fill all the parameters in PreparedStatement
     *
     * @param preSt
     *            PreparedStatement
     * @param fromIndex
     *            It must be greater than 0
     * @throws SQLException
     */
    private void fillParamInPreStatement(PreparedStatement preSt, int fromIndex)
            throws SQLException {
        int notNullCount = fromIndex;
        for (int i = 1; i <= columnCount; i++) {
            if (originalRowSet.getObject(i) != null) {
                preSt.setObject(notNullCount, originalRowSet.getObject(i));
                notNullCount++;
            }
        }
    }

    private String subStringN(String input, int n) {
        return input.substring(0, input.length() - n);
    }
}
TOP

Related Classes of org.apache.harmony.sql.internal.rowset.CachedRowSetWriter

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.