Skip to content

Instantly share code, notes, and snippets.

@juanghurtado
Last active August 29, 2015 14:16
Show Gist options
  • Save juanghurtado/1f0662b8e7c9da1f9ce5 to your computer and use it in GitHub Desktop.
Save juanghurtado/1f0662b8e7c9da1f9ce5 to your computer and use it in GitHub Desktop.
Vaadin multiselect OptionGroup and BeanFieldGroup
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;
}
}
// -----------------------------------------------------------------------------------
// 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");
}
// 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…
}
// 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…
}
// -----------------------------------------------------------------------------------
// 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