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

xml/soap/webservice

开发平台:

Java

  1. /*
  2.  * $Id: Filter.java,v 1.12 2005/10/13 08:59:52 kleopatra Exp $
  3.  *
  4.  * Copyright 2004 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.swingx.decorator;
  22. /**
  23.  * <p>A <b><code>Filter</code></b> is used to filter the data presented in a
  24.  * data-aware component such as a {@link org.jdesktop.swingx.JXList} or a
  25.  * {@link org.jdesktop.swingx.JXTable}. Filtering involves interposing one or
  26.  * more filters in a {@link org.jdesktop.swingx.decorator.FilterPipeline} between
  27.  * a data model and a view to change the apparent order and/or number of records
  28.  * in the data model.</p>
  29.  *
  30.  * @author Ramesh Gupta
  31.  * @see org.jdesktop.swingx.decorator.FilterPipeline
  32.  * @see org.jdesktop.swingx.JXTable
  33.  */
  34. public abstract class Filter {
  35.     /** the column the filter is bound to. JW: no need to make it final. */
  36.     private /** final */ int column; // in model coordinates
  37.     protected FilterPipeline pipeline = null;
  38.     protected ComponentAdapter adapter = null; /** @todo make private */
  39.     protected int[]             fromPrevious = new int[0];
  40.     // JW... magic number!
  41.     int order = -1; // package private
  42.     /**
  43.      * Constructs a new filter for the first column of a data model (in model coordinates).
  44.      */
  45.     public Filter() {
  46.         this(0);
  47.     }
  48.     /**
  49.      * Constructs a new filter for the specified column of a data model (in model coordinates).
  50.      *
  51.      * @param col column index in model coordinates
  52.      */
  53.     public Filter(int col) {
  54.         column = col;
  55.         init();
  56.     }
  57.     
  58. //----------------- public methods meant for end-client access
  59.     
  60.     /**
  61.      * Refreshes the internal state of the filter, performs the {@link #filter() filter}
  62.      * operation and regenerates row mappings from the previous filter. If this
  63.      * filter is bound to a filter pipeline (as most filters are), it also triggers a
  64.      * {@link org.jdesktop.swingx.decorator.FilterPipeline#filterChanged(org.jdesktop.swingx.decorator.Filter) filterChanged}
  65.      * notification.
  66.      */
  67.     public void refresh() {
  68.         refresh(true);
  69.     }
  70.     /**
  71.      * Returns the model index of the column that this filter has been bound to.
  72.      *
  73.      * @return the model index of the column that this filter has been bound to
  74.      */
  75.     public int getColumnIndex() {
  76.         return column;  // model coordinates
  77.     }
  78.     /**
  79.      * PENDING: not tested!
  80.      * 
  81.      * @param modelColumn
  82.      */
  83.     public void setColumnIndex(int modelColumn) {
  84.         if (getColumnIndex() == modelColumn) return;
  85.         this.column = modelColumn;
  86.         refresh();
  87.         
  88.     }
  89.     public String getColumnName() {
  90.         if (adapter == null) {
  91.             return "Column " + column;  // in model coordinates :-(
  92.         }
  93.         else {
  94.             return adapter.getColumnName(getColumnIndex());
  95.         }
  96.     }
  97.     /**
  98.      * Convert row index from view coordinates to model coordinates
  99.      * accounting for the presence of sorters and filters.
  100.      *
  101.      * PRE: 0 <= row < getSize()
  102.      *  
  103.      * @param row row index in this filters "view" coordinates - 
  104.      * @return row index in model coordinates
  105.      */
  106.     public int convertRowIndexToModel(int row) {
  107.         int mappedRow = mapTowardModel(row);
  108.         Filter filter = getMappingFilter();
  109.         if (filter != null) {
  110.             mappedRow = filter.convertRowIndexToModel(mappedRow);
  111.         }
  112.         return mappedRow;
  113.     }
  114.     /**
  115.      * Convert row index from model coordinates to view coordinates accounting
  116.      * for the presence of sorters and filters.
  117.      * 
  118.      * @param row row index in model coordinates
  119.      * @return row index in this filter's "view" coordinates
  120.      */
  121.     public int convertRowIndexToView(int row) {
  122.         int mappedRow = row;
  123.         Filter filter = getMappingFilter();
  124.         if (filter != null) {
  125.             mappedRow = filter.convertRowIndexToView(mappedRow);
  126.         }
  127.         return mapTowardView(mappedRow);
  128.     }
  129.     /**
  130.      * Returns the value at the specified row and column.
  131.      * 
  132.      * PRE: 0 <= row < getSize()
  133.      * 
  134.      * @param row row index in this filter's "view" coordinates
  135.      * @param column column index in model coordinates
  136.      * @return the value at the specified row and column
  137.      */
  138.     public Object getValueAt(int row, int column) {
  139.         int mappedRow = mapTowardModel(row);
  140.         Filter filter = getMappingFilter();
  141.         if (filter != null) {
  142.             return filter.getValueAt(mappedRow, column);
  143.         }
  144.         return adapter.getValueAt(mappedRow, column);
  145.     }
  146.     /**
  147.      * Sets the specified value as the new value for the cell identified by the
  148.      * specified row and column index.
  149.      *
  150.      * PRE: 0 <= row < getSize()
  151.      * 
  152.      * @param aValue new value for the specified cell
  153.      * @param row row index in this filter's "view" coordinates
  154.      * @param column column index in model coordinates
  155.      */
  156.     public void setValueAt(Object aValue, int row, int column) {
  157.         int mappedRow = mapTowardModel(row);
  158.         Filter filter = getMappingFilter();
  159.         if (filter != null) {
  160.             filter.setValueAt(aValue, mappedRow, column);
  161.             return; // make sure you return from here!
  162.         }
  163.         adapter.setValueAt(aValue, mappedRow, column);
  164.     }
  165.     /**
  166.      * returns editability of the cell identified by the specified row
  167.      * and column index.
  168.      * 
  169.      * PRE: 0 <= row < getSize()
  170.      * 
  171.      * @param row row index in this filter's "view" coordinates
  172.      * @param column
  173.      * @return
  174.      */
  175.     public boolean isCellEditable(int row, int column) {
  176.         int mappedRow = mapTowardModel(row);
  177.         Filter filter = getMappingFilter();
  178.         if (filter != null) {
  179.             return filter.isCellEditable(mappedRow, column);
  180.         }
  181.         return adapter.isCellEditable(mappedRow, column);
  182.     }
  183.     /**
  184.      * Returns the number of records that remain in this filter's "view"
  185.      * after the input records have been filtered.
  186.      *
  187.      * @return the number of records that remain in this filter's "view"
  188.      * after the input records have been filtered
  189.      */
  190.     public abstract int getSize();
  191. //---------------------------------- for subclasses
  192.     /**
  193.      * Returns the number of records that are processed by this filter.
  194.      *
  195.      * @return the number of records that are processed by this filter
  196.      */
  197.     protected int getInputSize() {
  198.         return pipeline == null ? adapter == null ?
  199.                 0 : adapter.getRowCount() : pipeline.getInputSize(this);
  200.     }
  201.     /**
  202.      * Returns the value of the cell at the specified row and column (in model coordinates).
  203.      *
  204.      * @param row in the coordinates of what is the filter's "view" of the model
  205.      * @param column in model coordinates
  206.      * @return the value of the cell at the specified row and column (in model coordinates)
  207.      */
  208.     protected Object getInputValue(int row, int column) {
  209.         Filter filter = getMappingFilter();
  210.         if (filter != null) {
  211.             return filter.getValueAt(row, column);
  212.         }
  213.         if (adapter != null) {
  214.             return adapter.getValueAt(row, column);
  215.         }
  216.         return null;
  217.     }
  218.     /**
  219.      * Provides filter-specific initialization. Called from the <code>Filter</code>
  220.      * constructor.
  221.      */
  222.     protected abstract void init();
  223.     /**
  224.      * Resets the internal row mappings from this filter to the previous filter.
  225.      */
  226.     protected abstract void reset();
  227.     /**
  228.      * Performs the filter operation defined by this filter.
  229.      */
  230.     protected abstract void filter();
  231.     /**
  232.      * PRE: 0 <= row < getSize();
  233.      * 
  234.      * @param row
  235.      * @return
  236.      */
  237.     protected abstract int mapTowardModel(int row);
  238.     /**
  239.      * PRE: 0 <= row < getInputSize();
  240.      * 
  241.      * @param row
  242.      * @return
  243.      */
  244.     protected int mapTowardView(int row) {
  245.         // WARNING: Not all model indices map to view when view is filtered!
  246.         // JW - TODO: cleanup and clarify preconditions in all mapping methods
  247.         // in all towardView the row must be < getInputSize
  248.         // in add towardModel the row must be < getSize
  249.         return row < 0 || row >= fromPrevious.length ? - 1 : fromPrevious[row];
  250.     }
  251.     /**
  252.      * Returns the row in this filter that maps to the specified row in the
  253.      * previous filter. If there is no previous filter in the pipeline, this returns
  254.      * the row in this filter that maps to the specified row in the data model.
  255.      * This method is called from
  256.      * {@link org.jdesktop.swingx.decorator.Filter#convertRowIndexToView(int) convertRowIndexToView}
  257.      *
  258.      * @param row a row index in the previous filter's "view" of the data model
  259.      * @return the row in this filter that maps to the specified row in
  260.      * the previous filter
  261.      */
  262.     @Deprecated /** @todo remove this deprecated method; use mapTowardView() instead */
  263.     protected int translateFromPreviousFilter(int row) {
  264.         return mapTowardView(row);
  265.     }
  266.     /**
  267.      * Returns the row in the previous filter that maps to the specified row in
  268.      * this filter. If there is no previous filter in the pipeline, this returns
  269.      * the row in the data model that maps to the specified row in this filter.
  270.      * This method is called from
  271.      * {@link org.jdesktop.swingx.decorator.Filter#convertRowIndexToModel(int) convertRowIndexToModel}
  272.      *
  273.      * @param row a row index in this filter's "view" of the data model
  274.      * @return the row in the previous filter that maps to the specified row in
  275.      * this filter
  276.      */
  277.     @Deprecated /** @todo remove this deprecated method; use mapTowardModel() instead */
  278.     protected int translateToPreviousFilter(int row) {
  279.         return mapTowardModel(row);
  280.     }
  281.     /**
  282.      * returns to filter to use for accessing input.
  283.      * That's the previous (model is first) filter if this is 
  284.      * part of a pipeline or null if this is standalone or the first
  285.      * in the pipeline.
  286.      * 
  287.      * @return
  288.      */
  289.     private Filter getMappingFilter() {
  290.         Filter filter = null;
  291.         if (pipeline != null) {
  292.             filter = pipeline.previous(this);
  293.         }
  294.         return filter;
  295.     }
  296.     
  297.     /**
  298.      * Refreshes the internal state of the filter, optionally resetting the
  299.      * cache of existing row mappings from this filter to the previous filter.
  300.      * Always performs the {@link #filter() filter} operation and regenerates
  301.      * row mappings from the previous filter. If this filter is bound to a filter
  302.      * pipeline (as most filters are), it also triggers a
  303.      * {@link org.jdesktop.swingx.decorator.FilterPipeline#filterChanged(org.jdesktop.swingx.decorator.Filter) filterChanged}
  304.      * notification.
  305.      *
  306.      * @param reset true if existing row mappings from this filter to the previous
  307.      * filter should be reset; false, if the existing row mappings should be preserved.
  308.      */
  309.     protected void refresh(boolean reset) {
  310.         if (reset) {
  311.             reset();
  312.         }
  313.         filter();
  314.         // trigger direct notification; will cascade to next in pipeline, if any
  315.         if (pipeline != null) {
  316.             if (pipeline.contains(this)) {
  317.                 pipeline.filterChanged(this);
  318.                 return;
  319.             }
  320.         }
  321.         if (adapter != null) {
  322.             adapter.refresh();
  323.         }
  324.     }
  325.     /**
  326.      * Binds this filter to the specified <code>ComponentAdapter</code>.
  327.      * Called by {@link org.jdesktop.swing.decorator.FilterPipeline#bind(org.jdesktop.swing.decorator.ComponentAdapter) FilterPipeline.bind()}.
  328.      *
  329.      * @param adapter adapter that this filter is bound to
  330.      */
  331.     protected void assign(ComponentAdapter adapter) {
  332.         if (adapter == null) {
  333.             throw new IllegalArgumentException("null adapter");
  334.         }
  335.         if (this.adapter == null) {
  336.             this.adapter = adapter;
  337.         }
  338.         else if (this.adapter != adapter){
  339.             throw new IllegalStateException("Already bound to another adapter");
  340.         }
  341.     }
  342.     /**
  343.      * Binds this filter to the specified filter pipeline.
  344.      * Called by {@link org.jdesktop.swing.decorator.FilterPipeline#bind(org.jdesktop.swing.decorator.ComponentAdapter) FilterPipeline.bind()}.
  345.      *
  346.      * @param pipeline the filter pipeline that this filter is bound to
  347.      */
  348.     final void assign(FilterPipeline pipeline) {
  349.         /** NOTE: JXTable.resetSorter may pass in null for filter pipeline!
  350.         if (pipeline == null) {
  351.             throw new IllegalArgumentException("null pipeline");
  352.         }
  353. */
  354.         if ((this.pipeline == null) || (pipeline == null)) {
  355.             this.pipeline = pipeline;
  356.         }
  357.         else if (this.pipeline != pipeline) {
  358.             throw new IllegalStateException("Already bound to another pipeline");
  359.         }
  360.     }
  361.     void assign(FilterPipeline pipeline, int i) {
  362.         if (order >= 0) {
  363.             throw new IllegalArgumentException("Element " + i +
  364.             " is part of another pipeline.");
  365.         }
  366.         this.order = i;
  367.         assign(pipeline);
  368.     }
  369.     protected FilterPipeline getPipeline() {
  370.         return pipeline;
  371.     }
  372. }