How to get multiple selected rows in a table or indexedcontainer? - java

I have a Table whose DataSource is set to a IndexedContainer. I also have multiple selection enabled on my Table. The Question is, how do I get all the selected values.. as an array perhaps?
My IndexedContainer:
private void populateAnalyteTable () {
Analyte[] analytes = Analyte.getAnalytes();
for (Analyte analyte : analytes) {
Object id = ic_analytes.addItem();
ic_analytes.getContainerProperty(id, "ID").setValue(analyte.getId());
ic_analytes.getContainerProperty(id, "Analyte Name").setValue(analyte.getAnalyteName());
}
// Bind indexed container to table
tbl_analytes.setContainerDataSource(ic_analytes);
}
What I'm eventually trying to get is an array of Analyte objects

Why do you want to use IndexContainer? Why don't you use BeanItemCotainer?
Please find the snippet of code below
table.setMultiSelect(true);
BeanItemContainer<Analyte> container = new BeanItemContainer<Analyte>(Analyte.class);
container.addAll(Arrays.asList(Analyte.getAnalytes()));
table.setContainerDatasource(container);
// Add some Properties of Analyte class that you want to be shown to user
table.setVisibleColumns(new Object[]{"ID","Analyte Name"});
//User selects Multiple Values, mind you this is an Unmodifiable Collection
Set<Analyte> selectedValues = (Set<Analyte>)table.getValue();
Please let me know in case it doesn't solve the issue

The vaadin objects supporting MultiSelect all return a set of the selected items.
https://www.vaadin.com/api/com/vaadin/ui/AbstractSelect.html#getValue%28%29
The drawback of this, if you need the selected items in "real" order (as displayed onscreen)
you will then have to find them from the Set to the Container

Just add your object as the Item-ID, like luuksen already propesed. Just change the initialisation of yout IndexedContainer to:
for (Analyte analyte : analytes) {
Object id = ic_analytes.addItem(analyte);
ic_analytes.getContainerProperty(id, "ID").setValue(analyte.getId());
ic_analytes.getContainerProperty(id, "Analyte Name").setValue(analyte.getAnalyteName());
}

table.getValue() is what you are looking for.
This method gives you an Object (if table is single select) or a Set<Object> (if multiselect) of the ID(s) of selected item(s). Runtime type depends on runtime id type, but if you do not need the value you can go around with Object .
If you are looking for Analytes as an array you can do
#SuppressWarnings("unchecked")
Set<Object> selectedIds = (Set<Object>) tbl_analytes.getValue();
List<Analyte> listAnalytes = new ArrayList<Analyte>();
for (Object id : selectedIds) {
listAnalytes.get(tbl_analytes.getItem(id));
}
listAnalytes.toArray();
Note that this approach works with every standard container you may use in Vaadin.
Regards!
EDIT: actually what .getValue() returns depends on the used container. In most of the cases it's the ID.

Related

How to attach a Weka instance to an Object?

