Rich:datascroller does not show the correct number of pages when used with 
ExtendedDataModel
--------------------------------------------------------------------------------------------

                 Key: RF-4283
                 URL: https://jira.jboss.org/jira/browse/RF-4283
             Project: RichFaces
          Issue Type: Bug
    Affects Versions: 3.0.0
            Reporter: Hristo Mitkov
            Priority: Critical


Rich:datascroller cannnot be set to show the correct number of pages when using 
an ExtendedDataModel. The reason for this is that ListSequenceDataModel is used 
for calculating the number of pages instead of ExtendedDataModel.
I have TestDataModel class which extends SerializableDataModel where in 
wrappedData I return just 10 elements but my getRowCount method returns the 
number of all records in the database which is 500. The datascroller though 
shows that there is only one page.
I debug the richfaces code to see how the datascroller is rendered.
This is done mainly in DatascrollerTemplate and DataScrollerRenderer in package 
org.richfaces.renderkit.html. As expected the datascroller uses the DataModel 
of the DataTable to calculate the number of pages:
org.richfaces.component.UIDatascroller.getRowCount(UIData data)
and after:
UIDataAdapter.getRowCount(){
... return getExtendedDataModel().getRowCount();
}

Here getExtendedDataModel() returns an instance of ModifiableModel which field 
"originalModel" contains my custom TestDataModel. So 
modifiableModel.getOriginalModel.getRowCount will return 500 as I need. But 
look at the implementation of modifiableModel.getRowCount:

public int getRowCount() {
return delegate.getRowCount();
}

!!!???
delegate is an instance of ListSequenceDataModel which contains the list 
wrappedKeys. So getRowCount() returns wrappedKeys.size() which is 10 so the 
datascroller renders with only one page.
The correct implementation of modifiableModel.getRowCount should be:

public int getRowCount() {
return originalModel.getRowCount();
}

At the time of rendering the dataTable when the model is created () both 
fields: modifiableModel.originalModel and modifiableModel.delegate are set to 
TestDataModel. But at some point delegate is set to ListSequenceDataModel and 
returns the size of the list.
Another thing is that there is no way to set the number of pages directly to 
the UIDatascroller component either by an attribute or by the API 

Here is an example code:

This is the datamodel class:

@Name("testDataModel")
@Scope(ScopeType.SESSION)
public class TestDataModel extends SerializableDataModel {

        private Integer currentPk;

        private boolean detached = false;
        private boolean descending;
        private List<Integer> wrappedKeys = null;
        private final Map<Integer, Container> wrappedData = new 
HashMap<Integer, Container>();
        private int rowCount=0;

        @Override
        public Object getRowKey() {
                return currentPk;
        }
        @Override
        public void setRowKey(Object key) {
                this.currentPk = (Integer) key;
        }
        @In(create = true)
        private ContainerService containerManager;

        @Override
        public void walk(FacesContext context, DataVisitor visitor, Range 
range, Object argument) throws IOException {
                if (detached){
                        for (Integer key : wrappedKeys) {
                                setRowKey(key);
                                visitor.process(context, key, argument);
                        }
                } else {
                        int firstRow = ((SequenceRange) range).getFirstRow();
                        int numberOfRows = 10;// ((SequenceRange) 
range).getRows();
                        wrappedKeys = new ArrayList<Integer>();

                        for (Container container : 
containerManager.findContainersPaged(firstRow, numberOfRows, null, null)) {
                                wrappedKeys.add(container.getId());
                                wrappedData.put(container.getId(), container);
                                visitor.process(context, container.getId(), 
argument);
                        }
                }
        }
        @Override
        public SerializableDataModel getSerializableModel(Range range) {
                if (wrappedKeys != null) {
                        detached = true;
                        return this;
                }
                return null;
        }

        @Override
        public void update() {
                detached = false;
        }
        
        @Override
        public int getRowCount() {
                        if(rowCount==0){
                                rowCount=containerManager.countContainers();
                        }
             // Here for test and debug purposes you can comment the code above 
and just do: 
             // return 500;

                return rowCount;
        }

        @Override
        public Object getRowData() {
                
                if (currentPk == null) {
                        return null;
                } else {
                        Container container = wrappedData.get(currentPk);
                        if (container == null) {
                                container = 
containerManager.getContainerById(currentPk);
                                wrappedData.put(currentPk, container);
                        }
                        return container;
                }
        }
        @Override
        public boolean isRowAvailable() {
                if (currentPk == null) {
                        return false;
                }
                if (wrappedKeys.contains(currentPk)) {
                        return true;
                }
                if (wrappedData.entrySet().contains(currentPk)) {
                        return true;
                }
                if (containerManager.getContainerById(currentPk) != null) {
                        return true;
                }
                return false;
        }
        @Override
        public void setRowIndex(int index) {
        }

        @Override
        public int getRowIndex() {
                throw new UnsupportedOperationException();
        }

        @Override
        public Object getWrappedData() {
                throw new UnsupportedOperationException();
        }

        @Override
        public void setWrappedData(java.lang.Object data) {
                throw new UnsupportedOperationException();
        }

}

Thisis the seam managed bean. It can be any kind of jsf managed bean:

@Stateful
@Name("containerManager")
public class ContainerManager  implements ContainerService {

        public Integer countContainers() {
              //For test and debug purposes you can comment the following code 
and just: return 500;
                Session session = (Session) entityManager.getDelegate();
                Criteria criteria = 
session.createCriteria(Container.class).setProjection(Projections.rowCount());
                Integer containerCount = (Integer) criteria.uniqueResult();
                return containerCount;
          }

        public List<Container> findContainersPaged(int firstRow, int 
numberOfRows, String sortField, boolean descending) {
                List<Container> container = entityManager.createQuery("select c 
from Container c 
").setFirstResult(firstRow).setMaxResults(numberOfRows).getResultList();
                return container;
        }
        public Container getContainerById(Integer id) {
                return entityManager.find(Container.class, id);
        }
 }

This is the page

<rich:dataTable id="containerList" rows="10"  var="c" value="#{testDataModel}">

                                        <rich:column>
                                                <f:facet name="header">
                                                        <h:outputText 
value="Name" />
                                                </f:facet>
                                                <h:outputText value="#{c.name}" 
 />
                                        </rich:column>
</rich:dataTable>
<rich:datascroller align="left" for="containerList" maxPages="10" 
rendered="true" />

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: 
https://jira.jboss.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        
_______________________________________________
richfaces-issues mailing list
[email protected]
https://lists.jboss.org/mailman/listinfo/richfaces-issues

Reply via email to