Looking for Wicket repeater that works only with iterator (without knowing exact result size) - wicket

I am trying to use wicket to display results from nosql database. This means large data sets with unknown size.
I need kind of GridView with paging functionality which DataProvider relies only on iterator and estimated result size (like 100+, which could also mean 500k). Good example would be google search - pagination has max 10 pages, and you can go one by one, or jump few pages ahead/backward.
Does anybody know such component?

I had a very similar problem here. Boris Pavlović pointed out i could use an infinite scrolling solution like this.
But i still ended up using a regular DataView with an IDataProvider with a default wicket ajax page navigator. I limited query results to ~100 (10 per page) and cached the results in the IDataProvider and used the size() on the list. When size() returned same as Maxresults (100) then I give a warning, the user usually doesn't go beyond page 2 (also like google).

My approach to something like that would be the following (that is using the regular DataProvider):
Determine the max displayed pages number (so in the google example, that would be 10 pages)
Whenever size() is called I estimate if there will be more results than [results per page]*[current page] + [max pages]*[results per page];
if yes, then return [results per page] * ([current page] + [max pages]) - 1
else return the exact amount
That would make wicket think that there are [current page] + [max pages] pages worth of results at any given time. So at any given point you would only have to know if there are [max pages] worth of results more, rather than the exact amount of results.
The size() is used to determine the first and count parameter values on the iterator() function, as well as pagination sizes, so it doesn't have to actually be the size of the result set, it can be a value that would indicate how many results you want displayed, and worry about how many more you want displayed when you get closer to that.
However, the intended behaviour of size() is to display the actual size of the results, so any other components or behaviours you use on the GridView should be checked for side-effects, as they could potentially suffer from unexpected results.

I was unable to find lib with such data provider, so I've implemented one - its called IterableGridView
Here is the code: https://github.com/maciejmiklas/cyclop/tree/master/cyclop-wicket-components
Iterable Grid View is based on Wicket's GridView, however it does not work with IDataProvider but with
IterableDataProvider. This new data provider relies only on plain java iterator - size information is not needed, and there is also no need to create range iterators for each page.
final List<String> myGridData = new ArrayList<>();
myGridData.add("value 1");
myGridData.add("value 2");
IterableDataProvider<String> iterableDataProvider = new IterableDataProvider<String>(10) {
#Override
protected Iterator<String> iterator() {
return myGridData.iterator();
}
#Override
public IModel<String> model(String s) {
return Model.of(s);
}
#Override
public void detach() {
}
};
IterableGridView<String> myGrid = new IterableGridView<String>("myGrid", iterableDataProvider) {
#Override
protected void populateEmptyItem(Item<String> item) {
item.add(new Label("myValue"));
}
#Override
protected void populateItem(Item<String> item) {
item.add(new Label("myValue", item.getModelObject()));
}
};
add(myGrid);
myGrid.setItemsPerPage(10);
// you have to use custom pager and not AjaxPagingNavigator
IterablePagingNavigator pager = new IterablePagingNavigator("rowNamesListPager", rowNamesList);
resultTable.add(pager);

Related

How do I use STL std::list with objects?

I want to create linked lists of objects sorted by an object attribute (physical size); but so far it seems I will have to code them myself...
These lists will be short, typically a dozen nodes each; but I may have up to a thousand lists; so I can't afford the extra weight of using std::map's. In fact, I'd be quite happy with single linked list.
But I need the node to be more than just a value.
The key value in my objects is rarely going to change; however elements will have to come out of one list and move to another quite often.
((Actual use: One list per quad, in a quad-tree (as for collision detection, etc); objects sorted by size, as the larger objects are less numerous but need to be picked quickly from larger ranges, so they should come up first in the lists.))
But every example I find for using std::list to maintain sorted lists uses a list of integers as the example; but that's not very useful; what I have is objects that have one value member to be sorted by.
I was thinking of using lower_bound to find the insertion point, then insert the object; but the lower_bound iterator takes a begin, and end, and a plain value as the third argument; I see no mechanism by which I can specify to use a particular member of my objects to sort by.
I could, of course, define a conversion operator,
my_object_type::int(){ return sortby; }
Would that work? Is there a better way?
I seem to have found my answer in this reference:
https://www.geeksforgeeks.org/lower_bound-in-cpp/
under "Syntax 2"; there is provision for a fourth
argument being a comparison functor. So, something
like this should work (not tested yet):
class pnt_proxy
{
int x; //position
int y;
point* real_pnt; //the real point this represents
public:
float sz; //rough largest diagonal across object
}
class pproxy_cmp : public std::binary_function< pnt_proxy, pnt_proxy, bool >
{
public:
bool operator()( pnt_proxy const & a, pnt_proxy const & b ) const
{
return a.sz < b.sz;
}
};
std::list< pnt_proxy > ll;
void insert_sorted( pnt_proxy const & pp )
{
if( ll.size() )
{
std::list<pnt_proxy>::iterator insert_at;
insert_at =
std::lower_bound( ll.begin(), ll.end(), pp, pproxy_cmp() );
ll.insert( insert_at, pp );
}
else ll.push_back( pp );
}

Adding elements to TableViewer from a collection?

So I'm trying to make a simple program that takes in some basic information about a loan, and turns it into an amortization table.
I am using WindowBuilder for this, and thus I have a Tableviewer that is supposed to have a column for Month, interest, payment, ect.
Unfortunately, I can't figure out how to get the table to actually display information. I have a Loan object that generates an ArrayList of month objects (each month being one row of the table), but from what I've read online, it's not as simple as telling the Tableviewer to populate each column with a variable from that arraylist.
I have set my Content Provider to be a Loan object, which contains an Arraylist of Month Objects, and each Month object has a getter for each column.
How do I go about displaying the text in each column?
Thanks.
EDIT:
So, here is the snippet of code from the example given to me below:
colFirstName.setLabelProvider(new ColumnLabelProvider() {
#Override
public String getText(Object element) {
Person p = (Person) element;
return p.getFirstName();
}});
I don't quite understand what is going on here. It's overriding the getText method, and casting the element to the type of element that has their data?
balanceCol.setLabelProvider(new ColumnLabelProvider(){
#Override
public String getText(Object element) {
Loan m = (Loan) element;
return m.getMonthObj().get(0).getMonth();
}
});
When I run this, it almost sorta works. It fills in about half the months, and then I get this error:
java.lang.ClassCastException: model.Month cannot be cast to model.Loan

GXT add filter to store

I'm having problems with a relatively simple piece of code.
I'm trying to set a filter for my store items (store associated with a GridView).
gridStore.addFilter(new StoreFilter<IncidentDto>() {
#Override
public boolean select(Store<IncidentDto> store, IncidentDto parent, IncidentDto item) {
if (item.getDescription().equals("WEEEE-TEST")) {
return true;
} else {
return false;
}
}
});
The problem is the store doesn't filter at all.
Thanks to anyone who will take the time to help me out with this.
Don't forget to enable the filters - this exists so that you can make several filter modifications without actually asking them to act:
gridStore.setEnableFilters(true);
Sorting doesn't have this as there isn't a concept of turning sorting 'off' - items are sorted to have a new order, then they stay that order. In contrast, filters can be turned back off to restore the items that are no longer visible.
If you trace the code, you will notice that the filter is not called in onLoad(). You have to manually call filter();

Programatic CellTable sort in GWT not working

I'm using the ListDataProvider example here as a guide. The columns are sorting fine as expectd based on the provided comparators. I'm trying to programatically apply a sort as alluded to on this line from the example:
// We know that the data is sorted alphabetically by default.
table.getColumnSortList().push(nameColumn);
What this does, is it makes the cell column appear to be sorted with the carrot sort indicator. However, the underlying data isn't sorted. Is there a way to get the table to actually apply the sort progarmatically. I suppose I could use this in conjunction with actually sorting the data via Collections.sort(), but I'd like to avoid that and do it in one place.
You can apply sorting on a column programatically with little exta code. The following code snippet does that -
When ever u set data to the cellTable you have to initialize the ListHandler as below code does -
cellTable.addColumnSortHandler( createColumnSortHandler() );
private ListHandler<T> createColumnSortHandler()
{
final ListHandler<T> listHandler = new ListHandler<T>(listDataProvider.getList());
listHandler.setComparator( sortColumn, comparator );
return listHandler;
}
And when u want to fire the SortEvent execute the following code snippet -
ColumnSortInfo columnSortInfo = new ColumnSortInfo( sortColumn, sortDirection );
cellTable.getColumnSortList().push( columnSortInfo );
ColumnSortEvent.fire( cellTable, cellTable.getColumnSortList());
you have to call setData on grid again.....

List/Object searching in CoffeeScript

I'm trying to get my head around using CoffeeScript comprehensions as efficiently as possible. I think I have basic mapping down -- turning one list into another -- but searching still seems verbose to me.
Say I have a map of items to shops:
shopMap:
toyStore: ["games", "puzzles"]
bookStore: ["novels", "picture books"]
and, given an item, I want to find out which shop it's in. What's the best way of doing that in CoffeeScript?
Here's how I could do in in JavaScript:
var shop = findShop(item);
function findShop(item) {
for (shop in shopMap)
itemList = shopMap[shop]
for (i = 0, ii = itemList.length; i<ii; i++) {
if (itemList[i] === item) {
return shop;
}
}
}
}
I used a function to allow it to quickly break out of the loops with the return statement, instead of using breaks, but the function is kind of fugly as this is only being used once.
So is there a shorter CS equivalent preferably one that doesn't require creating a new function?
You can try this:
findShop = (item) ->
for shop, items of shopMap
return shop if item in items
If you really want to try with a list comprehension, this is equivalent:
findShop = (item) ->
(shop for shop, items of shopMap when item in items)[0]
But i think the first one reads better (and also doesn't need to generate an intermediate array for the results). This would be a better approach IMO if you wanted to find all shops for a given item:
findShops = (item) ->
shop for shop, items of shopMap when item in items
If this is a common operation, you might be better off creating an intermediate data structure up front and doing the lookup directly.
shopMap =
toyStore: ["games", "puzzles"]
bookStore: ["novels", "picture books"]
categoryMap = {}
for k, v of shopMap
for category in v
categoryMap[category] = k
alert(categoryMap['puzzles'])
Demo
With this implementation you need to loop through the structure only once up front (plus possibly update it if shopMap changes). With yours and epidemian's answer, you have to loop every time you need to do this particular type of lookup. If you do this operation a lot, it could make a difference. On the other hand, if your shopMap is really large (like thousands of entries), then my implementation will take up more memory.
Depending upon how robust you want to make this, you might want to turn it into a Class and have any operations on it occur through the Class' interface. You'd need addCategory and deleteCategory methods as well as a getStoreFromCategory method, which is essentially what we are implementing above. This object-oriented approach would hide the internal data-structure/implementation so you could later alter the implementation to optimize for memory or speed.