/* * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.rowset.internal; import java.sql.*;import javax.sql.*;import java.util.*;import java.math.BigDecimal; import javax.sql.rowset.*;import javax.sql.rowset.spi.*; import com.sun.rowset.*;import java.io.IOException;import java.io.ObjectInputStream; /** * There will be two sets of data which will be maintained by the rowset at the * time of synchronization. The <code>SyncProvider</code> will utilize the * <code>SyncResolver</code> to synchronize the changes back to database. */public class SyncResolverImpl extends CachedRowSetImpl implements SyncResolver { /** * This CachedRowSet object will encapsulate a rowset * which will be sync'ed with the datasource but will * contain values in rows where there is conflict. * For rows other than conflict, it will *not* contain * any data. For rows containing conflict it will * return either of the three values set by SyncResolver.*_CONFLICT * from getStatus() */ private CachedRowSetImpl crsRes; /** * This is the actual CachedRowSet object * which is being synchronized back to * datasource. */ private CachedRowSetImpl crsSync; /** * This ArrayList will contain the status of a row * from the SyncResolver.* values else it will be null. */ private ArrayList stats; /** * The RowSetWriter associated with the original * CachedRowSet object which is being synchronized. */ private CachedRowSetWriter crw; /** * Row number identifier */ private int rowStatus; /** * This will contain the size of the <code>CachedRowSet</code> object */ private int sz; /** * The <code>Connection</code> handle used to synchronize the changes * back to datasource. This is the same connection handle as was passed * to the CachedRowSet while fetching the data. */ private transient Connection con; /** * The <code>CachedRowSet</code> object which will encapsulate * a row at any time. This will be built from CachedRowSet and * SyncResolver values. Synchronization takes place on a row by * row basis encapsulated as a CahedRowSet. */ private CachedRowSet row; private JdbcRowSetResourceBundle resBundle; /** * Public constructor */ public SyncResolverImpl() throws SQLException { try { crsSync = new CachedRowSetImpl(); crsRes = new CachedRowSetImpl(); crw = new CachedRowSetWriter(); row = new CachedRowSetImpl(); rowStatus = 1; try { resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); } catch(IOException ioe) { throw new RuntimeException(ioe); } } catch(SQLException sqle) { } } /** * Retrieves the conflict status of the current row of this * <code>SyncResolver</code>, which indicates the operationthe <code>RowSet</code> * object was attempting when the conflict occurred. * * @return one of the following constants: * <code>SyncResolver.UPDATE_ROW_CONFLICT</code>, * <code>SyncResolver.DELETE_ROW_CONFLICT</code>, or * <code>SyncResolver.INSERT_ROW_CONFLICT</code> */ public int getStatus() { return ((Integer)stats.get(rowStatus-1)).intValue(); } /** * Retrieves the value in the designated column in the current row of this * <code>SyncResolver</code> object, which is the value that caused a conflict. * * @param index <code>int</code> designating the column in this row of this * <code>SyncResolver</code> object from which to retrieve the value * causing a conflict */ public Object getConflictValue(int index) throws SQLException { try { return crsRes.getObject(index); } catch(SQLException sqle) { throw new SQLException(sqle.getMessage()); } } /** * Retrieves the value in the designated column in the current row of this * <code>SyncResolver</code> object, which is the value that caused a conflict. * * @param columnName a <code>String</code> object designating the column in this row of this * <code>SyncResolver</code> object from which to retrieve the value * causing a conflict */ public Object getConflictValue(String columnName) throws SQLException { try { return crsRes.getObject(columnName); } catch(SQLException sqle) { throw new SQLException(sqle.getMessage()); } } /** * Sets <i>obj</i> as the value in column <i>index</i> in the current row of the * <code>RowSet</code> object. This value is the resolved value that is to be * persisted in the data source. * * @param index an <code>int</code> giving the number of the column into which to * set the value to be persisted * @param obj an <code>Object</code> that is the value to be set in the data source */ public void setResolvedValue(int index, Object obj) throws SQLException { // modify method to throw SQLException in spec /** * When a value is resolved properly make it to null * inside crsRes for that column. * * For more than one conflicts in the row, * check for the last resolved value of the current row * (Note: it can be resolved randomly for same row) * then sync back immediately. **/ try { // check whether the index is in range if(index<=0 || index > crsSync.getMetaData().getColumnCount() ) { throw new SQLException(resBundle.handleGetObject("syncrsimpl.indexval").toString()+ index); } // check whether index col is in conflict if(crsRes.getObject(index) == null) { throw new SQLException(resBundle.handleGetObject("syncrsimpl.noconflict").toString()); } } catch (SQLException sqle) { // modify method to throw for SQLException throw new SQLException(sqle.getMessage()); } try { boolean bool = true; /** Check resolved value to be either of conflict * or in rowset else throw sql exception. * If we allow a value other than that in CachedRowSet or * datasource we will end up in looping the loop of exceptions. **/ if( ((crsSync.getObject(index)).toString()).equals(obj.toString()) || ((crsRes.getObject(index)).toString()).equals(obj.toString()) ) { /** * Check whether this is the only conflict in the row. * If yes, synchronize this row back * which has been resolved, else wait * for all conflicts of current row to be resolved * * Step 1: Update crsRes and make the index col as null * i.e. resolved * crsRes.updateObject(index, obj); **/ crsRes.updateNull(index); crsRes.updateRow(); /** * Step 2: Change the value in the CachedRowSetImpl object * crsSync.updateObject(index, obj); * crsSync.updateRow(); **/ if(row.size() != 1) { row = buildCachedRow(); } row.updateObject(index, obj); row.updateRow(); for(int j=1; j < crsRes.getMetaData().getColumnCount(); j++) { if(crsRes.getObject(j) != null) { bool = false; break; // break out of loop and wait for other cols // in same row to get resolved } //end if } //end for if(bool) { /** * sync data back using CachedRowSetWriter * construct the present row and pass it to the writer * to write back to db. **/ try { /** * Note : The use of CachedRowSetWriter to get *same* Connection handle. * The CachedRowSetWriter uses the connection handle * from the reader, Hence will use the same connection handle * as of original CachedRowSetImpl **/ writeData(row); //crw.writeData( (RowSetInternal)crsRow); //System.out.printlnt.println("12"); } catch(SyncProviderException spe) { /** * This will occur if db is not allowing * even after resolving the conflicts * due to some reasons. * Also will prevent from going into a loop of SPE's **/ throw new SQLException(resBundle.handleGetObject("syncrsimpl.syncnotpos").toString()); } } //end if(bool) } else { throw new SQLException(resBundle.handleGetObject("syncrsimpl.valtores").toString()); } //end if (crs.getObject ...) block } catch(SQLException sqle) { throw new SQLException(sqle.getMessage()); } } /** * This passes a CachedRowSet as a row the the CachedRowSetWriter * after the values have been resolved, back to the datasource. * * @param row a <code>CachedRowSet</code> object which will hold the * values of a particular row after they have been resolved by * the user to synchronize back to datasource. * @throws SQLException if synchronization does not happen properly * maybe beacuse <code>Connection</code> has timed out. **/ private void writeData(CachedRowSet row) throws SQLException { crw.updateResolvedConflictToDB(row, crw.getReader().connect((RowSetInternal)crsSync)); } /** * This function builds a row as a <code>CachedRowSet</code> object * which has been resolved and is ready to be synchrinized to the datasource * * @throws SQLException if there is problem in building * the metadata of the row. **/ private CachedRowSet buildCachedRow() throws SQLException { int iColCount; CachedRowSetImpl crsRow = new CachedRowSetImpl(); RowSetMetaDataImpl rsmd = new RowSetMetaDataImpl(); RowSetMetaDataImpl rsmdWrite = (RowSetMetaDataImpl)crsSync.getMetaData(); RowSetMetaDataImpl rsmdRow = new RowSetMetaDataImpl(); iColCount = rsmdWrite.getColumnCount(); rsmdRow.setColumnCount(iColCount); for(int i =1;i<=iColCount;i++) { rsmdRow.setColumnType(i,rsmdWrite.getColumnType(i)); rsmdRow.setColumnName(i,rsmdWrite.getColumnName(i)); rsmdRow.setNullable(i,ResultSetMetaData.columnNullableUnknown); try { rsmdRow.setCatalogName(i, rsmdWrite.getCatalogName(i)); rsmdRow.setSchemaName(i, rsmdWrite.getSchemaName(i)); } catch(SQLException e) { e.printStackTrace(); } } //end for crsRow.setMetaData(rsmdRow); crsRow.moveToInsertRow(); for(int col=1;col<=crsSync.getMetaData().getColumnCount();col++) { crsRow.updateObject(col, crsSync.getObject(col)); } crsRow.insertRow(); crsRow.moveToCurrentRow(); crsRow.absolute(1); crsRow.setOriginalRow(); try { crsRow.setUrl(crsSync.getUrl()); } catch(SQLException sqle) { } try { crsRow.setDataSourceName(crsSync.getCommand()); } catch(SQLException sqle) { } try { if(crsSync.getTableName()!= null){ crsRow.setTableName(crsSync.getTableName()); } } catch(SQLException sqle) { } try { if(crsSync.getCommand() != null) crsRow.setCommand(crsSync.getCommand()); } catch(SQLException sqle) { } try { crsRow.setKeyColumns(crsSync.getKeyColumns()); } catch(SQLException sqle) { } return crsRow; } /** * Sets <i>obj</i> as the value in column <i>columnName</i> in the current row of the * <code>RowSet</code> object. This value is the resolved value that is to be * persisted in the data source. * * @param columnName a <code>String</code> object giving the name of the column * into which to set the value to be persisted * @param obj an <code>Object</code> that is the value to be set in the data source */ public void setResolvedValue(String columnName, Object obj) throws SQLException { // modify method to throw SQLException in spec // %%% Missing implementation! } /** * This function is package private, * i.e. cannot be accesses outside this package. * This is used to set the actual CachedRowSet * which is being synchronized to the database **/ void setCachedRowSet(CachedRowSet crs) { crsSync = (CachedRowSetImpl)crs; } /** * This function is package private, * i.e. cannot be accesses outside this package. * This is used to set the CachedRowSet formed * with conflict values. **/ void setCachedRowSetResolver(CachedRowSet crs){ try { crsRes = (CachedRowSetImpl)crs; crsRes.afterLast(); sz = crsRes.size(); } catch (SQLException sqle) { // do nothing } } /** * This function is package private, * i.e. cannot be accesses outside this package. * This is used to set the status of each row * to either of the values SyncResolver.*_CONFLICT **/ void setStatus(ArrayList status){ stats = status; } /** * This function is package private, * i.e. cannot be accesses outside this package. * This is used to set the handle to the writer object * which will write the resolved values back to datasource **/ void setCachedRowSetWriter(CachedRowSetWriter CRWriter) { crw = CRWriter; } /** * Moves the cursor down one row from its current position. A <code>SyncResolver</code> * cursor is initially positioned before the first conflict row; the first call to the * method <code>nextConflict()</code> makes the first conflict row the current row; * the second call makes the second conflict row the current row, and so on. * <p> * If an input stream is open for the current row, a call to the method next will * implicitly close it. A <code>SyncResolver</code> object's warning chain is cleared * when a new row * * @return true if the new current row is valid; false if there are no more rows * @throws SQLException if a database access occurs * */ public boolean nextConflict() throws SQLException { /** * The next() method will hop from * one conflict to another * * Internally do a crs.next() until * next conflict. **/ boolean bool = false; crsSync.setShowDeleted(true); while(crsSync.next()) { crsRes.previous(); rowStatus++; //sz--; if((rowStatus-1) >= stats.size()) { bool = false; break; } if(((Integer)stats.get(rowStatus-1)).intValue() == SyncResolver.NO_ROW_CONFLICT) { // do nothing // bool remains as false ; } else { bool = true; break; } //end if } //end while crsSync.setShowDeleted(false); return bool; } // end next() method /** * Moves the cursor to the previous conflict row in this <code>SyncResolver</code> object. * * @return <code>true</code> if the cursor is on a valid row; <code>false</code> * if it is off the result setLines 1–500 of 4860. Load more
/* * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.rowset.internal; import java.sql.*; import javax.sql.*; import java.util.*; import java.math.BigDecimal; import javax.sql.rowset.*; import javax.sql.rowset.spi.*; import com.sun.rowset.*; import java.io.IOException; import java.io.ObjectInputStream; /** * There will be two sets of data which will be maintained by the rowset at the * time of synchronization. The <code>SyncProvider</code> will utilize the * <code>SyncResolver</code> to synchronize the changes back to database. */ public class SyncResolverImpl extends CachedRowSetImpl implements SyncResolver { /** * This CachedRowSet object will encapsulate a rowset * which will be sync'ed with the datasource but will * contain values in rows where there is conflict. * For rows other than conflict, it will *not* contain * any data. For rows containing conflict it will * return either of the three values set by SyncResolver.*_CONFLICT * from getStatus() */ private CachedRowSetImpl crsRes; /** * This is the actual CachedRowSet object * which is being synchronized back to * datasource. */ private CachedRowSetImpl crsSync; /** * This ArrayList will contain the status of a row * from the SyncResolver.* values else it will be null. */ private ArrayList stats; /** * The RowSetWriter associated with the original * CachedRowSet object which is being synchronized. */ private CachedRowSetWriter crw; /** * Row number identifier */ private int rowStatus; /** * This will contain the size of the <code>CachedRowSet</code> object */ private int sz; /** * The <code>Connection</code> handle used to synchronize the changes * back to datasource. This is the same connection handle as was passed * to the CachedRowSet while fetching the data. */ private transient Connection con; /** * The <code>CachedRowSet</code> object which will encapsulate * a row at any time. This will be built from CachedRowSet and * SyncResolver values. Synchronization takes place on a row by * row basis encapsulated as a CahedRowSet. */ private CachedRowSet row; private JdbcRowSetResourceBundle resBundle; /** * Public constructor */ public SyncResolverImpl() throws SQLException { try { crsSync = new CachedRowSetImpl(); crsRes = new CachedRowSetImpl(); crw = new CachedRowSetWriter(); row = new CachedRowSetImpl(); rowStatus = 1; try { resBundle = JdbcRowSetResourceBundle.getJdbcRowSetResourceBundle(); } catch(IOException ioe) { throw new RuntimeException(ioe); } } catch(SQLException sqle) { } } /** * Retrieves the conflict status of the current row of this * <code>SyncResolver</code>, which indicates the operationthe <code>RowSet</code> * object was attempting when the conflict occurred. * * @return one of the following constants: * <code>SyncResolver.UPDATE_ROW_CONFLICT</code>, * <code>SyncResolver.DELETE_ROW_CONFLICT</code>, or * <code>SyncResolver.INSERT_ROW_CONFLICT</code> */ public int getStatus() { return ((Integer)stats.get(rowStatus-1)).intValue(); } /** * Retrieves the value in the designated column in the current row of this * <code>SyncResolver</code> object, which is the value that caused a conflict. * * @param index <code>int</code> designating the column in this row of this * <code>SyncResolver</code> object from which to retrieve the value * causing a conflict */ public Object getConflictValue(int index) throws SQLException { try { return crsRes.getObject(index); } catch(SQLException sqle) { throw new SQLException(sqle.getMessage()); } } /** * Retrieves the value in the designated column in the current row of this * <code>SyncResolver</code> object, which is the value that caused a conflict. * * @param columnName a <code>String</code> object designating the column in this row of this * <code>SyncResolver</code> object from which to retrieve the value * causing a conflict */ public Object getConflictValue(String columnName) throws SQLException { try { return crsRes.getObject(columnName); } catch(SQLException sqle) { throw new SQLException(sqle.getMessage()); } } /** * Sets <i>obj</i> as the value in column <i>index</i> in the current row of the * <code>RowSet</code> object. This value is the resolved value that is to be * persisted in the data source. * * @param index an <code>int</code> giving the number of the column into which to * set the value to be persisted * @param obj an <code>Object</code> that is the value to be set in the data source */ public void setResolvedValue(int index, Object obj) throws SQLException { // modify method to throw SQLException in spec /** * When a value is resolved properly make it to null * inside crsRes for that column. * * For more than one conflicts in the row, * check for the last resolved value of the current row * (Note: it can be resolved randomly for same row) * then sync back immediately. **/ try { // check whether the index is in range if(index<=0 || index > crsSync.getMetaData().getColumnCount() ) { throw new SQLException(resBundle.handleGetObject("syncrsimpl.indexval").toString()+ index); } // check whether index col is in conflict if(crsRes.getObject(index) == null) { throw new SQLException(resBundle.handleGetObject("syncrsimpl.noconflict").toString()); } } catch (SQLException sqle) { // modify method to throw for SQLException throw new SQLException(sqle.getMessage()); } try { boolean bool = true; /** Check resolved value to be either of conflict * or in rowset else throw sql exception. * If we allow a value other than that in CachedRowSet or * datasource we will end up in looping the loop of exceptions. **/ if( ((crsSync.getObject(index)).toString()).equals(obj.toString()) || ((crsRes.getObject(index)).toString()).equals(obj.toString()) ) { /** * Check whether this is the only conflict in the row. * If yes, synchronize this row back * which has been resolved, else wait * for all conflicts of current row to be resolved * * Step 1: Update crsRes and make the index col as null * i.e. resolved * crsRes.updateObject(index, obj); **/ crsRes.updateNull(index); crsRes.updateRow(); /** * Step 2: Change the value in the CachedRowSetImpl object * crsSync.updateObject(index, obj); * crsSync.updateRow(); **/ if(row.size() != 1) { row = buildCachedRow(); } row.updateObject(index, obj); row.updateRow(); for(int j=1; j < crsRes.getMetaData().getColumnCount(); j++) { if(crsRes.getObject(j) != null) { bool = false; break; // break out of loop and wait for other cols // in same row to get resolved } //end if } //end for if(bool) { /** * sync data back using CachedRowSetWriter * construct the present row and pass it to the writer * to write back to db. **/ try { /** * Note : The use of CachedRowSetWriter to get *same* Connection handle. * The CachedRowSetWriter uses the connection handle * from the reader, Hence will use the same connection handle * as of original CachedRowSetImpl **/ writeData(row); //crw.writeData( (RowSetInternal)crsRow); //System.out.printlnt.println("12"); } catch(SyncProviderException spe) { /** * This will occur if db is not allowing * even after resolving the conflicts * due to some reasons. * Also will prevent from going into a loop of SPE's **/ throw new SQLException(resBundle.handleGetObject("syncrsimpl.syncnotpos").toString()); } } //end if(bool) } else { throw new SQLException(resBundle.handleGetObject("syncrsimpl.valtores").toString()); } //end if (crs.getObject ...) block } catch(SQLException sqle) { throw new SQLException(sqle.getMessage()); } } /** * This passes a CachedRowSet as a row the the CachedRowSetWriter * after the values have been resolved, back to the datasource. * * @param row a <code>CachedRowSet</code> object which will hold the * values of a particular row after they have been resolved by * the user to synchronize back to datasource. * @throws SQLException if synchronization does not happen properly * maybe beacuse <code>Connection</code> has timed out. **/ private void writeData(CachedRowSet row) throws SQLException { crw.updateResolvedConflictToDB(row, crw.getReader().connect((RowSetInternal)crsSync)); } /** * This function builds a row as a <code>CachedRowSet</code> object * which has been resolved and is ready to be synchrinized to the datasource * * @throws SQLException if there is problem in building * the metadata of the row. **/ private CachedRowSet buildCachedRow() throws SQLException { int iColCount; CachedRowSetImpl crsRow = new CachedRowSetImpl(); RowSetMetaDataImpl rsmd = new RowSetMetaDataImpl(); RowSetMetaDataImpl rsmdWrite = (RowSetMetaDataImpl)crsSync.getMetaData(); RowSetMetaDataImpl rsmdRow = new RowSetMetaDataImpl(); iColCount = rsmdWrite.getColumnCount(); rsmdRow.setColumnCount(iColCount); for(int i =1;i<=iColCount;i++) { rsmdRow.setColumnType(i,rsmdWrite.getColumnType(i)); rsmdRow.setColumnName(i,rsmdWrite.getColumnName(i)); rsmdRow.setNullable(i,ResultSetMetaData.columnNullableUnknown); try { rsmdRow.setCatalogName(i, rsmdWrite.getCatalogName(i)); rsmdRow.setSchemaName(i, rsmdWrite.getSchemaName(i)); } catch(SQLException e) { e.printStackTrace(); } } //end for crsRow.setMetaData(rsmdRow); crsRow.moveToInsertRow(); for(int col=1;col<=crsSync.getMetaData().getColumnCount();col++) { crsRow.updateObject(col, crsSync.getObject(col)); } crsRow.insertRow(); crsRow.moveToCurrentRow(); crsRow.absolute(1); crsRow.setOriginalRow(); try { crsRow.setUrl(crsSync.getUrl()); } catch(SQLException sqle) { } try { crsRow.setDataSourceName(crsSync.getCommand()); } catch(SQLException sqle) { } try { if(crsSync.getTableName()!= null){ crsRow.setTableName(crsSync.getTableName()); } } catch(SQLException sqle) { } try { if(crsSync.getCommand() != null) crsRow.setCommand(crsSync.getCommand()); } catch(SQLException sqle) { } try { crsRow.setKeyColumns(crsSync.getKeyColumns()); } catch(SQLException sqle) { } return crsRow; } /** * Sets <i>obj</i> as the value in column <i>columnName</i> in the current row of the * <code>RowSet</code> object. This value is the resolved value that is to be * persisted in the data source. * * @param columnName a <code>String</code> object giving the name of the column * into which to set the value to be persisted * @param obj an <code>Object</code> that is the value to be set in the data source */ public void setResolvedValue(String columnName, Object obj) throws SQLException { // modify method to throw SQLException in spec // %%% Missing implementation! } /** * This function is package private, * i.e. cannot be accesses outside this package. * This is used to set the actual CachedRowSet * which is being synchronized to the database **/ void setCachedRowSet(CachedRowSet crs) { crsSync = (CachedRowSetImpl)crs; } /** * This function is package private, * i.e. cannot be accesses outside this package. * This is used to set the CachedRowSet formed * with conflict values. **/ void setCachedRowSetResolver(CachedRowSet crs){ try { crsRes = (CachedRowSetImpl)crs; crsRes.afterLast(); sz = crsRes.size(); } catch (SQLException sqle) { // do nothing } } /** * This function is package private, * i.e. cannot be accesses outside this package. * This is used to set the status of each row * to either of the values SyncResolver.*_CONFLICT **/ void setStatus(ArrayList status){ stats = status; } /** * This function is package private, * i.e. cannot be accesses outside this package. * This is used to set the handle to the writer object * which will write the resolved values back to datasource **/ void setCachedRowSetWriter(CachedRowSetWriter CRWriter) { crw = CRWriter; } /** * Moves the cursor down one row from its current position. A <code>SyncResolver</code> * cursor is initially positioned before the first conflict row; the first call to the * method <code>nextConflict()</code> makes the first conflict row the current row; * the second call makes the second conflict row the current row, and so on. * <p> * If an input stream is open for the current row, a call to the method next will * implicitly close it. A <code>SyncResolver</code> object's warning chain is cleared * when a new row * * @return true if the new current row is valid; false if there are no more rows * @throws SQLException if a database access occurs * */ public boolean nextConflict() throws SQLException { /** * The next() method will hop from * one conflict to another * * Internally do a crs.next() until * next conflict. **/ boolean bool = false; crsSync.setShowDeleted(true); while(crsSync.next()) { crsRes.previous(); rowStatus++; //sz--; if((rowStatus-1) >= stats.size()) { bool = false; break; } if(((Integer)stats.get(rowStatus-1)).intValue() == SyncResolver.NO_ROW_CONFLICT) { // do nothing // bool remains as false ; } else { bool = true; break; } //end if } //end while crsSync.setShowDeleted(false); return bool; } // end next() method /** * Moves the cursor to the previous conflict row in this <code>SyncResolver</code> object. * * @return <code>true</code> if the cursor is on a valid row; <code>false</code> * if it is off the result set