I use the following to view large tables where fetching the all the results is 
not feasible.  It has about 1 million rows.

It does assume that you object implements the interface Idable  shown next.

  | 
  | import java.io.IOException;
  | import java.io.Serializable;
  | import java.util.ArrayList;
  | import java.util.HashMap;
  | import java.util.List;
  | import java.util.Map;
  | 
  | import javax.faces.context.FacesContext;
  | 
  | import org.ajax4jsf.model.DataVisitor;
  | import org.ajax4jsf.model.ExtendedDataModel;
  | import org.ajax4jsf.model.Range;
  | import org.ajax4jsf.model.SequenceRange;
  | import org.jboss.seam.ScopeType;
  | import org.jboss.seam.annotations.Logger;
  | import org.jboss.seam.annotations.Out;
  | import org.jboss.seam.log.Log;
  | 
  | import my.package.Idable;
  | 
  | public abstract class BaseExtendedDataModel<T,ID extends Serializable> 
extends ExtendedDataModel implements  BaseExtendedDataModelDAO<T, ID>{
  | 
  |     private @Logger Log log;
  |     
  |     @Out(scope=ScopeType.CONVERSATION, required=false)
  |     public List<T> listRow;
  |     
  |     private ID currentId;
  |     private Map<ID, T> wrappedData = new HashMap<ID, T>();
  |     private List<ID> wrappedKeys;
  |     private Long rowCount; // better to buffer row count locally
  |     
  |     public abstract Long getCount();
  |     public abstract List<T> getList(Integer firstRow, Integer maxResults);
  |     public abstract T findById(ID id);
  |     
  |     public void wrap(FacesContext context, DataVisitor visitor, Range 
range, Object argument, List<T> list) throws IOException
  |     {
  |             wrappedKeys = new ArrayList<ID>();
  |             wrappedData = new HashMap<ID, T>();
  |             for (T row : list)
  |             {
  |                     Idable idable = (Idable) row;
  |                     ID id = (ID) idable.getId();
  |                     wrappedKeys.add(id);
  |                     wrappedData.put(id, row);
  |                     visitor.process(context, id, argument);
  |             }               
  |     }       
  |     
  |     public boolean hasById(ID id) 
  |     {
  |             for (T row : listRow) 
  |             {
  |                     Idable idable = (Idable) row;
  |                     Long rowId = (Long) idable.getId();
  |                     if (rowId.equals(id))
  |                     {
  |                             return true;
  |                     }
  |             }
  |             return false;           
  |     }
  |     
  |     @Override
  |     public void walk(FacesContext context, DataVisitor visitor, Range 
range, Object argument) throws IOException
  |     {               
  |             int firstRow = ((SequenceRange) range).getFirstRow();
  |             int maxResults = ((SequenceRange) range).getRows();
  |             wrap(context, visitor, range, argument, getList(firstRow, 
maxResults));
  |     }
  |     
  |     /*
  |      * This method normally called by Visitor before request Data Row.
  |      */ 
  |     @Override
  |     public void setRowKey(Object key) 
  |     {
  |             this.currentId = (ID) key;
  |     }
  |     
  |     @Override
  |     public int getRowCount() 
  |     {
  |       if(rowCount == null) 
  |         return (rowCount = this.getCount()).intValue();  
  |       else 
  |         return rowCount.intValue();
  |     }
  |     
  |     @Override
  |     public boolean isRowAvailable() 
  |     {
  |             if (currentId == null) {
  |                     return false;
  |             } else {
  |                     return hasById(currentId);
  |             }
  |     }
  |     
  |     /**
  |      * This is main way to obtain data row. It is intensively used by 
framework.
  |      * We strongly recommend use of local cache in that method.
  |      */
  |     @Override
  |     public Object getRowData() {
  |             if (currentId == null) {
  |                     return null;
  |             } else {
  |                     T ret = wrappedData.get(currentId);
  |                     if (ret == null) {
  |                             ret = this.findById(currentId);
  |                             wrappedData.put(currentId, ret);
  |                             return ret;
  |                     } else {
  |                             return ret;
  |                     }
  |             }
  |     }
  |     
  |     /**
  |      * Unused rudiment from old JSF staff. 
  |      */
  |     @Override public Object getWrappedData() { throw new 
UnsupportedOperationException(); }
  |     @Override public int getRowIndex() { throw new 
UnsupportedOperationException(); }
  |     @Override public void setRowIndex(int rowIndex) { throw new 
UnsupportedOperationException(); }
  |     @Override public void setWrappedData(Object data) { throw new 
UnsupportedOperationException(); }
  |     
  |     /**
  |      * Unused update data. 
  |      */
  | //  @Override public void update() { throw new 
UnsupportedOperationException(); }
  | 
  |     /**
  |      * TODO if this is never called by the framework why is it necessary.
  |      */ 
  |     @Override public Object getRowKey() { if (true) throw new 
UnsupportedOperationException(); return currentId; }
  | 
  | }
  | 
  | public interface BaseExtendedDataModelDAO<T, ID> {
  |   | 
  |   | }
  | 
  | 
Idable interface

  | public interface Idable
  | {
  |     public Long getId();
  | }
  | 

I extend the base class as shown below.




  | import java.util.List;
  | 
  | import org.jboss.seam.annotations.In;
  | import org.jboss.seam.annotations.Name;
  | 
  | import mypackage.general.access.Access;
  | 
  | @Name("accessExtendedDataModel")
  | public class AccessExtendedDataModel extends BaseExtendedDataModel<Access, 
Long>  
  | {
  |     @In(create=true) AccessDAO accessDAO;
  |     
  |     @Override
  |     public Long getCount() 
  |     {               
  |       return accessDAO.getCount();
  |     }
  |     
  |     @Override
  |     public Access findById(Long id) 
  |     {               
  |       return accessDAO.findById(id);
  |     }
  |     
  |     @Override
  |     public List<Access> getList(Integer firstRow, Integer maxResults)
  |     {
  |             return listRow = accessDAO.getRange(firstRow, maxResults);
  |     }
  | 

Then in the facelets page


  |   <a4j:form>
  |     <rich:datascroller for="accessList" />
  |     <rich:spacer height="10" />
  |     <rich:dataTable id="accessList"
  |                  value="#{accessExtendedDataModel}"
  |                    var="accessL"
  |             styleClass="f_table"
  |             rowClasses="tr0,tr1"
  |                   rows="30">
  |       <rich:column id="id">
  |         <f:facet name="header">id</f:facet>
  |         <h:outputText value="#{accessL.id}" />
  |       </rich:column>
  |       <rich:column id="User">
  |         <f:facet name="header">User</f:facet>
  |         <h:outputText value="#{accessL.usr.usr}" />
  |       </rich:column>
  |     </rich:dataTable>
  |   </a4j:form>
  | 

The scroller is now connected to the datatable.  This is a first pass and was 
adapted for an example in the Richfaces cvs I took a while back.

The paging is all done with Ajax and only 30 objects are loaded at a time.

Any suggestions for improvement are most welcome.


View the original post : 
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4112998#4112998

Reply to the post : 
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&p=4112998
_______________________________________________
jboss-user mailing list
jboss-user@lists.jboss.org
https://lists.jboss.org/mailman/listinfo/jboss-user

Reply via email to