2012-11-13 108 views
2

我还有一个问题,与我在1月份发布的问题有些相关。我有一个丰富的列表:extendedDataTable组件,它随时更新,因为用户在一个单独的文本框中键入他的搜索条件(即用户键入前4个字符,并且在他继续输入时,结果列表更改)。最后,当我使用RichFaces 3时,它工作正常,但是当我升级到RichFaces 4时,我遇到了各种编译问题。下面是一些不再通行,没有合适的替代品,这些,似乎:RichFaces 4中的ExtendedDataTable:DataModel处理

org.richfaces.model.DataProvider 
org.richfaces.model.ExtendedTableDataModel 
org.richfaces.model.selection.Selection 
org.richfaces.model.selection.SimpleSelection 

这是它以前:

这是应该触发搜索逻辑输入文本:

<h:inputText id="firmname" value="#{ExtendedTableBean.searchValue}"> 
    <a4j:support ajaxSingle="true" eventsQueue="firmListUpdate" 
       reRender="resultsTable" 
       actionListener="#{ExtendedTableBean.searchForResults}" event="onkeyup" /> 
</h:inputText> 

动作监听器是什么应该更新列表。这里是extendedDataTable,右侧的inputText下面:

<rich:extendedDataTable tableState="#{ExtendedTableBean.tableState}" var="item" 
         id="resultsTable" value="#{ExtendedTableBean.dataModel}"> 

     ... <%-- I'm listing columns here --%> 

</rich:extendedDataTable> 

而这里的后端代码,在这里我用我的数据模型处理:

/* 
* To change this template, choose Tools | Templates 
* and open the template in the editor. 
*/ 

package com.beans; 

import java.io.FileInputStream; 
import java.util.ArrayList; 
import java.util.Collections; 
import java.util.ConcurrentModificationException; 
import java.util.List; 
import java.util.Properties; 
import java.util.concurrent.CopyOnWriteArrayList; 
import javax.faces.context.FacesContext; 
import javax.faces.event.ActionEvent; 
import org.richfaces.model.DataProvider; 
import org.richfaces.model.ExtendedTableDataModel; 

public class ExtendedTableBean {  
    private String sortMode="single"; 
    private ExtendedTableDataModel<ResultObject> dataModel; 
    //ResultObject is a simple pojo and getResultsPerValue is a method that 
    //read the data from the properties file, assigns it to this pojo, and 
    //adds a pojo to the list 

    private Object tableState; 
    private List<ResultObject> results = new CopyOnWriteArrayList<ResultObject>(); 
    private List<ResultObject> selectedResults = 
             new CopyOnWriteArrayList<ResultObject>(); 

    private String searchValue; 

    /** 
    * This is the action listener that the user triggers, by typing the search value 
    */ 
    public void searchForResults(ActionEvent e) { 
     synchronized(results) { 
      results.clear(); 
     }   

     //I don't think it's necessary to clear results list all the time, but here 
     //I also make sure that we start searching if the value is at least 4 
     //characters long 
     if (this.searchValue.length() > 3) { 
      results.clear(); 
      updateTableList(); 
     } else { 
      results.clear(); 
     } 

     dataModel = null; // to force the dataModel to be updated. 
    } 

    public List<ResultObject> getResultsPerValue(String searchValue) { 
     List<ResultObject> resultsList = new CopyOnWriteArrayList<ResultObject>(); 

     //Logic for reading data from the properties file, populating ResultObject 
     //and adding it to the list 

     return resultsList; 
    } 

    /** 
    * This method updates a firm list, based on a search value 
    */ 
    public void updateTableList() { 
     try {    
      List<ResultObject> searchedResults = getResultsPerValue(searchValue); 

      //Once the results have been retrieved from the properties, empty 
      //current firm list and replace it with what was found. 

      synchronized(firms) { 
       firms.clear(); 
       firms.addAll(searchedFirms); 
      } 
     } catch(Throwable xcpt) { 
      //Exception handling 
     } 
    } 