I'm able to create Instances from a list of objects like below using the Weka library https://weka.sourceforge.io/doc.dev/overview-summary.html
public static Instances createWekaInstances(List<Ticket> tickets, String name) {
// Create numeric attributes "x" and "y" and "z"
Attribute x = new Attribute("x"); //sqrt of row pos
Attribute y = new Attribute("y"); // section cv
// Create arrayList of the above attributes
ArrayList<Attribute> attributes = new ArrayList<Attribute>();
attributes.add(x);
attributes.add(y);
// Create the empty datasets "ticketInstances" with above attributes
Instances ticketInstances = new Instances(name, attributes, 0);
ticketInstances.setClassIndex(ticketInstances.numAttributes() - 1);
for (Ticket ticket : tickets) {
// Create empty instance with attribute values
Instance inst = new DenseInstance(ticketInstances.numAttributes());
// get the Ticket
Ticket t = ticket;
// Set instance's values for the attributes "x", "y" and so on
inst.setValue(x, Math.sqrt(t.getRowPosition()));
inst.setValue(y, t.getSectionCVS());
// Set instance's dataset to be the dataset "ticketInstances"
inst.setDataset(ticketInstances);
// Add the Instance to Instance
ticketInstances.add(inst);
}
return ticketInstances;
}
I'm able to do a nearest neighbor search of whatever instance I want to see it's K nearest neighbors using https://weka.sourceforge.io/doc.dev/weka/core/neighboursearch/NearestNeighbourSearch.html.
Instances neighbors = tree.kNearestNeighbours(ticketInstances.get(indexToSearch), 2);
However it returns a list of 2 instances where an instance looks like -> {0 2.44949,1 0.4} so there is no way for me to associate it to my object. So is there a "Weka" way of attaching an ID or something so I'd be able to know which Object is nearest to the target object in this list of instances?
UPDATE
Okay doing this seems to work for my use case
BallTree bTree = new BallTree();
try{
bTree.setInstances(dataset);
EuclideanDistance euclideanDistance = new EuclideanDistance();
euclideanDistance.setDontNormalize(true);
euclideanDistance.setAttributeIndices("2-last");
euclideanDistance.setInstances(dataset);
bTree.setDistanceFunction(euclideanDistance);
} catch(Exception e){
e.printStackTrace();
}
Weka has not concept of unique IDs for weka.core.Instance objects, instead you need to create an additional attribute that will allow you to identify your rows (e.g., the ticket ID or a numeric attribute with unique values).
You can use the AddID filter to add a numeric attribute to your dataset that will contain such an ID, as mentioned in the Weka wiki article on Instance ID.
From your code it seems that you are just using the nearest neighbor search without any classifier or cluster involved (for these, you would use the FilteredClassifier/FilteredClusterer approach to remove the ID attribute from the data that is used for building the model), therefore you need to specify in the DistanceFunction which attributes to use for the distance calculation. This is done by supplying an attribute range to the setAttributeIndices(String) method. If your ID attribute is the first one, then you would use 2-last.

Assigning New Object to a Generic Array Index

