Matrix Model

From Documentation
Revision as of 07:20, 11 April 2012 by Jumperchen (talk | contribs)
  • Available for ZK:
  • http://www.zkoss.org/product/zkhttp://www.zkoss.org/whyzk/zkeeVersion ee.png

Here we describe how to implement a matrix model (MatrixModel). For the concept of component, model and renderer, please refer to the Model-driven Display section.

By default, ZK does not provide a built-in model implementation class for MatrixModel because Biglistbox is designed to handle unlimited data set, therefore, there is no need to handle model data in memory. This usage is application-dependent and varies from case to case. However, you can extend your own implementation from the AbstractListModel skeleton class.

To implement a MatrixModel needs to consider the performance issue that handles a huge data set in memory with Java Collection Framework. The issue is when using the default implementation of Java Collection Framework as it goes through every entry to gather the value of hashCode when searching the key in Map/Set or to check every entry for equals and toString functions. This implementation method greatly reduces the performance of Biglistbox, therefore, to use the Biglistbox component with MatrixModel, we need to implement a clever and simple List for traversing huge data sets.

FakerKeyList

In this example, we create a FakerKeyList to implement the List interface for MatrixModel to handle the partial big data in memory.

private class FakerKeyList<T> extends AbstractList<T> {
	final int _size;
	Map<String, T> _updateCache = new HashMap<String,T> ();
	final Fun<?> _fn;
	final String _key;

	public FakerKeyList(int size, int key, Fun<?> fn) {
		_size = size;
		_key = key + "_" + size;
		_fn = fn;
	}

	@Override
	public T get(int index) {
		// if changed, returns the changed value
		Object val = _updateCache.get(String.valueOf(index));
		if (val != null)
			return (T) val;
		return (T) _fn.apply(index);
	}

	@Override
	public int hashCode() {
		return _key.hashCode();
	}
		
	@Override
	public boolean equals(Object obj) {
		if (obj == this)
			return true;
		if (obj instanceof FakerKeyList) {
			return _key.equals(((FakerKeyList)(obj))._key);
		}
		return false;
	}
	
	@Override
	public String toString() {
		return _key;
	}

	// omitted...
}

As you can see, we use a key string as the key for toString, hashCode, and equals methods to speed up searching time. Fun class on the other hand, is a handy class to render the model data for this example.

FakerMatrixModel

In this example, we create a FakerMatrixModel to implement MatrixModel. Following is the fragment code:

public class FakerMatrixModel<Head extends List, Row extends List, Cell, Header> extends
		AbstractListModel<Row> implements MatrixModel<Row, Head, Cell, Header>, Sortable {

	// omitted...

	private boolean _sortDir = true;

	@Override
	public Row getElementAt(int index) {
		final int rowIndex = _sortDir ? index : getSize() - index - 1; // handle the sorting
		final String key = String.valueOf(rowIndex);
		List<String> value = _rowCache.get(key);
		if (value == null) {
			value = new FakerKeyList<String>(_colSize, rowIndex, new Fun() {
				@Override
				public Object apply(int index) {
					return "y = " + rowIndex;
				}});
			_rowCache.put(key, value);
		}
		return (Row) value;
	}

	// omitted...
}

MatrixModel is extended from the ListModel interface and uses the getElementAt(int) method to receive row data from the FakerKeyList object that implements the List interface.

Sortable Model

The MatrixModel can also support Sortable interface. In your implementor class you can just implement the Sortable interface and provide Sortable.sort(Comparator, boolean) and Sortable.getSortDirection(Comparator) methods.

For example,

	public void sort(Comparator cmpr, boolean ascending) {
		_sorting = cmpr;
		_sortDir = ascending;
		fireEvent(ListDataEvent.STRUCTURE_CHANGED, -1, -1);
	}

	@Override
	public String getSortDirection(Comparator cmpr) {
		if (Objects.equals(_sorting, cmpr))
			return _sortDir ? "ascending" : "descending";
		return "natural";
	}

As you can see, we fire a data change event with ListDataEvent.STRUCTURE_CHANGED attribute to notify the component that model data has been changed.

Notify for Data Updates

MatrixModel is the same as ListModel when notify for data updates, please refer to ListMode#Notify_for_Data_Updates

Resource

All of the example above can be found here - Github's FakerMatrixModel source code

Version History

Last Update : 2012/04/11


Version Date Content
6.0.1 March 2012 The Biglistbox and MatrixModel was introduced



Last Update : 2012/04/11

Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.