Before reading this article I strongly recommend you to read the below two articles of Arjan Tijms:
JSF 2.3 new feature: registrable DataModels
With @FacesDataModel custom DataModel wrappers can be registered, but those wrappers can not (yet)
override any of the build-in types.
Usage involve two steps:
Usage involve two steps:
- register your wrapper by
annotating it with @FacesDataModel
- designates the type this
wrapper is able to handle via forClass
attribute
WRAPPER MODEL
@FacesDataModel(forClass =
fooCollection.class)
public class FooCollectionModel<E>
extends DataModel<E> {
@Override
public E getRowData() {
// access FooCollection here
}
@Override
public void setWrappedData(Object fooCollection)
{
// likely just store fooCollection
}
// Other methods omitted for brevity
}
USE COLLECTION IN YOUR BEANS
@Named
public class
FooBean {
public FooCollection<Foo> getFoo() {
// return fooCollection
}
}
IN DATA TABLE IT WORKS OUT OF THE BOX
<h:dataTable
value="#{fooBean.foo}" var="t">
<h:column>
#{t} | #{t.property}
</h:column>
</h:dataTable>
For
example, let's define an ArraySet as below:
public class
ArraySet<T> implements Cloneable, Serializable {
private ArrayList list;
public ArraySet() {
list =
new ArrayList();
}
public ArraySet(Collection collection) {
list =
new ArrayList();
Iterator iterator = collection.iterator();
if
(collection instanceof Set) {
while (iterator.hasNext()) {
list.add(iterator.next());
}
} else {
while (iterator.hasNext()) {
add(iterator.next());
}
}
}
public Iterator iterator() {
return
list.iterator();
}
public int size() {
return
list.size();
}
public final boolean add(Object element) {
boolean
modified;
if
(modified = !list.contains(element)) {
list.add(element);
}
return
modified;
}
public boolean remove(Object element) {
return
list.remove(element);
}
public boolean isEmpty() {
return
list.isEmpty();
}
public boolean contains(Object element) {
return
list.contains(element);
}
public void clear() {
list.clear();
}
public Object get(int index) {
return
list.get(index);
}
@Override
public Object clone() throws
CloneNotSupportedException {
try {
ArraySet newSet = (ArraySet) super.clone();
newSet.list = (ArrayList) list.clone();
return newSet;
} catch
(CloneNotSupportedException e) {
throw new InternalError();
}
}
}
For this collection we can write a sortable model, as below:
@FacesDataModel(forClass
= ArraySet.class)
public final
class SortDataModel<T> extends DataModel<T> {
private static final Logger LOG =
Logger.getLogger(SortDataModel.class.getName());
private int index = -1;
private ArraySet list;
private Integer[] rows;
public SortDataModel() {
LOG.info("Using the SortDataModel
!");
}
public SortDataModel(List<T> list) {
super();
LOG.info("Using
the SortDataModel !");
setWrappedData(list);
}
@Override
public boolean isRowAvailable() {
if
(list == null) {
return (false);
} else
if ((index >= 0) && (index < list.size())) {
return (true);
} else
{
return (false);
}
}
@Override
public int getRowCount() {
if
(list == null) {
return (-1);
}
return
(list.size());
}
@Override
public T getRowData() {
if (list == null) {
return (null);
} else if (!isRowAvailable()) {
try
{
throw new Exception();
}
catch (Exception ex) {
Logger.getLogger(SortDataModel.class.getName()).log(Level.SEVERE, null,
ex);
}
} else
{
return ((T) list.get(index));
}
return
(null);
}
@Override
public int getRowIndex() {
return (index);
}
@Override
public void setRowIndex(int rowIndex) {
if (rowIndex < -1) {
throw new IllegalArgumentException();
}
int old = index;
if ((0 <= rowIndex) && (rowIndex
< rows.length)) {
index = rows[rowIndex];
} else {
index = rowIndex;
}
if
(list == null) {
return;
}
DataModelListener[] listeners =
getDataModelListeners();
if ((old != index) && (listeners !=
null)) {
Object rowData = null;
if (isRowAvailable()) {
rowData = getRowData();
}
DataModelEvent event = new
DataModelEvent(this, index, rowData);
int n = listeners.length;
for (int i = 0; i < n; i++) {
if (null != listeners[i]) {
listeners[i].rowSelected(event);
}
}
}
}
@Override
public Object getWrappedData() {
return
(this.list);
}
@Override
public void setWrappedData(Object data) {
if
(data == null) {
list = null;
setRowIndex(-1);
} else
{
list = (ArraySet) data;
initRows();
index = -1;
setRowIndex(0);
sortThis((T key_1, T key_2) -> {
if (key_1 == null ? key_2 == null :
key_1.equals(key_2)) {
return 1;
}
if (key_1 == null) {
return -1;
}
if (key_2 == null) {
return 1;
}
return
String.valueOf(key_1).compareTo(String.valueOf(key_2));
});
}
}
public void sortThis(final Comparator<T>
comparator) {
Comparator<Integer> rowc = (Integer key_1,
Integer key_2) -> {
T
key_1_data = getData(key_1);
T
key_2_data = getData(key_2);
return
comparator.compare(key_1_data, key_2_data);
};
Arrays.sort(rows, rowc);
}
private T getData(int row) {
int baseRowIndex = getRowIndex();
setRowIndex(row);
T newRowData = getRowData();
setRowIndex(baseRowIndex);
return newRowData;
}
private void initRows() {
int rowCount = getRowCount();
if (rowCount != -1) {
this.rows = new Integer[rowCount];
for (int i = 0; i < rowCount; ++i) {
rows[i] = i;
}
}
}
}
Now, let's fill up an ArraySet:
String
players[] = {"Rafa", "Federer", "Tonga", "Novak",
"Murray"};
ArraySet
arraySet = new ArraySet(Arrays.asList(players));
And, in the JSF page we can used it like below:
<h:dataTable
value="#{playerBean.arraySet}" var="t"
border="1">
<h:column>
<f:facet name="header">Player:</f:facet>
#{t}
</h:column>
</h:dataTable>
And, the output will be:
Niciun comentariu :
Trimiteți un comentariu