I'm POSITIVE that my title for this topic is not appropriate. Let me explain. The purpose of this is to duplicate a "Profile" application, where I have a profile and so would you. We both have our own followers and in this example, we both follow each other. What this method is needed to return is a cross reference based on whom you follow that I do not. I need this method to return to me a recommended Profile object that I do not already have in my array. Right now I'm having a difficult time with one line of code within a particular method.
One of my classes is a Set class that implements a SetInterface (provided by my professor) and also my Profile class that implements a ProfileInterface which was also provided. In my code for the Profile class, I have the following object: private Set<ProfileInterface> followBag = new Set<ProfileInterface>(); which utilizes the Array bag methods from my Set class with the ProfileInterface methods I've made.
Here is the method (not complete but can't move further without my problem being explained):
public ProfileInterface recommend(){
Set<ProfileInterface> recommended;
ProfileInterface thisProfile = new Profile();
for(int index = 0; index < followBag.getCurrentSize(); index++){
Set<ProfileInterface> follows = followBag[index].toArray();
for(int followedFollowers = 0; followedFollowers < follows.getCurrentSize(); followedFollowers++) {
if()
//if Profile's do not match, set recommended == the Profile
}
}
return recommended;
}
The purpose of this method is to parse through an array (Profile as this example) and then take each of those sub-Profiles and do a similar action. The reason for this much like "Twitter", "Facebook", or "LinkedIn"; where each Profile has followers. This method is meant to look through the highest Profiles follows and see if those subProfiles have any followers that aren't being followed by the highest one. This method is then meant to return that Profile as a recommended one to be followed. This is my first dealing with Array Bag data structures, as well as with generics. Through "IntelliJ", I'm receiving errors with the line Set<ProfileInterface> follows = followBag[index].toArray();. Let me explain the reason for this line. What I'm trying to do is take "my" profile (in this example), and see who I'm following. For each followed profile (or followBag[index]) I wish to see if followBag[index][index] == followBag[index] and continue to parse the array to see if it matches. But, due to my confusion with generics and array bag data structures, I'm having major difficulties figuring this out.
I'd like to do the following:
//for all of my followers
//look at a particular followed profile
//look at all of that profile's followers
//if they match one of my followers, do nothing
//else
//if they don't match, recommend that profile
//return that profile or null
My problem is that I do not know how to appropriately create an object of a Profile type that will allow me to return this object
(in my method above, the line Set<ProfileInterface> follows = followBag[index].toArray();)
I'm trying to make an index of my Profile set to an object that can later be compared where my difficulties are. I'd really appreciate any insight into how this should be done.
Much appreciated for all help and Cheers!
When you do:
Set<ProfileInterface> follows = followBag[index].toArray();
you're trying to use Set as Array. But you can't.
Java will not allow, because Set and Array are different classes, and Set does not support [] syntax.
That is why you get error. For usefollowBag as Array you have to convert it:
ProfileInterface[] profileArray = followBag.toArray(new ProfileInterface[followBag.size()]);
for(int i=0; i<profileArray.length; i++){
ProfileInterface profile = profileArray[i];
//do what you would like to do with array item
}
I believe, in your case, you don't need assign Set object to generic Array at all. Because you can enumerate Set as is.
public class Profile {
private Set<ProfileInterface> followBag = new HashSet<Profile>();
...
public Set<ProfileInterface> recommended(){
Set<ProfileInterface> recommendSet = new HashSet<ProfileInterface>();
for(Profile follower : followBag){
for(Profile subfollower : follower.followBag){
if(!this.followBag.contains(subfollower)){
recommendSet.add(subfollower);
}
}
}
return recommendSet;
}
}
I also added possibility of returning list of recommended profiles, because there is may be several.

Oracle ADF When Selecting Multiple Rows, RowSetIterator Does Not Populate on First Method Invocation

Uncertain how best to word the title, but here's the gist.
The goal is to retrieve all selected rows of a table and manipulate them. The problem I'm bumping into is that the RowSetIterator doesn't get populated the first time the method within my backing bean is invoked. It does get populated when invoked a second time.
How do I go about getting it to work properly on the first invocation?
Doubtless I'm not being perfectly clear, please let me know if you require any additional information. Here's a snippet of the bean method:
public String deleteSelectedQueries()
{
JSFUtils.addInformationMessage("Delete");
RowKeySet selectedQueries =
getSavedQueriesByUserTable().getSelectedRowKeys();
Iterator selectedQueriesIter = selectedQueries.iterator();
DCBindingContainer bindings =
(DCBindingContainer) BindingContext.getCurrent().getCurrentBindingsEntry();
DCIteratorBinding savedQueriesByUserIter =
bindings.findIteratorBinding("SavedQueriesByUserROVOIterator");
RowSetIterator savedQueriesByUserRowSetIterator =
savedQueriesByUserIter.getRowSetIterator();
while (selectedQueriesIter.hasNext())
{
Key key = (Key) ((List) selectedQueriesIter.next()).get(0);
Row currentRow = savedQueriesByUserRowSetIterator.getRow(key);
System.out.println(currentRow.getAttribute("QueryName"));
}
return null;
}
}
Any ideas?
Thanks!
This code looks good to me.
The problem may come from <af:table> tag, make sure you have these tags removed:
selectedRowKeys="#{bindings.SavedQueriesByUserROVO.collectionModel.selectedRow}"
selectionListener="#{bindings.SavedQueriesByUserROVO.collectionModel.makeCurrent}"

Java Swing - DefaultListModel - Printing all object information, when i only want to print one field

