DataRow.java
上传用户:zhengdagz
上传日期:2014-03-06
资源大小:1956k
文件大小:25k
源码类别:

xml/soap/webservice

开发平台:

Java

  1. /*
  2.  * $Id: DataRow.java,v 1.9 2005/10/15 11:43:19 pdoubleya Exp $
  3.  *
  4.  * Copyright 2005 Sun Microsystems, Inc., 4150 Network Circle,
  5.  * Santa Clara, California 95054, U.S.A. All rights reserved.
  6.  *
  7.  * This library is free software; you can redistribute it and/or
  8.  * modify it under the terms of the GNU Lesser General Public
  9.  * License as published by the Free Software Foundation; either
  10.  * version 2.1 of the License, or (at your option) any later version.
  11.  *
  12.  * This library is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  * Lesser General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU Lesser General Public
  18.  * License along with this library; if not, write to the Free Software
  19.  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  20.  */
  21. package org.jdesktop.dataset;
  22. import static org.jdesktop.dataset.event.RowChangeEvent.EventType.*;
  23. import java.beans.PropertyChangeListener;
  24. import java.beans.PropertyChangeSupport;
  25. import java.util.Comparator;
  26. import java.util.HashMap;
  27. import java.util.List;
  28. import java.util.Map;
  29. import javax.swing.event.EventListenerList;
  30. import org.jdesktop.dataset.event.DataTableListener;
  31. import org.jdesktop.dataset.event.RowChangeEvent;
  32. /**
  33.  * <p>A <CODE>DataRow</CODE> contains a set of values within a {@link DataTable}; the <CODE>DataTable</CODE> defines
  34.  * the {@link DataColumn DataColumns} in each row, and each row always has a value for each <CODE>DataColumn</CODE>. The
  35.  * intersection of a <CODE>DataColumn</CODE> in a <CODE>DataRow</CODE> is called a cell, though cells are not exposed
  36.  * in the <CODE>DataRow's</CODE> API. A <CODE>DataRow</CODE> always belongs to a <CODE>DataTable</CODE>; rows are added to a table using the
  37.  * table's {@link DataTable#appendRow()} or {@link DataTable#appendRowNoEvent()} methods and cannot be instantiated
  38.  * directly. Values in each cell can be changed using the {@link #setValue(String colName, Object value)} or
  39.  * {@link #setValue(DataColumn col, Object value)} methods; values are always <CODE>Objects</CODE>.
  40.  * 
  41.  * <p>A <CODE>DataRow</CODE> always has a status, whose state is relative to the persistence
  42.  * mechanism for the table. Statuses are returned using the row's <CODE>DataRowStatus</CODE> enumeration,
  43.  * through {@link getStatus()} and can be changed using {@link #setStatus(DataRowStatus)}. Statuses
  44.  * are normally managed without developer intervention. Normally, when rows are loaded from a persistent store, they
  45.  * have a status <CODE>UNCHANGED</CODE>, which indicates that a {@link DataProvider} does not need to synchronize
  46.  * them on the next {@link DataTable#save()} operation. A status of <CODE>INSERTED</CODE> means the row was added to the
  47.  * table and should be added to the persistent store on the next {@link DataTable#save()}, <CODE>UPDATED</CODE> means changes
  48.  * to a row loaded from the persistent store must be written back to the store, and <CODE>DELETED</CODE>
  49.  * means the row should be removed from the store. Adding a row programmatically through the table's
  50.  * {@link DataTable#appendRow()} or {@link DataTable#appendRowNoEvent()} methods gives the row a status of <CODE>INSERTED</CODE>.
  51.  * 
  52.  * <p>Each cell in a row can hold a reference value and a current value. The reference value is normally
  53.  * the value as last read from the persistent store; this value is usually not modified programatically,
  54.  * but may be overridden by a <CODE>DataProvider</CODE> if the row is re-read from the data store. The
  55.  * {@link #setReferenceValue(DataColumn col, Object refValue)} method changes the reference value for a cell.
  56.  * The current value is the value which is normally changed programmatically or through a user interface. When the current
  57.  * value is different than the reference value, we say the cell has changed. If the row had <CODE>UNCHANGED</CODE> status before
  58.  * the change, its status will change to <CODE>UPDATED</CODE>; this happens either on both the {@link #setValue(DataColumn, Object)}
  59.  * or {@link #setReferenceValue(DataColumn, Object)} methods. An <CODE>INSERTED</CODE> or a <CODE>DELETED</CODE> row can have its cells
  60.  * changed without affecting the row's status.
  61.  * 
  62.  * <p>For performance, comparing the reference to the current value of a cell is done using the Java
  63.  * <CODE>==</CODE> comparison by default, which of course only works for object references that are the same. Identity
  64.  * comparisons are used on all columns if the <CODE>DataTable's</CODE> <CODE>identityComparisonEnabled</CODE> property is set to <CODE>true</CODE>.
  65.  * If this property is false, one can assign  a <CODE>Comparator</CODE> per-column in the table, or per-class (DataColumn type).
  66.  * If both a per-class and a per-column <CODE>Comparator</CODE> have been assigned, the per-column <CODE>Comparator</CODE> is used.
  67.  * If the property is false, and no <CODE>Comparator</CODE> is assigned, equality comparison (<CODE>.equals()</CODE>) is used. Note
  68.  * that if you do not assign <CODE>Comparators</CODE>, you may have rows with an <CODE>UPDATED</CODE> status when the value is
  69.  * actually the same, if the <CODE>==</CODE> comparison fails. For accuracy, you should assign a <CODE>Comparator</CODE>, but for efficiency
  70.  * (e.g. columns with large content sizes), you may want a <CODE>Comparator</CODE> that just skips the test altogether.
  71.  * 
  72.  * <p><CODE>DataRows</CODE> support both property change listeners and event listeners; note that row status is a property of
  73.  * the row. Events broadcast {@link RowChangeEvent} messages.
  74.  * @author Richard Bair
  75.  * @author Patrick Wright
  76.  */
  77. public class DataRow {
  78.     /**
  79.      * Flag indicating the status of the DataRow; these are described in the class JavaDoc.
  80.      */
  81.     public enum DataRowStatus {
  82.         /**
  83.          * The row was inserted into the table.
  84.          */
  85.         INSERTED,
  86.         /**
  87.          * The row was deleted from the table.
  88.          */
  89.         DELETED,
  90.         /**
  91.          * The row has been updated, at least one cell is modified.
  92.          */
  93.         UPDATED,
  94.         /**
  95.          * The row has not been modified; no cells are modified.
  96.          */
  97.         UNCHANGED
  98.     };
  99.     
  100.     //used for communicating changes to this JavaBean, especially necessary for
  101.     //IDE tools, but also handy for any other component listening to this row
  102.     /**
  103.      * Property change support for the row.
  104.      */
  105.     private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
  106.     
  107.     /**
  108.      * The DataTable that created this DataRow. This is an immutable property
  109.      */
  110.     private DataTable table;
  111.     
  112.     /**
  113.      * The status of this DataRow. By default, it is set to INSERTED. It is
  114.      * possible to change the status manually, although during certain
  115.      * lifecycle events it is automatically changed, such as after the data
  116.      * is saved to disk, or a change is made.
  117.      */
  118.     private DataRowStatus status = DataRowStatus.INSERTED;
  119.     
  120.     /**
  121.      * The data associated with this Row. This structure implies that when a
  122.      * DataColumn is removed from the DataTable, then each row will have to be
  123.      * traversed and the DataColumn removed from the Map, along with the cell
  124.      */
  125.     private Map<DataColumn,DataCell> cells = new HashMap<DataColumn,DataCell>();
  126.     
  127.     /**
  128.      * Create a new DataRow. The table creating this row must be passed in; rows are
  129.      * normally created by calling the DataTable's appendRow() or appendRowNoEvent methods.
  130.      * The new row will have a cell for each column the the table, with the value being the
  131.      * default value for that DataColumn.
  132.      */
  133.     protected DataRow(DataTable table) {
  134.         assert table != null;
  135.         this.table = table;
  136.         
  137.         //construct the cells based on the columns in the table
  138.         //add a cell for each column
  139.         for (DataColumn col : this.table.getColumns()) {
  140.             addCell(col);
  141.         }
  142.     }
  143.     
  144.     /**
  145.      * Sets the given refence value to the column with the given name.
  146.      *
  147.      * @param colName The name of the DataColumn to change the value for.
  148.      * @param value The new column reference value; may cause the row status to change, see class
  149.      * comments.
  150.      */
  151.     public void setReferenceValue(String colName, Object value) {
  152.         setReferenceValue(table.getColumn(colName), value);
  153.     }
  154.     
  155.     /**
  156.      * Sets the given refence value to the specified DataColumn.
  157.      *
  158.      * @param col The DataColumn to change the value for.
  159.      * @param value The new column reference value; may cause the row status to change, see class
  160.      * comments.
  161.      */
  162.     public void setReferenceValue(DataColumn col, Object value) {
  163.         assert col != null;
  164.         
  165.         // get the cell
  166.         getCell(col).setReferenceValue(table, col, value);
  167.         
  168.         // determine new status
  169.         DataRowStatus newStatus = deriveRowStatus();
  170.         if ( newStatus != status ) {
  171.             setStatus(newStatus);
  172.         }
  173.     }
  174.     
  175.     /**
  176.      * Sets the given value to the column with the given name.
  177.      *
  178.      * @param colName The name of the DataColumn to change the value for.
  179.      * @param value The new column value; may cause the row status to change, see class
  180.      * comments.
  181.      */
  182.     public void setValue(String colName, Object value) {
  183.         DataColumn col = table.getColumn(colName);
  184.         setValue(col, value);
  185.     }
  186.     
  187.     /**
  188.      * Sets the given value to the specified DataColumn with the given name.
  189.      * @param col The DataColumn for which to set the value.
  190.      * @param value The new column value; may cause the row status to change, see class
  191.      * comments.
  192.      */
  193.     public void setValue(DataColumn col, Object value) {
  194.         assert col != null;
  195.         
  196.         Object oldValue = getValue(col);
  197.         DataCell cell = getCell(col);
  198.         boolean wasChanged = cell.changed;
  199.         getCell(col).setValue(table, col, value);
  200.         
  201.         if ( wasChanged != cell.changed ) {
  202.             fireDataRowChanged(RowChangeEvent.newCellChangedEvent(this, col, oldValue));
  203.         }
  204.         
  205.         DataRowStatus oldStatus = status;
  206.         DataRowStatus newStatus = deriveRowStatus();
  207.         if ( newStatus != oldStatus ) {
  208.             setStatus(newStatus);
  209.         }
  210.     }
  211.     
  212.     /**
  213.      * Resets all columns in the row to have their current value be their reference value, effectively reverting
  214.      * the effects of calling {@link #setValue(DataColumn, Object)} till now. After this method call, the row will once
  215.      * again regain its normal status (INSERTED or UNCHANGED). For a discussion on reference
  216.      * values, see the class docs.
  217.      */
  218.     public void resetAllToReferenceValue() {
  219.         List<DataColumn> cols = table.getColumns();
  220.         for ( DataColumn col : cols ) {
  221.             resetToReferenceValue(col);
  222.         }
  223.     }  
  224.     
  225.     /**
  226.      * Resets the named column in the row to its reference value, effectively reverting
  227.      * the effects of calling {@link #setValue(DataColumn, Object)} till now. After this method call, the row may once
  228.      * again regain its normal status (INSERTED or UNCHANGED) if there are no longer any
  229.      * modified columns. For a discussion on reference values, see the class docs.
  230.      * @param colName The column name for which to reset to the reference value.
  231.      */
  232.     public void resetToReferenceValue(String colName) {
  233.         resetToReferenceValue(table.getColumn(colName));
  234.     }
  235.     
  236.     /**
  237.      * Resets the DataColumn in the row to its reference value, effectively reverting
  238.      * the effects of calling {@link #setValue(DataColumn, Object)} till now. After this method call, the row may once
  239.      * again regain its normal status (INSERTED or UNCHANGED) if there are no longer any
  240.      * modified columns. For a discussion on reference values, see the class docs.
  241.      * @param col The DataColumn for which to reset to the reference value.
  242.      */
  243.     public void resetToReferenceValue(DataColumn col) {
  244.         setValue(col, getCell(col).referenceValue);
  245.         /* CLEAN
  246.          getCell(col).revert();
  247.         DataRowStatus newStatus = deriveRowStatus();
  248.         if ( newStatus != status ) {
  249.             setStatus(newStatus);
  250.         }
  251.          */
  252.     }
  253.     
  254.     /**
  255.      * Returns the current reference value for the column.
  256.      * @return the reference value at the given column name; see class documentation
  257.      * for a discussion of reference values.
  258.      * @param colName The column name for which to lookup the reference value.
  259.      */
  260.     public Object getReferenceValue(String colName) {
  261.         return getReferenceValue(table.getColumn(colName));
  262.     }
  263.     
  264.     /**
  265.      * Returns the value for the given column.
  266.      * @param colName The column for which to return the current value.
  267.      * @return the value at the given column name
  268.      */
  269.     public Object getValue(String colName) {
  270.         return getValue(table.getColumn(colName));
  271.     }
  272.     /**
  273.      * Returns the reference value for the column.
  274.      * @return the reference value for the given DataColumn; see class documentation
  275.      * for a discussion of reference values.
  276.      * @param col The DataColumn for which to return the reference value.
  277.      */
  278.     public Object getReferenceValue(DataColumn col) {
  279.         assert col != null;
  280.         String exp = col.getExpression();
  281.         if (exp == null || exp.equals("")) {
  282.             DataCell cell = getCell(col);
  283.             return cell.referenceValue;
  284.         } else {
  285.             return col.getValueForRow(this);
  286.         }
  287.     }
  288.     
  289.     /**
  290.      * Returns the current value for the column.
  291.      * @return the value for the given DataColumn.
  292.      * @param col The DataColumn for which to return the current value.
  293.      */
  294.     public Object getValue(DataColumn col) {
  295.         assert col != null;
  296.         String exp = col.getExpression();
  297.         if (exp == null || exp.equals("")) {
  298.             DataCell cell = getCell(col);
  299.             return cell.value;
  300.         } else {
  301.             return col.getValueForRow(this);
  302.         }
  303.     }
  304.     
  305.     /**
  306.      * Returns the DataCell for the column; if there is none, creates one
  307.      * initialized to the column's default value.
  308.      */
  309.     protected DataCell getCell(DataColumn col) {
  310.         DataCell cell = cells.get(col);
  311.         if (cell == null && col.getTable() == table) {
  312.             cell = addCell(col);
  313.         }
  314.         return cell;
  315.     }
  316.     
  317.     /**
  318.      * Returns the DataTable that owns this row.
  319.      * @return The DataTable that owns this DataRow.
  320.      */
  321.     public DataTable getTable() {
  322.         return table;
  323.     }
  324.     
  325.     /**
  326.      * Returns the current row status.
  327.      * @return The current DataRowStatus enumerated value for this DataRow;
  328.      * see class comments.
  329.      */
  330.     public DataRowStatus getStatus() {
  331.         return status;
  332.     }
  333.     
  334.     /**
  335.      * Returns true if the current value for the column is different from its reference value.
  336.      * @return true if the given column has been modified; see class comments.
  337.      * @param colName The column name to check for modification.
  338.      */
  339.     public boolean isModified(String colName) {
  340.         return isModified(table.getColumn(colName));
  341.     }
  342.     
  343.     /**
  344.      * Returns true if the current value for the column is different from its reference value.
  345.      * @return true if the given column has been modified; see class comments.
  346.      * @param col The DataColumn to check for modification.
  347.      */
  348.     public boolean isModified(DataColumn col) {
  349.         return cells.get(col).changed;
  350.     }
  351.     
  352.     /**
  353.      * CLEAN: remove these once getReference... methods have been approved (they replace getOriginal...)
  354.      * 
  355.      * @return the original value for the column in this row. If the cell was not
  356.      * assigned a value explicitly, this is the column's default value. Otherwise it is
  357.      * the first value assigned to the column on this row.
  358.      * @deprecated use getReferenceValue(String colName)
  359.      * @param colName 
  360.      */
  361.     public Object getOriginalValue(String colName) {
  362.         return getReferenceValue(colName);
  363.     }
  364.     
  365.     /**
  366.      * CLEAN: remove these once getReference... methods have been approved (they replace getOriginal...)
  367.      * 
  368.      * 
  369.      * @return the original value for the column in this row. If the cell was not
  370.      * assigned a value explicitly, this is the column's default value. Otherwise it is
  371.      * the first value assigned to the column on this row.
  372.      * @deprecated use getReferenceValue(DataColumn col)
  373.      * @param col 
  374.      */
  375.     public Object getOriginalValue(DataColumn col) {
  376.         return getReferenceValue(col);
  377.     }
  378.     
  379.     /**
  380.      * Changes the row's status; a status change event will be broadcast if the status is
  381.      * different from the current status. Changing an UPDATED row's status to UNCHANGED will 
  382.      * overwrite reference values in all cells with the current values; modifying any column 
  383.      * subsequently will change the row status if the columns new value is different than 
  384.      * this reference value.
  385.      *
  386.      * @param status The new status for the row.
  387.      */
  388.     public void setStatus(DataRowStatus status) {
  389.         if (this.status != status) {
  390.             DataRowStatus priorStatus = this.status;
  391.             this.status = status;
  392.             
  393.             pcs.firePropertyChange("status", priorStatus, status);
  394.             
  395.             if (this.status == DataRowStatus.UNCHANGED) {
  396.                 // overwrite all reference values with current values
  397.                 List<DataColumn> cols = table.getColumns();
  398.                 for ( DataColumn col : cols ) {
  399.                     // note: we don't send a row-cell change event here because it's
  400.                     // the reference val, not the current val, that is changing
  401.                     DataCell cell = getCell(col);
  402.                     if ( cell.changed ) cell.overwriteReference();
  403.                 }
  404.             }
  405.         }
  406.     }
  407.     
  408.     /**
  409.      * Used internally to fire events for row changes.
  410.      * @param evt The RowChangeEvent to fire.
  411.      */
  412.     public void fireDataRowChanged(RowChangeEvent evt) {
  413.         table.fireRowChanged(evt);
  414.     }
  415.     
  416.     /**
  417.      * Adds a PropertyChangeListener to this class for any changes to bean
  418.      * properties.
  419.      *
  420.      * @param listener The PropertyChangeListener to notify of changes to this
  421.      * instance.
  422.      */
  423.     public void addPropertyChangeListener(PropertyChangeListener listener) {
  424.         pcs.addPropertyChangeListener(listener);
  425.     }
  426.     
  427.     /**
  428.      * Adds a PropertyChangeListener to this class for specific property changes.
  429.      *
  430.      * @param property The name of the property to listen to changes for.
  431.      * @param listener The PropertyChangeListener to notify of changes to this
  432.      * instance.
  433.      */
  434.     public void addPropertyChangeListener(String property, PropertyChangeListener listener) {
  435.         pcs.addPropertyChangeListener(property,  listener);
  436.     }
  437.     
  438.     /**
  439.      * Stops notifying a specific listener of any changes to bean properties.
  440.      *
  441.      * @param listener The listener to stop receiving notifications.
  442.      */
  443.     public void removePropertyChangeListener(PropertyChangeListener listener) {
  444.         pcs.removePropertyChangeListener(listener);
  445.     }
  446.     
  447.     /**
  448.      * Stops notifying a specific listener of changes to a specific property.
  449.      *
  450.      * @param propertyName The name of the property to ignore from now on.
  451.      * @param listener The listener to stop receiving notifications.
  452.      */
  453.     public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
  454.         pcs.removePropertyChangeListener(propertyName,  listener);
  455.     }
  456.     
  457.     /**
  458.      * {@inheritDoc}
  459.      */
  460.     public String toString() {
  461.         StringBuilder buffer = new StringBuilder();
  462.         buffer.append("Row #");
  463.         buffer.append(table.indexOfRow(this));
  464.         buffer.append(" [ ");
  465.         int i=0;
  466.         for (DataCell c : cells.values()) {
  467.             buffer.append(c.value);
  468.             if (i < cells.size() -1) {
  469.                 buffer.append(", ");
  470.             }
  471.             i++;
  472.         }
  473.         buffer.append(" ]");
  474.         return buffer.toString();
  475.     }
  476.     
  477.     /**
  478.      * Used internally to add a cell to the row. If a cell for this column
  479.      * already exists, returns that cell.
  480.      *
  481.      * @param col The DataColumn for which to add the cell.
  482.      */
  483.     protected DataCell addCell(DataColumn col) {
  484.         DataCell cell = cells.get(col);
  485.         if ( cell == null ) {
  486.             cell = new DataCell(col);
  487.             cells.put(col, cell);
  488.         }
  489.         return cell;
  490.     }
  491.     
  492.     /**
  493.      * Used internally to determine the row's current status, called after a cell's
  494.      * value is changed. The general rule is that UNCHANGED rows will be marked UPDATED if
  495.      * at least one cell is changed, and UPDATED rows will be marked UNCHANGED if no cells
  496.      * are changed. INSERTED and DELETED rows do not change status in this method.
  497.      */
  498.     protected DataRowStatus deriveRowStatus() {
  499.         DataRowStatus derived;
  500.         switch (status) {
  501.             case INSERTED: // fall-thru
  502.             case DELETED:
  503.                 derived = status;
  504.                 break;
  505.             case UPDATED: // fall-thru
  506.             case UNCHANGED:
  507.                 boolean any = false;
  508.                 for ( DataCell cell : cells.values()) {
  509.                     if ( cell.changed ) {
  510.                         any = true;
  511.                         break;
  512.                     }
  513.                 }
  514.                 derived = ( any ? DataRowStatus.UPDATED : DataRowStatus.UNCHANGED );
  515.                 break;
  516.             default:
  517.                 throw new RuntimeException("deriveRowStatus() has no case for row status of " + status);
  518.         }
  519.         return derived;
  520.     }
  521.     
  522.     /**
  523.      * Class used internally to intersect a DataColumn for the row; holds the reference
  524.      * and current values. As these are populated per-column per-row, a minimum of state
  525.      * information is kept in each cell, and methods receive contextual information necessary
  526.      * for the task to reduce stored state.
  527.      */
  528.     private static final class DataCell {
  529.         /**
  530.          * The reference value for the cell.
  531.          */
  532.         Object referenceValue;
  533.         /**
  534.          * The current value for the cell.
  535.          */
  536.         Object value;
  537.         /**
  538.          * True if the current value is different from the reference value.
  539.          */
  540.         boolean changed;
  541.         /**
  542.          * True is the current value was set for the first time.
  543.          */
  544.         boolean valueSet;
  545.         
  546.         /**
  547.          * Instantiates a cell for a given column.
  548.          * @param col The DataColumn for which to create a cell.
  549.          */
  550.         DataCell(DataColumn col){
  551.             this.value = this.referenceValue = col.getDefaultValue();
  552.         }
  553.         
  554.         /**
  555.          * Sets the reference value for the cell.
  556.          * @param table The DataTable for the row.
  557.          * @param col The DataColumn for the cell.
  558.          * @param newRef The new reference value for the cell.
  559.          */
  560.         public void setReferenceValue(DataTable table, DataColumn col, Object newRef) {
  561.             referenceValue = newRef;
  562.             changed = isSame(table, col, referenceValue, newRef);
  563.         }
  564.         
  565.         /**
  566.          * Sets the current value for the cell.
  567.          * @param table The DataTable for the row.
  568.          * @param col The DataColumn for the cell.
  569.          * @param newValue The new current value for the cell.
  570.          */
  571.         public void setValue(DataTable table, DataColumn col, Object newValue) {
  572.             // if this is the first call, set reference value for cell
  573.             if ( !valueSet ) {
  574.                 value = referenceValue = newValue;
  575.                 changed = false;
  576.                 valueSet = true;
  577.                 return;
  578.             }
  579.             
  580.             // if the new value is our current reference value, then cell is
  581.             // no longer changed
  582.             if ( isSame(table, col, referenceValue, newValue )) {
  583.                 value = referenceValue;
  584.                 changed = false;
  585.                 return;
  586.             } else {
  587.                 // not the same as our reference value
  588.                 if ( ! isSame( table, col, value, newValue )) {
  589.                     value = newValue;
  590.                     changed = true;
  591.                 }
  592.             }
  593.         }
  594.         
  595.         /**
  596.          * Overwrites the reference value for the cell with its current value.
  597.          */
  598.         public void overwriteReference() {
  599.             referenceValue = value;
  600.             changed = false;
  601.         }
  602.         /**
  603.          * Returns true if the two values are the same, using either <CODE>==</CODE>, or a <CODE>Comparator</CODE>; see 
  604.          * class docs on DataRow.
  605.          * @param table The DataTable for the row.
  606.          * @param col The DataColumn for the cell.
  607.          * @param baseValue The base value we are comparing.
  608.          * @param newValue The new value we are comparing with.
  609.          * @return True if the value are the same.
  610.          */
  611.         private boolean isSame(DataTable table, DataColumn col, Object baseValue, Object newValue) {
  612.             if ( table.isIdentityComparisonEnabled()) {
  613.                 return newValue == baseValue;
  614.             } else {
  615.                 Comparator comp = null;
  616.                 if ( table.hasColumnComparator(col)) {
  617.                     comp = table.getColumnComparator(col);
  618.                 } else {
  619.                     // this returns a default .equals() comparator if none
  620.                     // is assigned to the column type
  621.                     comp = table.getClassComparator(col.getType());
  622.                 }
  623.                 return comp.compare(baseValue, newValue) == 0;
  624.             }
  625.         }
  626.     }
  627. }