⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cascadedtable.java

📁 用applet实现很多应用小程序
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
package prefuse.data;

import java.util.ArrayList;
import java.util.Iterator;

import javax.swing.event.TableModelEvent;

import prefuse.data.column.Column;
import prefuse.data.column.ColumnMetadata;
import prefuse.data.event.EventConstants;
import prefuse.data.event.ExpressionListener;
import prefuse.data.event.ProjectionListener;
import prefuse.data.event.TableListener;
import prefuse.data.expression.BooleanLiteral;
import prefuse.data.expression.Expression;
import prefuse.data.expression.Predicate;
import prefuse.data.tuple.TableTuple;
import prefuse.data.util.AcceptAllColumnProjection;
import prefuse.data.util.CascadedRowManager;
import prefuse.data.util.ColumnProjection;
import prefuse.util.collections.CompositeIterator;
import prefuse.util.collections.IntIterator;


/**
 * <p>Table subclass featuring a "cascaded" table design - a CascadedTable can
 * have a parent table, from which it inherits a potentially filtered set of
 * rows and columns. Child tables may override the columns of the parent by
 * having a column of the same name as that of the parent, in which case the
 * parent's column will not be accessible.</p>
 * 
 * <p>Table rows of the parent table can be selectively included by providing
 * a {@link prefuse.data.expression.Predicate} that filters the parent rows.
 * Columns of the parent table can be selectively included by providing
 * a {@link prefuse.data.util.ColumnProjection} indicating the columns to
 * include.</p>
 * 
 * <p>Tuple instances backed by a CascadedTable will be not be equivalent to
 * the tuples backed by the parent table. However, setting a value in a
 * CascadedTable that is inherited from a parent table <em>will</em> update
 * the value in the parent table.</p>
 * 
 * @author <a href="http://jheer.org">jeffrey heer</a>
 */
public class CascadedTable extends Table {

    /** Cascaded parent table */ 
    protected Table      m_parent;
    /** List of included parent column names */
    protected ArrayList  m_pnames;
    
    /** ColumnProjection determining which columns of the parent table
     * are included in this table. */
    protected ColumnProjection m_colFilter;
    /** Selection Predicate determining which rows of the parent table
     * are included in this table. */
    protected Predicate    m_rowFilter;
    
    /** An internal listener class */
    protected Listener m_listener;
    
    // ------------------------------------------------------------------------
    // Constructor
    
    /**
     * Create a new CascadedTable. By default all rows and columns of the
     * parent table are included in this one.
     * @param parent the parent Table to use
     */
    public CascadedTable(Table parent) {
        this(parent, null, null);
    }
    
    /**
     * Create a new CascadedTable. By default all columns of the parent
     * table are included in this one.
     * @param parent the parent Table to use
     * @param rowFilter a Predicate determining which rows of the parent
     * table to include in this one.
     */
    public CascadedTable(Table parent, Predicate rowFilter) {
        this(parent, rowFilter, null);
    }
    
    /**
     * Create a new CascadedTable. By default all rows of the parent
     * table are included in this one.
     * @param parent the parent Table to use
     * @param colFilter a ColumnProjection determining which columns of the
     * parent table to include in this one.
     */
    public CascadedTable(Table parent, ColumnProjection colFilter) {
        this(parent, null, colFilter);
    }
    
    /**
     * Create a new CascadedTable.
     * @param parent the parent Table to use
     * @param rowFilter a Predicate determining which rows of the parent
     * table to include in this one.
     * @param colFilter a ColumnProjection determining which columns of the
     * parent table to include in this one.
     */
    public CascadedTable(Table parent, Predicate rowFilter, 
                         ColumnProjection colFilter)
    {
        this(parent, rowFilter, colFilter, TableTuple.class);
    }
    
    /**
     * Create a new CascadedTable.
     * @param parent the parent Table to use
     * @param rowFilter a Predicate determining which rows of the parent
     * table to include in this one.
     * @param colFilter a ColumnProjection determining which columns of the
     * parent table to include in this one.
     * @param tupleType the class type of the Tuple instances to use
     */
    protected CascadedTable(Table parent, Predicate rowFilter, 
            ColumnProjection colFilter, Class tupleType)
    {
        super(0, 0, tupleType);
        m_parent = parent;
        m_pnames = new ArrayList();
        m_rows = new CascadedRowManager(this);
        m_listener = new Listener();
        
        setColumnProjection(colFilter);
        setRowFilter(rowFilter);
        m_parent.addTableListener(m_listener);
    }
    
    // -- non-cascading version -----------------------------------------------
    
    /**
     * Create a CascadedTable without a backing parent table.
     */
    protected CascadedTable() {
        this(TableTuple.class);
    }