I have this DefaultListModel
DefaultListModel listModel;
//constructor does the right hting... etc.. I skipped over a lot of code
JList jlist_available_items;
....
jlist_available_items= new JList(cartModel); //etc
Everything is working almost perfectly the issue is that
listModel.addElement(product);
if I change it to product.name it will look correctly, but behave wrongly [the object itself won't be accesisble, only the name]
Is adding the object to the view, and all I want to add is the object name.
When I change it to the name it causes all sorts of issues, because I store the objects in a hashmap, and the hashmap uses objects as keys, not the product.name string.
The reason is so that this method can search the hashmap for the right object.
for (Product p : store.database.keySet()) {
if (jlist_available_items.getSelectedValuesList().contains(
(Product) p)) { // if item is selected
cart.addItem(p);
}
}
How can I fix this?? I have been trying to fix it and related bugs for almsot two hours = ( !
Also sample output is
Product [description=descrion test, name=test]
That is what it is printing. I just want it to print the name. = (!
Also the objects are in a hashmap. I can just iterate through the hashmap until an object has the same name value and then use that, but I don't want to. I want a more proper and scalable solution, namely because I am having so much trouble thinking of one.
BY THE WAY! This is a GUI app in Swing! If you want images just ask = )!
EDIT: And now nmy list cell renderer is broken! It was working just a moment ago... = (
#Override
public Component getListCellRendererComponent(JList list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
Product product = (Product) value;
return this;
}
}
By default, the toString() method of the objects in the model is called to display the list element. And your Product.toString() method returns Product [description=descrion test, name=test].
If you want to display something else, then use a ListCellRenderer, as explained in the swing tutorial about JList.
EDIT: your renderer has a bug: it doesn't set the text of the returned component (which is a JLabel). It should be:
Product product = (Product) value;
setText(product.getName());
return this;

How do bind indexed property to jface viewer

I want to bind an indexed property to JFace ComboViewer.
Lets say that I have a DataModel class like this:
class DataModel {
private String[] props = {"A","B","C"};
private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
public String getProperties( int idx ){
return props[idx];
}
public void setProperties( int idx, String value ){
String oldVal = props[idx];
props[idx] = value;
pcs.fireIndexedPropertyChange( "properties", idx, oldVal, value );
}
// code to add/remove PropertyChangeListener
// ...
}
The data binding code for simple property would look like this:
DataModel dataModel = ...
ComboViewer propertyChoice = ...
DataBindingContext ctx = new DataBindingContext();
IObservableValue target = ViewerProperties.singleSelection().observe( propertyChoice );
IObservableValue model = BeanProperties.value( DataModel.class, "properties" ).observe(dataModel);
ctx.bindValue( target, model );
but with an indexed property I have to inform the ctx at which index is the value that I want to bind. I have tried
IObservableValue model = BeanProperties.value( DataModel.class, "properties[0]" ).observe(dataModel);
but it doesn't work.
Is it possible to bind indexed property instead of simple property? How?
Unfortunately this seems to be unsupported. I was looking for exactly the same functionality. There is no documentation in BeanProperties that says it is supported.
When looking into the implementation of BeanProperties.value, you find that it delegates to BeanPropertyHelper for reading and writing a property. The method Object readProperty(Object source, PropertyDescriptor propertyDescriptor) does not know about the subclass IndexedPropertyDescriptor. When it is invoked for an indexed property, readProperty tries to use a read method that reads the entire array. I think this method is optional for indexed properties. For indexed properties it should use the IndexedPropertyDescriptor.getIndexedReadMethod().
Depending on your use case you may be able to workaround the problem by using BeanProperties.list. However you cannot use this in combination with indexed properties. I tried this by adding a method that returns the entire array but still keeping the method that does a "fireIndexedPropertyChange". Unfortunately this gives a ClassCastException: Eclipse's BeanListProperty seems to suppose that the value in the change event is an array or list. However for an indexed property it is a single element of the array.
Or perhaps you can use an observable map instead?

Categories