📄 datatable.java
字号:
/* * $Id: DataTable.java,v 1.16 2005/10/15 11:43:20 pdoubleya Exp $ * * Copyright 2005 Sun Microsystems, Inc., 4150 Network Circle, * Santa Clara, California 95054, U.S.A. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */package org.jdesktop.dataset;import java.beans.PropertyChangeEvent;import java.beans.PropertyChangeListener;import java.beans.PropertyChangeSupport;import java.util.ArrayList;import java.util.Collections;import java.util.Comparator;import java.util.HashMap;import java.util.LinkedHashMap;import java.util.List;import java.util.Map;import java.util.logging.Logger;import javax.swing.event.EventListenerList;import org.jdesktop.dataset.event.DataTableListener;import org.jdesktop.dataset.event.RowChangeEvent;import org.jdesktop.dataset.event.TableChangeEvent;import static org.jdesktop.dataset.event.TableChangeEvent.EventType.*;/** * A <CODE>DataTable</CODE> represents a two-dimensional non-visual data structure composed of {@link DataRow DataRows}, where each row has * one or more {@link DataColumn DataColumns}; the set of columns is specified in the table, and applies to all rows. A * <CODE>DataTable</CODE> always belongs to a {@link DataSet}, and in fact must be created using the {@link DataSet#createTable()} * method, as a table cannot exist outside of a <CODE>DataSet</CODE>. For an overview of the DataSet API, see * {@link https://jdnc.dev.java.net/documentation/dataset}. * * Table data is loaded either programmatically (by your code, one row and one value at a time) or by a {@link DataProvider}. A * table can have a single <CODE>DataProvider</CODE>, which is responsible for loading the table from, and storing table changes back * to, some data source. See documentation for <CODE>DataProvider</CODE> and its subclasses to see what sources are supported. * * A table has a name property, which is unique within the * <CODE>DataSet</CODE> that owns it. Names can be specified when the table is created, or will be assigned automatically. * * A table must have columns assigned to it in order to store data in any row. The intersection of a column and row is called a * cell. Columns are instances of <CODE>DataColumn</CODE>, and each * has a name unique within the table. Columns add added using {@link #createColumn()}, {@link #createColumn(String)} or * {@link #createColumns(String...)} and are attached to the table from which they are created. As a rule, any methods that * are column-specific (like {@link #setValue(DataColumn, Object)} can take either the <CODE>DataColumn</CODE> instance or the name * of the <CODE>DataColumn</CODE> as a parameter. Columns can be removed from the table using {@link #dropColumn(String)}. Adding * a column to a table with rows in it will give the cells for the new column the column's {@link DataColumn#getDefaultValue() default value}. * Dropping a column from a table will cause the data in the cells of that column to be lost. * * A table has 0...n rows at any time. Blank rows are added using {@link #appendRow()} and {@link #appendRowNoEvent()} and remain * in the table in the order they were added to it, so can be retrieved by a 0-based index using {@link getRow(int)}. New rows start with * the current set of columns in the table, and adding or dropping columns from a table will have those automatically added or dropped * from all rows in the table. To remove a row, use {@link #deleteRow(int)} or {@link #deleteRow(DataRow)} if you want the table's * DataProvider to remove the row as well from the table's data source. Deleted rows are maked with a row status of DELETED and * remain in memory until the DataProvider removes them. To drop a row completely, use {@link #discardRow(int)} or {@link #discardRow(DataRow)}. * Discarding rows causes them to be dropped immediately from the table, and the deletion will not be recorded by the table's DataProvider. * * Once you have rows in the table, you can change values in the row using {@link #setValue(int, String, Object)}, or through the * equivalent methods on the {@link DataRow} itself. You can retrieve row values using {@link #getValue(int, String)} or equivalent * methods on the row. Rows have a certain status within the table, as described in the documentation for the {@link DataRow} class. To list * rows in the table, use {@link getRows()} or {@link getRow(int)}. * @author Richard Bair * @author Patrick Wright */public class DataTable { /** * The Logger */ private static final Logger LOG = Logger.getLogger(DataTable.class.getName()); //protected for testing /** Used as a prefix for auto-generated names. */ protected static final String DEFAULT_NAME_PREFIX = "DataTable"; /** The shared instance of the NameGenerator for DataTables not assigned a name. */ private static final NameGenerator NAMEGEN = new NameGenerator(DEFAULT_NAME_PREFIX); //used for communicating changes to this JavaBean, especially necessary for //IDE tools, but also handy for any other component listening to this table /** * Used for communicating changes to this JavaBean, especially necessary for IDE tools, but also handy for any other component listening to this table. */ private PropertyChangeSupport pcs = new PropertyChangeSupport(this); /** * A reference to the DataSet to which this DataTable belongs */ private DataSet dataSet; /** * The DataProvider that is used to manage this DataTables data. It is * technically possible for a DataProvider to populate a DataTable to which * it is not associated, but the results are undefined */ private DataProvider dataProvider; /** * The name of this DataTable */ private String name; /** * Mapping of DataColumn.name to DataColumn. Extremely useful for * discovering the column object associated with a name. The resolver code * responsible for locating a particular data cell will first convert the * column name to a DataColumn, and then use the DataColumn in the hash for * locating the data. This is done so that: * <ol> * <li>The lookup is constant time (or close to it)</li> * <li>Avoid looping through a columns list looking for the column</li> * <li>More efficient handling if the column name changes in a large table, * which would not be possible if the column name was used in the hash</li> * </ol> */ protected Map<String,DataColumn> columns = new LinkedHashMap<String,DataColumn>(); /** * A map of Comparators by Class type; only one Comparator is allowed per class. * This is used by DataRows to compare a new value for a cell with the * reference value, to determine if the cell is "changed" or not. */ protected Map<Class,Comparator> classComparators = new HashMap<Class,Comparator>(); /** * A map of Comparators by DataColumn; only one Comparator is allowed per column. * This is used by DataRows to compare a new value for a cell with the * reference value, to determine if the cell is "changed" or not. */ protected Map<DataColumn,Comparator> columnComparators = new HashMap<DataColumn,Comparator>(); /** * A comparator for checking for changes between reference and current values for a column * in a row, used when identityComparisonEnabled is false, and no column or class comparators * are assigned. */ private final static Comparator EQUALS_COMPARATOR = new Comparator() { public boolean equals(Object obj) { return obj == this; } public int compare(Object o1, Object o2) { return ( o1.equals(o2) ? 0 : -1 ); } }; /** * The list of DataRows in this DataTable. The DataRow actually contains the * data at the various cells. */ protected List<DataRow> rows = new ArrayList<DataRow>(); /** * Every DataTable contains a list of selectors, which manage tracking * "selected" state in a DataTable. This is necessary for proper handling * of master/detail relationships, also known as parent/child. This data * structure maps the data selectors name to the selector itself. */ protected Map<String,DataSelector> selectors = new HashMap<String,DataSelector>(); /** * Indicates whether deleting rows is supported. Attempts to * delete a row when row deletion is not supported will be ignored */ private boolean deleteRowSupported = true; /** * Indicates whether appending rows is supported. Attempts to append a * row when row appending is not supported will be ignored. */ private boolean appendRowSupported = true; /** * Indicates whether new values applied to any row are compared with the * cell's reference value using == (instance identity comparison). If true, * identity comparison is used; if false, defaults to using .equals() on * the two values, unless a Comparator is assigned to the column class or * the column. See class docs for {@link DataRow} and {@link DataTable} for * more details on value comparison and row status. Defaults to true for new * tables. */ private boolean identityComparisonEnabled; /** * A list of DataTableListeners to notify of various events */ private List<DataTableListener> listeners = new ArrayList<DataTableListener>(); /** * A PropertyChangeListener for listening to name property change events * on DataSelectors and DataColumns. The listener makes sure that the name * used as the hash key in the selectors and columns maps is always * accurate. */ private final PropertyChangeListener nameChangeListener = new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent evt) { if (evt.getSource() instanceof DataSelector) { DataSelector sel = selectors.remove(evt.getOldValue()); if (sel != null) { //name changed selectors.put((String)evt.getNewValue(), sel); } } else if (evt.getSource() instanceof DataColumn) { DataColumn c = columns.remove(evt.getOldValue()); if (c != null) { //name changed columns.put((String)evt.getNewValue(), c); } } } }; /** * Create a new DataTable for a specified DataSet, with an * automatically-generated name unique to the DataSet. * * @param ds The DataSet to which the table will be added. */ protected DataTable(DataSet ds) { assert ds != null; this.dataSet = ds; this.name = NAMEGEN.generateName(this); this.identityComparisonEnabled = true; } /** * Create a new DataTable for a specified DataSet, with the * specified name. * * @param ds The DataSet to which the table will be added. * @param name The name of the table. */ protected DataTable(DataSet ds, String name) { this(ds); if (name != null) { setName(name); } } /** * creates a new DataColumn, and adds it to this DataTable. A name will * be automatically generated for the DataColumn. * * @return the DataColumn that was created */ public DataColumn createColumn() { return createColumn(null); } /** * Creates a new DataColumn with the given name, and adds it to this * DataTable. * * @param colName the name to give the DataColumn. If the name is invalid * or has already been used in the DataSet, an assertion will be raised * * @return the new DataColumn */ public DataColumn createColumn(String colName) { DataColumn col = new DataColumn(this); if (colName != null) { col.setName(colName); } columns.put(col.getName(), col); col.addPropertyChangeListener("name", nameChangeListener); fireDataTableChanged(TableChangeEvent.newColumnAddedEvent(this, col)); return col; } /** * Adds a column to the table for each name in the supplied array of Strings. * @param colNames Array of column names to add to the table. */ public void createColumns(String... colNames) { for (String name : colNames) { createColumn(name); } } /** * Drops the column with the given name. If there is no column by the * specified name, then nothing is done. * @param colName Name of the column to drop. */ public void dropColumn(String colName) { DataColumn col = columns.remove(colName); if (col != null) { col.removePropertyChangeListener("name", nameChangeListener); //remove any remaining references to this column in the DataRelations for (DataRelation r : dataSet.getRelations()) { DataColumn c = r.getChildColumn(); if (c == col) { r.setChildColumn(null); } c = r.getParentColumn(); if (c == col) { r.setParentColumn(null); } } columnComparators.remove(col); fireDataTableChanged(TableChangeEvent.newColumnRemovedEvent(this, col)); } } /** * @return a List of DataColumns representing all of the columns in this * DataTable. */ public List<DataColumn> getColumns() { return Collections.unmodifiableList(new ArrayList<DataColumn>(columns.values())); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -