Where does IModel Apache Wicket retrieve an object? - wicket

First of all, please take a look at how IModel is used in this example:
#SuppressWarnings("serial")
public static List<IColumn> getTableColumns(
final ReportParams reportParams, final boolean columnsSortable
) {
List<IColumn> columns = new ArrayList<IColumn>();
final Map<String,ToolInfo> eventIdToolMap = Locator.getFacade().getEventRegistryService().getEventIdToolMap();
// site
if(Locator.getFacade().getReportManager().isReportColumnAvailable(reportParams, StatsManager.T_SITE)) {
columns.add(new PropertyColumn(new ResourceModel("th_site"), columnsSortable ? ReportsDataProvider.COL_SITE : null, ReportsDataProvider.COL_SITE) {
#Override
public void populateItem(Item item, String componentId, IModel model) {
final String site = ((Stat) model.getObject()).getSiteId();
String lbl = "", href = "";
Site s = null;
try{
s = Locator.getFacade().getSiteService().getSite(site);
lbl = s.getTitle();
href = s.getUrl();
}catch(IdUnusedException e){
lbl = (String) new ResourceModel("site_unknown").getObject();
href = null;
}
item.add(new ImageWithLink(componentId, null, href, lbl, "_parent"));
}
});
}
And my questions are:
How does populateItem get an input for IModel parameter?
I cannot find any code in this application, which explicitly constructs IModel object. Is it correct for me to assume that the object is retrieved directly from a table in the database? I'm thinking of this because Mapping Hibernate is used for this application.

The models are created using the IDataProvider you provide to the DataTable (DataTable constructor will also take your IColumn List) .
The IDataProvider could use Hibernate - hard to say without having more information on that implementation.

Related

Google Web Toolkit - How to prevent duplication of the records?

I am new in GWT. I am trying to use the cell table to do this. Here is my questions:
Name Gender
Ali M
Abu M
Siti F
page 1
Name Gender
Siti F
Noor F
Ahmad F
page 2
I use simple pager to do the paging function. Everything is ok except next page.
When i click next page, siti record appear 2 times.
How to prevent the name Siti not appear in page 2? Below are my code:
private static class Contact{
private final String name;
private final String gender;
public Contact(String name, String gender){
this.name = name;
this.gender = gender;
}
}
private static final List<Contact> CONTACTS = Arrays.asList(
new Contact("Ali","M"),
new Contact("Abu","M"),
new Contact("Siti","F"),
new Contact("Noor","F"),
new Contact("Ahmad","M")
);
public void onModuleLoad(){
final CellTable<Contact> table = new CellTable<Contact>();
table.setPageSize(3);
TextColumn<Contact> nameColumn = new TextColumn<Contact>(){
#Override
public String getValue(Contact object) {
return object.name;
}
};
TextColumn<Contact> genderColumn = new TextColumn<Contact>(){
#Override
public String getValue(Contact object) {
return object.gender;
}
};
table.addColumn(nameColumn, "Name");
table.addColumn(genderColumn, "Gender");
AsyncDataProvider<Contact> provider = new AsyncDataProvider<Contact>(){
#Override
protected void onRangeChanged(HasData<Contact> display) {
int start = display.getVisibleRange().getStart();
int end = start + display.getVisibleRange().getLength();
end = end >= CONTACTS.size() ? CONTACTS.size() : end;
List<Contact> sub = CONTACTS.subList(start,end);
updateRowData(start,sub);
}
};
provider.addDataDisplay(table);
provider.updateRowCount(CONTACTS.size(), true);
SimplePager.Resources pagerResources = GWT.create(SimplePager.Resources.class);
SimplePager pager = new SimplePager(TextLocation.CENTER, pagerResources, false, 0, true);
pager.setDisplay(table);
Please help me to solve this problem. Thanks.
You have faced most probably the gwt last page problem, described in the linked questions:
GWT - celltable with simple pager issue
SimplePager row count is working incorrectly
The solution here is to set:
setRangeLimited(false)
and the last page is paged correctly, ie. it contains only Noor and Ahmad.
So in conclusion: actually no duplication is present here, but a bug on pagination in case of the last page. You will observe the same behavior with also other amounts of data, but on my view point it would be always a last page issue only.

GWT-Editors and sub-editors

I'm trying to run an example of Editors with sub-editors.
When flushing the parent the value of child editor is null.
The classes are Person and Address.
The main editor is:
// editor fields
public TextField firstname;
public TextField lastname;
public NumberField<Integer> id;
public AddressEditor address = new AddressEditor();
public PersonEditor(Person p){
asWidget();
}
#Override
public Widget asWidget() {
setWidth(400);
setBodyStyle("padding: 5px;");
setHeaderVisible(false);
VerticalLayoutContainer c = new VerticalLayoutContainer();
id = new NumberField<Integer>(new IntegerPropertyEditor());
// id.setName("id");
id.setFormat(NumberFormat.getFormat("0.00"));
id.setAllowNegative(false);
c.add(new FieldLabel(id, "id"), new VerticalLayoutData(1, -1));
firstname = new TextField();
// firstname.setName("firstname");
c.add(new FieldLabel(firstname, "firstname"), new VerticalLayoutData(1, -1));
lastname = new TextField();
lastname.setName("lastname");
c.add(new FieldLabel(lastname, "lastname"), new VerticalLayoutData(1, -1));
c.add(address);
add(c);
return this;
The sub-editor:
public class AddressEditor extends Composite implements Editor<Address> {
private AddressProperties props = GWT.create(AddressProperties.class);
private ListStore<Address> store = new ListStore<Address>(props.key());
ComboBox<Address> address;
public AddressEditor() {
for(int i = 0; i < 5; i ++)
store.add(new Address("city" + i));
address = new ComboBox<Address>(store, props.nameLabel());
address.setAllowBlank(false);
address.setForceSelection(true);
address.setTriggerAction(TriggerAction.ALL);
initWidget(address);
}
And this is where the Driver is created:
private HorizontalPanel hp;
private Person googleContact;
PersonDriver driver = GWT.create(PersonDriver.class);
public void onModuleLoad() {
hp = new HorizontalPanel();
hp.setSpacing(10);
googleContact = new Person();
PersonEditor pe = new PersonEditor(googleContact);
driver.initialize(pe);
driver.edit(googleContact);
TextButton save = new TextButton("Save");
save.addSelectHandler(new SelectHandler() {
#Override
public void onSelect(SelectEvent event) {
googleContact = driver.flush();
System.out.println(googleContact.getFirstname() + ", " + googleContact.getAddress().getCity());
if (driver.hasErrors()) {
new MessageBox("Please correct the errors before saving.").show();
return;
}
}
});
The value of googleContact.getFirstname() is filled but googleContact.getAddress() is always null.
What I'm missing?
The AddressEditor needs to map to the Address model - presently, it doesn't seem to, unless Address only has one getter/setter, called getAddress() and setAddress(Address), which wouldn't really make a lot of sense.
If you want just a ComboBox<Address> (which implements Editor<Address> already), consider putting that combo in the PersonEditor directly. Otherwise, you'll need to add #Path("") to the AddressEditor.address field, to indicate that it should be directly editing the value itself, and not a sub property (i.e. person.getAddress().getAddress()).
Another way to build an address editor would be to list each of the properties of the Address type in the AddressEditor. This is what the driver is expecting by default, so it is confused when it sees a field called 'address'.
Two quick thoughts on the code itself: there is no need to pass a person into the PersonEditor - thats the job of the driver itself. Second, your editor fields do not need to be public, they just can't be private.

Add filters to LiveGrid?

I am using gxt's LiveGrid. I want to add filters. I have added below few lines but data is not filtered. Am I missing any thing here?
GridFilters filters = new GridFilters();
filters.setLocal(true);
StringFilter nameFilter = new StringFilter("column name");
filters.addFilter(nameFilter);
filters.init(liveGrid);
liveGrid.addPlugin(filters);
From the filter javadoc :
To add a filter to a Grid column, create an instance of a concrete subclass of Filter, passing to the constructor the ValueProvider for the column, then add the filter to a GridFilters
Your code sample seems too restrinct and should probably be parameterized. The StringFilter should be given a ValueProvider for the property of the model object you wish to filter. Following is a simple overview of how to create a Grid with Filters.
Let's say you have a class User
public class User implements Serializable {
private String name;
private Integer id;
// Setters and getters
}
public interface UserProperties extends PropertyAccess<User> {
#Path("id")
ModelKeyProvider<User> key();
ValueProvider<User, String> name();
}
To create a grid that will display your users, you would do as follow
private static final UserProperties props = GWT.create(UserProperties.class);
...
// Create column config
ColumnConfig<User, String> nameCol = new ColumnConfig<User, String>(props.name(), 200, "Name");
// Create column model
List<ColumnConfig<User, ?>> l = new ArrayList<ColumnConfig<User, ?>>();
l.add(nameCol);
ColumnModel<User> cm = new ColumnModel<User>(l);
// Create User store
ListStore<User> store = new ListStore<User>(props.key());
// Create your grid
final LiveGridView<User> liveGridView = new LiveGridView<User>();
liveGridView.setForceFit(true);
Grid<User> view = new Grid<User>(store, cm) {
#Override
protected void onAfterFirstAttach() {
super.onAfterFirstAttach();
// Get grid data
}
};
// Create a String filter for the column
StringFilter<User> nameFilter = new StringFilter<User>(props.name());
// Create a GridFilters
GridFilters<User> filters = new GridFilters<User>();
filters.initPlugin(grid);
filters.setLocal(true);
filters.addFilter(nameFilter);
GridFilters filters = new GridFilters();
filters.setLocal(true);
StringFilter nameFilter = new StringFilter("column name");
filters.addFilter(nameFilter);
filters.init(liveGrid);
liveGrid.addPlugin(filters);
If u want to get the data after filter applied u need to overide reload() method of AbstractGridFilters.

Case-insensitive indexing with Hibernate-Search?

Is there a simple way to make Hibernate Search to index all its values in lower case ? Instead of the default mixed-case.
I'm using the annotation #Field. But I can't seem to be able to configure some application-level set
Fool that I am ! The StandardAnalyzer class is already indexing in lowercase. It's just a matter of setting the search terms in lowercase too. I was assuming the query would do that.
However, if a different analyzer were to be used, application-wide, then it can be set using the property hibernate.search.analyzer.
Lowercasing, term splitting, removing common terms and many more advanced language processing functions are applied by the Analyzer.
Usually you should process user input meant to match indexed strings with the same Analyzer used at indexing; configuring hibernate.search.analyzer sets the default (global) Analyzer, but you can customize it per index, per entity type, per field and even on different entity instances.
It is for example useful to have language specific analysis, so to process Chinese descriptions with Chinese specific routines, Italian descriptions with Italian tokenizers.
The default analyzer is ok for most use cases, and does lowercasing and splits terms on whitespace.
Consider as well that when using the Lucene Queryparser the API requests you the appropriate Analyzer.
When using the Hibernate Search QueryBuilder it attempts to apply the correct Analyzer on each field; see also http://docs.jboss.org/hibernate/search/4.1/reference/en-US/html_single/#search-query-querydsl .
There are multiple way to make sort insensitive in string type field only.
1.First Way is add #Fields annotation in field/property on entity.
Like
#Fields({#Field(index=Index.YES,analyze=Analyze.YES,store=Store.YES),
#Field(index=Index.YES,name = "nameSort",analyzer = #Analyzer(impl=KeywordAnalyzer.class), store = Store.YES)})
private String name;
suppose you have name property with custom analyzer and sort on that. so it's not possible then you can add new Field in index with nameSort apply sort on that field.
you must apply Keyword Analyzer class because that is not tokeniz field and by default apply lowercase factory class in field.
2.Second way is that you can implement your comparison class on sorting like
#Override
public FieldComparator newComparator(String field, int numHits, int sortPos, boolean reversed) throws IOException {
return new StringValComparator(numHits, field);
}
Make one class with extend FieldComparatorSource class and implement above method.
Created new Class name with StringValComparator and implements FieldComparator
and implement following method
class StringValComparator extends FieldComparator {
private String[] values;
private String[] currentReaderValues;
private final String field;
private String bottom;
StringValComparator(int numHits, String field) {
values = new String[numHits];
this.field = field;
}
#Override
public int compare(int slot1, int slot2) {
final String val1 = values[slot1];
final String val2 = values[slot2];
if (val1 == null) {
if (val2 == null) {
return 0;
}
return -1;
} else if (val2 == null) {
return 1;
}
return val1.toLowerCase().compareTo(val2.toLowerCase());
}
#Override
public int compareBottom(int doc) {
final String val2 = currentReaderValues[doc];
if (bottom == null) {
if (val2 == null) {
return 0;
}
return -1;
} else if (val2 == null) {
return 1;
}
return bottom.toLowerCase().compareTo(val2.toLowerCase());
}
#Override
public void copy(int slot, int doc) {
values[slot] = currentReaderValues[doc];
}
#Override
public void setNextReader(IndexReader reader, int docBase) throws IOException {
currentReaderValues = FieldCache.DEFAULT.getStrings(reader, field);
}
#Override
public void setBottom(final int bottom) {
this.bottom = values[bottom];
}
#Override
public String value(int slot) {
return values[slot];
}
}
Apply sorting on Fields Like
new SortField("name",new StringCaseInsensitiveComparator(), true);

How do I add items to GWT ListBox in Uibinder .ui.xml template ?

How to add the listbox items using UiBinder?
It is possible since february 2011 version:
http://code.google.com/p/google-web-toolkit/issues/detail?id=4654
Following this patch you are now able to add items following this syntax:
<g:ListBox>
<g:item value='1'>
first item
</g:item>
<g:item value='2'>
second item
</g:item>
</g:ListBox>
This is a listbox of translations of an enumeration, I suppose this also works for a listbox with string values (version of GWT: 2.1.0)
You only need the renderer for translating the enumeration values.
//UI XML
<g:ValueListBox ui:field="requesterType"/>
//JAVA CODE
#UiField(provided = true)
ValueListBox<RequesterType> requesterType = new ValueListBox<RequesterType>(requesterTypeRenderer);
static EnumRenderer<RequesterType> requesterTypeRenderer = new EnumRenderer<RequesterType>();
public Constructor() {
requesterTypeRenderer.setEmptyValue(Translations.translateEmptyValue(RequesterType.class));
requesterType.setAcceptableValues(Arrays.asList(EnumUtil.getRequesterTypes()));
}
/**
* Translates enum entries. Use setEmptyValue() if you want to have a custom empty value. Default empty value is "".
*
* #param <T>
* an enumeration entry which is to be registered in {#link Translations}
*/
public class EnumRenderer<T extends Enum<?>> extends AbstractRenderer<T> {
private String emptyValue = "";
#Override
public String render(T object) {
if (object == null)
return emptyValue;
return Translations.translate(object);
}
public void setEmptyValue(String emptyValue) {
this.emptyValue = emptyValue;
}
}
GWT ValueListbox otherwise know as a ComboBox or Dropdown component.
Another example that also demonstrates populating the list.
UiBinder...
<g:ValueListBox ui:field="subCategory"/>
Editor...
#UiField(provided = true)
ValueListBox<String> subCategory = new ValueListBox<String>(
new Renderer<String>() {
#Override
public String render(String object) {
String s = "Cats";
if (object != null) {
s = object.toString();
}
return s;
}
#Override
public void render(String object, Appendable appendable)
throws IOException {
render(object);
}
});
Constructor...
List<String> values = new ArrayList<String>();
values.add("Animal Shelters and Rescues");
values.add("Birds");
values.add("Cats");
values.add("Dogs");
values.add("Other Pets");
values.add("Rabbits");
subCategory.setAcceptableValues(values);