    /** 
    * This is a recursive method, that's used to constantly keep updating the 
    * table list. 
    */ 
    public synchronized ExtendedTableDataModel<ResultObject> getDataModel() { 
     try { 
      if (dataModel == null) { 
       dataModel = new ExtendedTableDataModel<ResultObject>(
           new DataProvider<ResultObject>() { 
            public ResultObject getItemByKey(Object key) { 
             try { 
              for(ResultObject c : results) { 
               if (key.equals(getKey(c))){ 
                return c; 
               } 
              } 
             } catch (Exception ex) { 
              //Exception handling 
             } 
             return null; 
            } 

            public List<ResultObject> getItemsByRange(
               int firstRow, int endRow) { 
             return Collections.unmodifiableList(results.subList(firstRow, endRow)); 
            } 

            public Object getKey(ResultObject item) { 
             return item.getResultName(); 
            } 

            public int getRowCount() { 
             return results.size(); 
            } 
           }); 
      } 
     } catch (Exception ex) { 
      //Exception handling  
     } 

     return dataModel; 
    } 

    //Getters and setters 

} 

现在的类ExtendedTableDataModel和DataProvider中不再可用,我应该用什么来代替? RichFaces论坛声称这里没有任何东西,开发人员在他们自己身上非常多(意味着他们必须自己执行)。有没有人有任何其他想法或建议?

再次感谢您的所有帮助和再次,对于冗长的问题抱歉。

回答

1

您可以转换您的数据模型来扩展摘要org.ajax4jsf.model.ExtendedDataModel,而实际上这是一个更健壮和高性能的数据模型,可用于<rich:extendedDataTable/>。现有的模式下新的粗略翻译(我已经决定要使用现有的ExtendedDataModel<ResultObject>作为基础数据源,而不是results列表展示翻译):

public class MyDataModel<ResultObject> extends ExtendedDataModel<ResultObject>{ 

    String currentKey; //current row in the model 
    Map<String, ResultObject> cachedResults = new HashMap<String, ResultObject>(); // a local cache of search/pagination results 
    List<String> cachedRowKeys; // a local cache of key values for cached items 
    int rowCount; 
    ExtendedTableDataModel<ResultObject> dataModel; // the underlying data source. can be anything 


    public void setRowKey(Object item){ 
    this.currentKey = (ResultObject)item.getResultName(); 
    } 

    public void walk(FacesContext context, DataVisitor visitor, Range range, Object argument) throws IOException { 
    int firstRow = ((SequenceRange)range).getFirstRow(); 
    int numberOfRows = ((SequenceRange)range).getRows(); 
    cachedRowkeys = new ArrayList<String>(); 
    for (ResultObject result : dataModel.getItemsByRange(firstRow,numberOfRows)) { 
     cachedRowKeys.add(result.getResultName()); 
     cachedResults.put(result.getResultName(), result); //populate cache. This is strongly advised as you'll see later. 
     visitor.process(context, result.getResultName(), argument); 
     } 
    } 

    } 


public Object getRowData() { 
    if (currentKey==null) { 
     return null; 
    } else { 
     ResultObject selectedRowObject = cachedResults.get(currentKey); // return result from internal cache without making the trip to the database or other underlying datasource 
     if (selectedRowObject==null) { //if the desired row is not within the range of the cache 

      selectedRowObject = dataModel.getItemByKey(currentKey); 
      cachedResults.put(currentKey, selectedRowObject); 
      return selectedRowObject; 
     } else { 
      return selectedRowObject; 
     } 
    } 

public int getRowCount(){ 
if(rowCount == 0){ 
    rowCount = dataModel.getRowCount(); //cache row count 
    return rowCount; 
    } 
    return rowCount 

} 

那些是3个最该班的重要方法。还有其他一些方法,基本上可以从传统版本继承,你不需要担心。如果您将JSF状态保存到客户端,那么您可能对org.ajax4jsf.model.SerializableDataModel有兴趣进行序列化。查看here的示例。这是一个旧博客,但逻辑仍然适用。

与此无关,您目前实施的getRowData在生产级应用程序中表现不佳。必须遍历每个元素以返回结果?尝试一个更好的搜索算法。