Databinding java.util.Map

Hey all,
Okay, I must be crazy or something, but I can’t seem to figure out how to properly databind a java.util.Map.

Some background info:
Our company uses a tree-like structure to represent connections between virtual files. Every virtual file is pointed towards by a virtual file link, this way we’re able to represent the same file (or actually the same file contents) at different locations in the tree, a bit like symlinks in linux. We use Hibernate to store objects in a database, these link objects are stored there as well.

Now for my problem:
A link object has a metadata Map. This is a simple java.util.Map<String, String> storing all kinds of interesting information about the link, such as the name, a string representation of the creation date, etc.

I would like to show the data in this Map by using a Table (seemed like the most natural representation of a Map; a two column Table). However, I can’t seem to figure out how to get Vaadin to bind it properly.

What I have tried so far is:

  • Create a MetadataMap class, extending an IndexedContainer
  • Use addContainerProperty(x, String.class, null) for x is {key:String, value:String}, thus adding two String container properties
  • Then fill the container by creating empty Item objects, then retrieving all the entries from the original Map and adding them as properties to the item
  • Use this MetadataMap as a datasource for the Table

This setup properly shows all the Map items in the Table. However, If I want to be able to edit the values in the Value column, this will never work, as there is no “real” binding between the Map.Entry<String, String> objects in the Map and their representation. Now, using the Map.Entry objects as Items, then adding the properties using i.getItemProperty(key).setValue(e.getKey()); doesn’t seem to work either.

Anyway, I must be overlooking something trivial I guess, as most people on the forum have way more difficult questions…
Thanks in advance.

Cheers, Peter

Ps. Attached are (parts of) the source used, in case my explanation is a bit too mind boggling :slight_smile:
11495.java (952 Bytes)
11496.java (889 Bytes)

A late reply, but hope this helps.

What you are doing is effectively copying the map keys and values to the IndexedContainer. The Property implementation in IndexedContainer does not bind to the original values.

In fact, as you are using Strings which are immutable objects, a Property that would modify the instance (e.g. MethodProperty) is not an option, either.

If you are not editing the keys, nor adding/removing key/value pairs, you could try a BeanItemContainer with the Map.Entry instances as beans. I haven’t tested this, but it could be an easy option if everything works.

Otherwise, you could e.g. listen to modifications of all properties of all items of the container and update the map there. You would have two copies of the data, and keep the in synch in the listener. It might be a bit tricky to set up all the listeners from outside the container. If you can afford to have the updates not take place immediately, you could instead copy the whole table contents to the map on some “commit” action - this would be a simpler option.

Implementing your own Container for a Map would be the cleanest solution, but is far from trivial. It might be doable with reasonable effort if extending some existing Container implementation in the
Directory
, such as the
Lazy Query Container
or some lighter weight container that might require a little more coding.

Having this as an add-on in the directory would be great - there is a
PropertyItem
add-on for presenting Properties (effectively Maps) on a Form, and some collection backed Containers, but no Container for a Map as far as I could see.