About extended data models
blabno Aug 19, 2010 3:20 AMHi,
I'm developing another component, which could use ExtendedDataModel that would use my custom Range (the SquareRange(startX,startY,endX,endY)).
I've looked around RF sources to see how datamodels are used and found out that there are some assumptions made.
I.e.: org.ajax4jsf.model.SequenceDataModel
It casts Range to SequenceRange without any check if it is instance of SequenceRange, and there is no mentioning about acceptable Range in javadoc.
I think it is dangerous to do check in UIComponent if datamodel is instance of ExtendedDataModel and then send there some custom implementation of Range.
I also have question about using extended data model by UIComponent. If I want to retrive data restricted by SquareRange (my custom implementation) from datamodel (also my custom impl), should i store keys passed to "process" method of DataVisitor by datamodel and then retrive data from datamodel according to set of passed keys, or should I assume, that if I pass SquareRange to "walk" method then datamodel will filter itself and I can iterate over all rowIndexes?
Here is my solution according to first approach. Could you comment if it is right?
public List<Map<String, Object>> getData(int startX, int startY, int endX, int endY) throws IOException { ELContext elContext = getFacesContext().getELContext(); ValueExpression valueExpression = getFacesContext().getApplication().getExpressionFactory().createValueExpression(getFacesContext().getELContext(), "#{" + getVar() + "}", Object.class); List<Map<String, Object>> data = new ArrayList<Map<String, Object>>(); DataModel dataModel = getDataModel(); List<Object> elements = new ArrayList<Object>(); if (dataModel instanceof ExtendedDataModel) { final List<Object> keys = new ArrayList<Object>(); DataVisitor visitor = new DataVisitor() { public void process(FacesContext context, Object rowKey, Object argument) throws IOException { keys.add(rowKey); } }; ((ExtendedDataModel) dataModel).walk(getFacesContext(), visitor, new SquareRange(startX, startY, endX, endY), null); for (Object key : keys) { ((ExtendedDataModel) dataModel).setRowKey(key); if (dataModel.isRowAvailable()) { elements.add(dataModel.getRowData()); } } } else { for (int i = 0; i < dataModel.getRowCount(); i++) { dataModel.setRowIndex(i); if (dataModel.isRowAvailable()) { elements.add(dataModel.getRowData()); } } } for (Object element : elements) { valueExpression.setValue(elContext, element); Map<String, Object> firstDataElement = new HashMap<String, Object>(); for (UIComponent child : getChildren()) { if (child instanceof UICoordinatesGridItem) { UICoordinatesGridItem item = (UICoordinatesGridItem) child; if (!item.isRendered()) { continue; } firstDataElement.put("x", item.getX()); firstDataElement.put("y", item.getY()); if (item.getText() != null) { firstDataElement.put("text", item.getText()); } if (item.getStyleClass() != null) { firstDataElement.put("className", item.getStyleClass()); } data.add(firstDataElement); } } } valueExpression.setValue(elContext, null); return data; }
And here is ExtendedDataModel implementation:
/** This is inner class */ private class CustomDataModel extends SequenceDataModel { public CustomDataModel() { /** seats is attribute of outer class */ super(new ListDataModel(seats)); } @Override public void walk(FacesContext context, DataVisitor visitor, Range range, Object argument) throws IOException { SquareRange squareRange = null; if (range instanceof SquareRange) { squareRange = (SquareRange) range; } if (squareRange == null) { super.walk(context, visitor, new SequenceRange(0, -1), argument); } else { for (int i = 0; i < seats.size(); i++) { Seat seat = seats.get(i); if (squareRange.getStartX() <= seat.getSeatNr() && seat.getSeatNr() <= squareRange.getEndX() && squareRange.getStartY() <= seat.getRow() && seat.getRow() <= squareRange.getEndY()) { visitor.process(context, i, argument); } } } } }