All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.vaadin.data.util.BeanItem Maven / Gradle / Ivy

There is a newer version: 8.27.3
Show newest version
/*
 * Vaadin Framework 7
 *
 * Copyright (C) 2000-2024 Vaadin Ltd
 *
 * This program is available under Vaadin Commercial License and Service Terms.
 *
 * See  for the full
 * license.
 */

package com.vaadin.data.util;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.vaadin.data.Property;

/**
 * A wrapper class for adding the Item interface to any Java Bean.
 *
 * @author Vaadin Ltd.
 * @since 3.0
 */
@SuppressWarnings("serial")
public class BeanItem extends PropertysetItem {

    /**
     * The bean which this Item is based on.
     */
    private BT bean;

    /**
     * 

* Creates a new instance of BeanItem and adds all properties * of a Java Bean to it. The properties are identified by their respective * bean names. *

* *

* Note : This version only supports introspectable bean properties and * their getter and setter methods. Stand-alone is and * are methods are not supported. *

* * @param bean * the Java Bean to copy properties from. * */ public BeanItem(BT bean) { this(bean, (Class) bean.getClass()); } /** *

* Creates a new instance of BeanItem and adds all properties * of a Java Bean to it. The properties are identified by their respective * bean names. *

* *

* Note : This version only supports introspectable bean properties and * their getter and setter methods. Stand-alone is and * are methods are not supported. *

* * @since 7.4 * * @param bean * the Java Bean to copy properties from. * @param beanClass * class of the {@code bean} * */ public BeanItem(BT bean, Class beanClass) { this(bean, getPropertyDescriptors(beanClass)); } /** *

* Creates a new instance of BeanItem using a pre-computed set * of properties. The properties are identified by their respective bean * names. *

* * @param bean * the Java Bean to copy properties from. * @param propertyDescriptors * pre-computed property descriptors */ BeanItem(BT bean, Map> propertyDescriptors) { this.bean = bean; for (VaadinPropertyDescriptor pd : propertyDescriptors.values()) { addItemProperty(pd.getName(), pd.createProperty(bean)); } } /** *

* Creates a new instance of BeanItem and adds all listed * properties of a Java Bean to it - in specified order. The properties are * identified by their respective bean names. *

* *

* Note : This version only supports introspectable bean properties and * their getter and setter methods. Stand-alone is and * are methods are not supported. *

* * @param bean * the Java Bean to copy properties from. * @param propertyIds * id of the property. */ public BeanItem(BT bean, Collection propertyIds) { this.bean = bean; // Create bean information LinkedHashMap> pds = getPropertyDescriptors( (Class) bean.getClass()); // Add all the bean properties as MethodProperties to this Item for (Object id : propertyIds) { VaadinPropertyDescriptor pd = pds.get(id); if (pd != null) { addItemProperty(pd.getName(), pd.createProperty(bean)); } } } /** *

* Creates a new instance of BeanItem and adds all listed * properties of a Java Bean to it - in specified order. The properties are * identified by their respective bean names. *

* *

* Note : This version only supports introspectable bean properties and * their getter and setter methods. Stand-alone is and * are methods are not supported. *

* * @param bean * the Java Bean to copy properties from. * @param propertyIds * ids of the properties. */ public BeanItem(BT bean, String... propertyIds) { this(bean, Arrays.asList(propertyIds)); } /** *

* Perform introspection on a Java Bean class to find its properties. *

* *

* Note : This version only supports introspectable bean properties and * their getter and setter methods. Stand-alone is and * are methods are not supported. *

* * @param beanClass * the Java Bean class to get properties for. * @return an ordered map from property names to property descriptors */ static LinkedHashMap> getPropertyDescriptors( final Class beanClass) { final LinkedHashMap> pdMap = new LinkedHashMap>(); // Try to introspect, if it fails, we just have an empty Item try { List propertyDescriptors = BeanUtil .getBeanPropertyDescriptor(beanClass); // Add all the bean properties as MethodProperties to this Item // later entries on the list overwrite earlier ones for (PropertyDescriptor pd : propertyDescriptors) { final Method getMethod = pd.getReadMethod(); if ((getMethod != null) && getMethod.getDeclaringClass() != Object.class) { VaadinPropertyDescriptor vaadinPropertyDescriptor = new MethodPropertyDescriptor( pd.getName(), pd.getPropertyType(), pd.getReadMethod(), pd.getWriteMethod()); pdMap.put(pd.getName(), vaadinPropertyDescriptor); } } } catch (final java.beans.IntrospectionException ignored) { } return pdMap; } /** * Expands nested bean properties by replacing a top-level property with * some or all of its sub-properties. The expansion is not recursive. * * @param propertyId * property id for the property whose sub-properties are to be * expanded, * @param subPropertyIds * sub-properties to expand, all sub-properties are expanded if * not specified */ public void expandProperty(String propertyId, String... subPropertyIds) { Set subPropertySet = new HashSet( Arrays.asList(subPropertyIds)); if (0 == subPropertyIds.length) { // Enumerate all sub-properties Class propertyType = getItemProperty(propertyId).getType(); Map pds = getPropertyDescriptors(propertyType); subPropertySet.addAll(pds.keySet()); } for (String subproperty : subPropertySet) { String qualifiedPropertyId = propertyId + "." + subproperty; addNestedProperty(qualifiedPropertyId); } removeItemProperty(propertyId); } /** * Adds a nested property to the item. The property must not exist in the * item already and must of form "field1.field2" where field2 is a field in * the object referenced to by field1. If an intermediate property returns * null, the property will return a null value * * @param nestedPropertyId * property id to add. */ public void addNestedProperty(String nestedPropertyId) { addItemProperty(nestedPropertyId, new NestedMethodProperty(getBean(), nestedPropertyId)); } /** * Gets the underlying JavaBean object. * * @return the bean object. */ public BT getBean() { return bean; } /** * Changes the Java Bean this item is based on. *

* This will cause any existing properties to be re-mapped to the new bean. * Any added custom properties which are not of type {@link MethodProperty} * or {@link NestedMethodProperty} will not be updated to reflect the change * of bean. *

* Changing the bean will fire value change events for all properties of * type {@link MethodProperty} or {@link NestedMethodProperty}. * * @param bean * The new bean to use for this item, not null * @since 7.7.7 */ public void setBean(BT bean) { if (bean == null) { throw new IllegalArgumentException("Bean cannot be null"); } if (getBean().getClass() != bean.getClass()) { throw new IllegalArgumentException( "The new bean class " + bean.getClass().getName() + " does not match the old bean class " + getBean().getClass()); } // Remap properties for (Object propertyId : getItemPropertyIds()) { Property p = getItemProperty(propertyId); if (p instanceof MethodProperty) { MethodProperty mp = (MethodProperty) p; assert (mp.getInstance() == getBean()); mp.setInstance(bean); } else if (p instanceof NestedMethodProperty) { NestedMethodProperty nmp = (NestedMethodProperty) p; assert (nmp.getInstance() == getBean()); nmp.setInstance(bean); } } this.bean = bean; } }