    /**
     * Create a CascadedTable without a backing parent table.
     * @param tupleType the class type of the Tuple instances to use
     */
    protected CascadedTable(Class tupleType) {
        super(0, 0, tupleType);
        m_pnames = new ArrayList();
    }
    
    // ------------------------------------------------------------------------
    // Filter Methods
    
    /**
     * Determines which columns are inherited from the backing parent table.
     */
    protected void filterColumns() {
        if ( m_parent == null ) return;
        
        for ( int i=0; i<m_pnames.size(); ++i ) {
            String name = (String)m_pnames.get(i);
            Column col = m_parent.getColumn(i);
            boolean contained = m_names.contains(name);
            if ( !m_colFilter.include(col, name) || contained ) {
                m_pnames.remove(i--);
                if ( !contained ) {
                    ((ColumnEntry)m_entries.get(name)).dispose();
                    m_entries.remove(name);
                }
                
                // fire notification
                fireTableEvent(m_rows.getMinimumRow(), 
                               m_rows.getMaximumRow(), 
                               i, EventConstants.DELETE);
            }
        }
        
        m_pnames.clear();

        Iterator pcols = m_parent.getColumnNames();
        for ( int i=0, j=m_columns.size(); pcols.hasNext(); ++i ) {
            String name = (String)pcols.next();
            Column col  = m_parent.getColumn(i);
            
            if ( m_colFilter.include(col, name) && !m_names.contains(name) ) {
                m_pnames.add(name);
                ColumnEntry entry = (ColumnEntry)m_entries.get(name);
                if ( entry == null ) {
                    entry = new ColumnEntry(j++, col, 
                            new ColumnMetadata(this, name));
                    m_entries.put(name, entry);
                    // fire notification
                    fireTableEvent(m_rows.getMinimumRow(), 
                                   m_rows.getMaximumRow(), 
                                   i, EventConstants.INSERT);
                } else {
                    entry.colnum = j++;
                }
                m_lastCol = m_columns.size()-1;
            }
        }
        
    }
    
    /**
     * Manually trigger a re-filtering of the rows of this table. If the
     * filtering predicate concerns only items within this table, calling
     * this method should be unnecessary. It is only when the filtering
     * predicate references data outside of this table that a manual
     * re-filtering request may be necessary. For example, filtering
     * valid edges of a graph from a pool of candidate edges will depend
     * on the available nodes.
     * @see prefuse.data.util.ValidEdgePredicate
     */
    public void filterRows() {
        if ( m_parent == null ) return;
        
        CascadedRowManager rowman = (CascadedRowManager)m_rows;
        IntIterator crows = m_rows.rows();
        while ( crows.hasNext() ) {
            int crow = crows.nextInt();
            if ( !m_rowFilter.getBoolean(
                    m_parent.getTuple(rowman.getParentRow(crow))) )
            {
                removeCascadedRow(crow);
            }
        }
        
        Iterator ptuples = m_parent.tuples(m_rowFilter);
        while ( ptuples.hasNext() ) {
            Tuple pt = (Tuple)ptuples.next();
            int prow = pt.getRow();
            if ( rowman.getChildRow(prow) == -1 )
                addCascadedRow(prow);
        }
    }
    
    /**
     * Get the ColumnProjection determining which columns of the
     * parent table are included in this one.
     * @return the ColumnProjection of this CascadedTable
     */
    public ColumnProjection getColumnProjection() {
    	return m_colFilter;
    }
    
    /**
     * Sets the ColumnProjection determining which columns of the
     * parent table are included in this one.
     * @param colFilter a ColumnProjection determining which columns of the
     * parent table to include in this one.
     */
    public void setColumnProjection(ColumnProjection colFilter) {
        if ( m_colFilter != null ) {
        	m_colFilter.removeProjectionListener(m_listener);
        }
        m_colFilter = colFilter==null ? new AcceptAllColumnProjection() : colFilter;
        m_colFilter.addProjectionListener(m_listener);
        filterColumns();
    }
    
    /**
     * Gets ths Predicate determining which rows of the parent
     * table are included in this one.
     * @return the row filtering Predicate of this CascadedTable
     */
    public Predicate getRowFilter() {
    	return m_rowFilter;
    }
    
    /**
     * Sets the Predicate determining which rows of the parent
     * table are included in this one.
     * @param rowFilter a Predicate determining which rows of the parent
     * table to include in this one.
     */
    public void setRowFilter(Predicate rowFilter) {
    	if ( m_rowFilter != null ) {
    		m_rowFilter.removeExpressionListener(m_listener);
    	}
        m_rowFilter = rowFilter==null ? BooleanLiteral.TRUE : rowFilter;
        if ( m_rowFilter != BooleanLiteral.TRUE )
            m_rowFilter.addExpressionListener(m_listener);
        filterRows();
    }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -