blob: 647b1030f053958b766602d7443ba7b4de054c14 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jface.databinding;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.util.Collection;
import java.util.Map;
import org.eclipse.jface.internal.databinding.beans.JavaBeanTree;
import org.eclipse.jface.internal.databinding.beans.JavaBeanUpdatableCollection;
import org.eclipse.jface.internal.databinding.beans.JavaBeanUpdatableTree;
import org.eclipse.jface.internal.databinding.beans.JavaBeanUpdatableValue;
/**
* A factory for creating updatable objects for properties of plain Java objects
* with JavaBeans-style notification.
*
* This factory supports the following description objects:
* <ul>
* <li>org.eclipse.jface.databinding.PropertyDescription:
* <ul>
* <li>Returns an updatable value representing the specified value property of
* the given object, if {@link Property#isCollectionProperty()}
* returns false</li>
* <li>Returns an updatable collection representing the specified collection
* property of the given object, if
* {@link Property#isCollectionProperty()} returns false</li>
* </ul>
* </li>
* </ul>
*
* @since 3.2
*
*/
final public class BeanUpdatableFactory implements IUpdatableFactory {
public IUpdatable createUpdatable(Map properties, Object description,
IDataBindingContext bindingContext) {
if (description instanceof Property) {
Property propertyDescription = (Property) description;
if (propertyDescription.getObject() != null) {
Object object = propertyDescription.getObject();
BeanInfo beanInfo;
try {
beanInfo = Introspector.getBeanInfo(object.getClass());
} catch (IntrospectionException e) {
// cannot introspect, give up
return null;
}
PropertyDescriptor[] propertyDescriptors = beanInfo
.getPropertyDescriptors();
for (int i = 0; i < propertyDescriptors.length; i++) {
PropertyDescriptor descriptor = propertyDescriptors[i];
if (descriptor.getName().equals(
propertyDescription.getPropertyID())) {
if (descriptor.getPropertyType().isArray() || Collection.class.isAssignableFrom(descriptor.getPropertyType())){
// If we are a collection them the type must be explicitly specified in order to be edited.
// There is no way to derive it by name matching (because of different ways of plurals being made,
// e.g. getFlies() and addFly(Fly aFly) or getHooves() and addHoof(Hoof aHoof)
Class elementType = descriptor.getPropertyType().isArray() ?
descriptor.getPropertyType().getComponentType() :
propertyDescription.getPropertyType();
if (elementType == null) {
// If we don't know the element type, use the polymorphic converter
// This should usually get us object to string, but won't get us string
// back to the object. At least this handles the read-only case for
// tables and handles Combos and Lists.
elementType = Object.class;
}
/*
* FIXME: CopyOfJavaBeanUpdatableCollection is the new IUpdatableCollection
* that fixes bug #119930. It seems to work now. Unfortunately, there is
* a bunch of code that depends on the IUpdatableCollections themselves
* listening to the generic change event on each of the collections' elements.
*
* Examples of this include StructuredViewerUpdatableValue and the table
* implementations. These need to be fixed to use IUpdatableValues
* pointing to the specific properties being displayed/edited rather than
* expecting the IUpdatableCollection to be registered to the generic
* property change event.
*/
return new JavaBeanUpdatableCollection(object,
descriptor, elementType);
// return new CopyOfJavaBeanUpdatableCollection(object, descriptor, elementType);
}
return new JavaBeanUpdatableValue(object, descriptor);
}
}
}
}
else if (description instanceof ITree)
return new JavaBeanUpdatableTree((ITree)description);
else if (description instanceof TreeModelDescription) {
Object root = ((TreeModelDescription)description).getRoot();
if (root==null || ! (root instanceof IUpdatable) && !(root instanceof Property)) // TODO workaround until the context's factory is driven first
return new JavaBeanUpdatableTree(new JavaBeanTree((TreeModelDescription)description));
}
return null;
}
}