Last active
August 29, 2015 14:16
-
-
Save juanghurtado/1f0662b8e7c9da1f9ce5 to your computer and use it in GitHub Desktop.
Vaadin multiselect OptionGroup and BeanFieldGroup
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class AbstractMultiSelectToDTOConverter implements Converter<Object, List<BaseDTO>> { | |
private static final long serialVersionUID = -7589634171531062832L; | |
private BeanContainer<Long, BaseDTO> container; | |
private final static List<BaseDTO> MODEL_TYPE_INSTANCE = new ArrayList<BaseDTO>(); | |
@SuppressWarnings("unchecked") | |
public AbstractMultiSelectToDTOConverter(AbstractSelect field) { | |
this.container = (BeanContainer<Long, BaseDTO>) field.getContainerDataSource(); | |
} | |
@SuppressWarnings("unchecked") | |
@Override | |
public List<BaseDTO> convertToModel(Object itemIds, Class<? extends List<BaseDTO>> targetType, Locale locale) throws com.vaadin.data.util.converter.Converter.ConversionException { | |
List<BaseDTO> models = new ArrayList<BaseDTO>(); | |
if (container.size() > 0) { | |
for (Object itemId : ((HashSet<Object>) itemIds)) { | |
if (container.containsId(itemId)) { | |
models.add(container.getItem(itemId).getBean()); | |
} | |
} | |
} | |
return models; | |
} | |
@Override | |
public Object convertToPresentation(List<BaseDTO> models, Class<? extends Object> targetType, Locale locale) throws com.vaadin.data.util.converter.Converter.ConversionException { | |
List<Object> ids = new ArrayList<Object>(); | |
for (Object itemId : container.getItemIds()) { | |
BaseDTO bean = container.getItem(itemId).getBean(); | |
for (Object model : models) { | |
if (((BaseDTO) model).compareTo(bean)) { | |
ids.add(itemId); | |
} | |
} | |
} | |
return ids; | |
} | |
@SuppressWarnings("unchecked") | |
@Override | |
public Class<List<BaseDTO>> getModelType() { | |
return (Class<List<BaseDTO>>) MODEL_TYPE_INSTANCE.getClass(); | |
} | |
@Override | |
public Class<Object> getPresentationType() { | |
return Object.class; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ----------------------------------------------------------------------------------- | |
// Saving a country | |
// | |
// In this case, I must manually do the setCities() after the commit() of | |
/// the BeanFieldGroup, because it's done in the commit() itself. | |
// ----------------------------------------------------------------------------------- | |
country = new CountryDTO(); | |
formGroup = new BeanFieldGroup<CountryDTO>(CountryDTO.class); | |
formGroup.setItemDataSource(new BeanItem<CountryDTO>(country)); | |
formGroup.buildAndBind("_Cities", "cities", OptionGroup.class); | |
// Set OptionGroup properties | |
OptionGroup citiesOptionGroup = (OptionGroup) formGroup.getField("cities"); | |
// getCitiesContainer() returns a BeanContainer with all the cities in the DB, | |
// because thats what we need to be shown in the OptionGroup | |
citiesOptionGroup.setContainerDataSource(controller.getCitiesContainer()); | |
citiesOptionGroup.setItemCaptionPropertyId("name"); | |
citiesOptionGroup.setMultiSelect(true); | |
citiesOptionGroup.setConverter(new AbstractMultiSelectToDTOConverter(citiesOptionGroup)); | |
// Attach it to a FormLayout | |
formLayout.addComponent(citiesOptionGroup); | |
// Later… on the click of the "save" button | |
try { | |
Collection<Long> ids = (Collection<Long>) formGroup.getField("cities").getValue(); | |
formGroup.commit(); | |
country.setCities(controller.getCitiesById(ids)); | |
controller.saveCountry(country, successMessage); | |
} catch (CommitException e) { | |
showWarningMessage("_Please fix marked fields and try again"); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Package, imports and so on… | |
@XmlRootElement | |
@Entity | |
@Table(name = "city", uniqueConstraints = @UniqueConstraint(name = "UNIQ_CITY", columnNames = { "city_id" })) | |
public class CityDTO extends BaseDTO { | |
@Id | |
@Column(name = "city_id") | |
@GeneratedValue(strategy = GenerationType.IDENTITY) | |
private Long cityId; | |
@Column(name = "name", nullable = false) | |
private String name; | |
@ManyToMany(mappedBy = "cities") | |
private List<CountryDTO> countries; | |
// Getters and setters… | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Package, imports and so on… | |
@XmlRootElement | |
@Entity | |
@Table(name = "role", uniqueConstraints = @UniqueConstraint(name = "UNIQ_COUNTRY", columnNames = { "country_id" })) | |
public class CountryDTO extends BaseDTO { | |
@Id | |
@Column(name = "country_id") | |
@GeneratedValue(strategy = GenerationType.IDENTITY) | |
private Long countryId; | |
@Column(name = "name", nullable = false) | |
private String name; | |
@ManyToMany(fetch = FetchType.EAGER) | |
@JoinTable(name = "country_city", joinColumns = { @JoinColumn(name = "country_id", nullable = true, updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "city_id", nullable = true, updatable = false) }) | |
private List<CityDTO> cities; | |
// Getters and setters… | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ----------------------------------------------------------------------------------- | |
// Existing country with cities | |
// | |
// Same process here, except we are working with an existing DB CountryDTO, which | |
// happens to have some CityDTO inside. | |
// | |
// Here, the situation is that the cities of the country are not being checked in | |
// the OptionGroup. And that happens because the "set" of the OptionGroup is not being | |
// called. I know this because the methods on the OptionGroup converter are not being | |
// called neither. | |
// | |
// So I ended up setting the value of the OptionGroup manually, like this; | |
// | |
// OptionGroup permissionsOptionGroup = (OptionGroup) formGroup.getField("cities"); | |
// permissionsOptionGroup.setValue(controller.getSelectedCities(country)); | |
// | |
// Notice that getSelectedCities() returns a List<Long> with the IDs of the cities | |
// inside the given country. | |
// | |
// Following this path, everything works as expected. The OptionGroup gets the right | |
// options checked. | |
// ----------------------------------------------------------------------------------- | |
country = countryService.findOne(1L); // Get sample CountryDTO | |
formGroup = new BeanFieldGroup<CountryDTO>(CountryDTO.class); | |
formGroup.setItemDataSource(new BeanItem<CountryDTO>(country)); | |
formGroup.buildAndBind("_Cities", "cities", OptionGroup.class); | |
// Set OptionGroup properties | |
OptionGroup citiesOptionGroup = (OptionGroup) formGroup.getField("cities"); | |
// getCitiesContainer() returns a BeanContainer with all the cities in the DB, | |
// because thats what we need to be shown in the OptionGroup | |
citiesOptionGroup.setContainerDataSource(controller.getCitiesContainer()); | |
citiesOptionGroup.setItemCaptionPropertyId("name"); | |
citiesOptionGroup.setMultiSelect(true); | |
citiesOptionGroup.setConverter(new AbstractMultiSelectToDTOConverter(citiesOptionGroup)); | |
// Attach it to a FormLayout | |
formLayout.addComponent(citiesOptionGroup); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment