/******************************************************************************* * Copyright (c) 2008, 2014 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 * Matthew Hall - bug 278314 *******************************************************************************/ package org.eclipse.jface.internal.databinding.util; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.eclipse.core.databinding.observable.value.IObservableValue; import org.eclipse.core.databinding.property.INativePropertyListener; import org.eclipse.core.databinding.property.ISimplePropertyListener; import org.eclipse.core.databinding.property.NativePropertyListener; import org.eclipse.core.databinding.property.value.SimpleValueProperty; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; /** * Class that supports the use of {@link IObservableValue} with objects that * follow standard bean method naming conventions but notify an * {@link IPropertyChangeListener} when the property changes. */ public class JFaceProperty extends SimpleValueProperty { private Class returnType; private Method setterMethod; private Method getterMethod; private final String property; private Method removePropertyListenerMethod; private Method addPropertyListenerMethod; private static String getSetterName(String fieldName) { return "set" + toMethodSuffix(fieldName); //$NON-NLS-1$ } private static String getGetterName(String fieldName) { return "get" + toMethodSuffix(fieldName); //$NON-NLS-1$ } private static String getBooleanGetterName(String fieldName) { return "is" + toMethodSuffix(fieldName); //$NON-NLS-1$ } private static String toMethodSuffix(String fieldName) { if (Character.isLowerCase(fieldName.charAt(0))) { return Character.toUpperCase(fieldName.charAt(0)) + fieldName.substring(1); } return fieldName; } class Listener extends NativePropertyListener implements IPropertyChangeListener { public Listener(ISimplePropertyListener listener) { super(JFaceProperty.this, listener); } @Override public void propertyChange(PropertyChangeEvent event) { if (event.getProperty().equals(JFaceProperty.this.property)) { fireChange(event.getSource(), null); } } @Override protected void doAddTo(Object model) { try { addPropertyListenerMethod.invoke(model, new Object[] { this }); } catch (Exception e) { throw new IllegalStateException(e.getMessage()); } } @Override protected void doRemoveFrom(Object model) { try { removePropertyListenerMethod.invoke(model, new Object[] { this }); } catch (Exception e) { throw new IllegalStateException(e.getMessage()); } } } /** * @param fieldName * @param property * @param clazz */ public JFaceProperty(String fieldName, String property, Class clazz) { this.property = property; // Create all the necessary method ahead of time to ensure they are // available try { try { String getterName = getGetterName(fieldName); getterMethod = clazz.getMethod(getterName, new Class[] {}); } catch (NoSuchMethodException e) { String getterName = getBooleanGetterName(fieldName); getterMethod = clazz.getMethod(getterName, new Class[] {}); } returnType = getterMethod.getReturnType(); setterMethod = clazz.getMethod(getSetterName(fieldName), new Class[] { returnType }); addPropertyListenerMethod = clazz .getMethod( "addPropertyChangeListener", new Class[] { IPropertyChangeListener.class }); //$NON-NLS-1$ removePropertyListenerMethod = clazz .getMethod( "removePropertyChangeListener", new Class[] { IPropertyChangeListener.class }); //$NON-NLS-1$ } catch (SecurityException e) { throw new IllegalArgumentException(); } catch (NoSuchMethodException e) { throw new IllegalArgumentException(); } } @Override public INativePropertyListener adaptListener( ISimplePropertyListener listener) { return new Listener(listener); } @Override protected Object doGetValue(Object model) { try { return getterMethod.invoke(model, new Object[] {}); } catch (InvocationTargetException e) { throw new IllegalStateException(e.getMessage()); } catch (IllegalAccessException e) { throw new IllegalStateException(e.getMessage()); } } @Override protected void doSetValue(Object model, Object value) { try { setterMethod.invoke(model, new Object[] { value }); } catch (IllegalAccessException e) { throw new IllegalStateException(e.getMessage()); } catch (InvocationTargetException e) { throw new IllegalStateException(e.getMessage()); } } @Override public Object getValueType() { return returnType; } }