/*
* (c) Copyright 2010-2011 AgileBirds
*
* This file is part of OpenFlexo.
*
* OpenFlexo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* OpenFlexo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with OpenFlexo. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openflexo.inspector.widget.propertylist;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.openflexo.antar.expr.Constant.ObjectSymbolicConstant;
import org.openflexo.antar.expr.Constant.StringConstant;
import org.openflexo.antar.expr.Expression;
import org.openflexo.antar.expr.Function;
import org.openflexo.inspector.InspectableObject;
import org.openflexo.inspector.model.PropertyListAction;
import org.openflexo.kvc.KeyValueCoding;
/**
* Please comment this class
*
* @author sguerin
*
*/
public class PropertyListActionListener implements ActionListener {
private static final Logger logger = Logger.getLogger(PropertyListActionListener.class.getPackage().getName());
private PropertyListAction _plAction;
private InspectableObject _selectedObject;
private Vector<InspectableObject> selectedObjects;
private InspectableObject _model;
private PropertyListTableModel _tableModel;
public PropertyListActionListener(PropertyListAction plAction, PropertyListTableModel tableModel) {
super();
_plAction = plAction;
_selectedObject = null;
_tableModel = tableModel;
}
public boolean isAddAction() {
return _plAction.type.equals("ADD");
}
public boolean isActive(InspectableObject selectedObject) {
boolean returned = false;
if (_plAction.type.equals("ADD")) {
returned = true;
} else if (_plAction.type.equals("DELETE")) {
returned = selectedObject != null;
} else if (_plAction.type.equals("ACTION")) {
returned = selectedObject != null;
} else if (_plAction.type.equals("STATIC_ACTION")) {
return isAvailable(null);
}
if (_plAction.getIsAvailableExpression() != null && selectedObject != null && returned == true) {
return isAvailable(selectedObject);
}
return returned;
}
private KeyValueCoding getTargetObject(KeyValueCoding sourceObject, String listAccessor) {
if (listAccessor == null) {
return null;
}
StringTokenizer strTok = new StringTokenizer(listAccessor, ".");
String accessor;
Object currentObject = sourceObject;
while (strTok.hasMoreTokens() && currentObject != null && currentObject instanceof KeyValueCoding) {
accessor = strTok.nextToken();
if (strTok.hasMoreTokens()) {
if (currentObject != null) {
currentObject = ((KeyValueCoding) currentObject).objectForKey(accessor);
}
}
}
if (currentObject instanceof KeyValueCoding) {
return (KeyValueCoding) currentObject;
} else {
if (currentObject == null) {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Could not find target object : currentObject is null !");
}
} else {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Could not find target object : must be a KeyValueCoding object but is a " + currentObject.getClass());
}
}
return null;
}
}
private String getLastAccessor(String listAccessor) {
if (listAccessor == null) {
return null;
}
int lastDotPosition = listAccessor.lastIndexOf(".");
if (lastDotPosition < 0) {
return listAccessor;
}
return listAccessor.substring(lastDotPosition + 1, listAccessor.length());
}
@Override
public void actionPerformed(ActionEvent e) {
if (_plAction.type.equals(PropertyListAction.ADD_TYPE)) {
performAction();
} else if (_plAction.type.equals(PropertyListAction.STATIC_ACTION_TYPE)) {
performAction();
} else if (_plAction.type.equals(PropertyListAction.DELETE_TYPE)) {
performAction(getSelectedObject(), getSelectedObjects());
} else if (_plAction.type.equals(PropertyListAction.ACTION_TYPE)) {
performAction(getSelectedObject(), getSelectedObjects());
}
}
public InspectableObject getSelectedObject() {
return _selectedObject;
}
public void setSelectedObject(InspectableObject selectedObject) {
_selectedObject = selectedObject;
}
public InspectableObject getModel() {
return _model;
}
public void setModel(InspectableObject model) {
_model = model;
}
// TODO: rewrite this property with AnTAR (Expression.evaluateExpression())...
protected void performAction() {
if (getActionMethod(getSelectedObject()) != null) {
Object[] params;
if (_plAction.getMethodExpression() instanceof Function) {
params = new Object[_plAction.getMethodExpressionArgs().size()];
for (int i = 0; i < _plAction.getMethodExpressionArgs().size(); i++) {
Expression arg = _plAction.getMethodExpressionArgs().get(i);
if (arg instanceof StringConstant) {
params[i] = ((StringConstant) arg).getValue();
} else if (arg == ObjectSymbolicConstant.NULL) {
params[i] = null;
} else if (arg == ObjectSymbolicConstant.THIS) {
params[i] = getSelectedObject();
}
}
} else {
params = new Object[0];
}
try {
Object targetObject = getTargetObject(getModel(), _plAction.getMethodName());
if (logger.isLoggable(Level.FINE)) {
logger.fine("invoking " + getActionMethod(getSelectedObject()) + " on object" + targetObject);
}
getActionMethod(getSelectedObject()).invoke(targetObject, params);
_tableModel.fireTableDataChanged();
_tableModel.getPropertyListWidget().updateWidgetFromModel();
} catch (IllegalArgumentException e) {
// Warns about the exception
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Exception raised: " + e.getClass().getName() + ". See console for details.");
}
e.printStackTrace();
} catch (IllegalAccessException e) {
// Warns about the exception
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Exception raised: " + e.getClass().getName() + ". See console for details.");
}
e.printStackTrace();
} catch (InvocationTargetException e) {
// Warns about the exception
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Exception raised: " + e.getClass().getName() + ". See console for details.");
}
e.printStackTrace();
}
}
}
// TODO: rewrite this property with AnTAR (Expression.evaluateExpression())...
protected void performAction(InspectableObject paramObject, Vector<InspectableObject> selectedObjects) {
if (selectedObjects == null) {
selectedObjects = new Vector<InspectableObject>();
}
if (paramObject != null && !selectedObjects.contains(paramObject)) {
selectedObjects.add(paramObject);
}
for (InspectableObject object : selectedObjects) {
if (getActionMethod(paramObject) != null) {
Object[] params;
if (_plAction.getMethodExpression() instanceof Function) {
params = new Object[_plAction.getMethodExpressionArgs().size()];
for (int i = 0; i < _plAction.getMethodExpressionArgs().size(); i++) {
Expression arg = _plAction.getMethodExpressionArgs().get(i);
if (arg instanceof StringConstant) {
params[i] = ((StringConstant) arg).getValue();
} else if (arg == ObjectSymbolicConstant.NULL) {
params[i] = null;
} else if (arg == ObjectSymbolicConstant.THIS) {
params[i] = paramObject;
}
}
} else {
params = new Object[1];
params[0] = object;
}
try {
Object targetObject = getTargetObject(getModel(), _plAction.getMethodName());
if (logger.isLoggable(Level.FINE)) {
logger.fine("invoking " + getActionMethod(paramObject) + " on object" + targetObject);
}
getActionMethod(paramObject).invoke(targetObject, params);
_tableModel.fireTableDataChanged();
_tableModel.getPropertyListWidget().updateWidgetFromModel();
} catch (IllegalArgumentException e) {
// Warns about the exception
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Exception raised: " + e.getClass().getName() + ". See console for details.");
}
e.printStackTrace();
} catch (IllegalAccessException e) {
// Warns about the exception
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Exception raised: " + e.getClass().getName() + ". See console for details.");
}
e.printStackTrace();
} catch (InvocationTargetException e) {
// Warns about the exception
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Exception raised: " + e.getClass().getName() + ". See console for details.");
}
e.printStackTrace();
}
} else {
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Could not find method: " + _plAction.getMethodName());
}
}
}
}
private Method _actionMethod;
// TODO: rewrite this property with AnTAR (Expression.evaluateExpression())...
private Method getActionMethod(InspectableObject paramObject) {
if (_actionMethod == null) {
String methodName = getLastAccessor(_plAction.getMethodName());
if (getModel() != null) {
KeyValueCoding targetObject = getTargetObject(getModel(), _plAction.getMethodName());
if (targetObject == null) {
return null;
}
Class targetClass = targetObject.getClass();
Class[] methodClassParams = null;
if (_plAction.getMethodExpression() instanceof Function) {
methodClassParams = new Class[_plAction.getMethodExpressionArgs().size()];
for (int i = 0; i < _plAction.getMethodExpressionArgs().size(); i++) {
Expression arg = _plAction.getMethodExpressionArgs().get(i);
if (arg instanceof StringConstant) {
methodClassParams[i] = String.class;
} else if (arg == ObjectSymbolicConstant.NULL) {
methodClassParams[i] = Object.class;
} else if (arg == ObjectSymbolicConstant.THIS) {
methodClassParams[i] = paramObject.getClass();
}
}
} else {
if (_plAction.type.equals(PropertyListAction.ADD_TYPE) || _plAction.type.equals(PropertyListAction.STATIC_ACTION_TYPE)) {
methodClassParams = new Class[0];
} else if (_plAction.type.equals(PropertyListAction.DELETE_TYPE)
|| _plAction.type.equals(PropertyListAction.ACTION_TYPE)) {
if (paramObject != null) {
methodClassParams = new Class[1];
methodClassParams[0] = paramObject.getClass();
}
}
}
if (methodClassParams != null) {
try {
_actionMethod = lookupMethod(targetClass, methodName, methodClassParams);
} catch (SecurityException e) {
// Warns about the exception
if (logger.isLoggable(Level.WARNING)) {
logger.warning("SecurityException raised: " + e.getClass().getName() + ". See console for details.");
}
e.printStackTrace();
} catch (NoSuchMethodException e) {
// Warns about the exception
if (logger.isLoggable(Level.WARNING)) {
logger.warning("NoSuchMethodException raised: unable to find method " + methodName + " for class "
+ targetClass);
}
e.printStackTrace();
}
}
}
}
return _actionMethod;
}
private Method _isAvailableMethod;
// TODO: rewrite this property with AnTAR (Expression.evaluateExpression())...
private Method getAvailableMethod(InspectableObject paramObject) {
if (_isAvailableMethod == null) {
String methodName = getLastAccessor(_plAction.getIsAvailableMethodName());
if (methodName == null || methodName.trim().equals("")) {
return null;
}
if (getModel() != null) {
// System.out.println("Model: "+getModel());
KeyValueCoding targetObject = getTargetObject(getModel(), _plAction.getIsAvailableMethodName());
if (targetObject == null) {
return null;
}
Class targetClass = targetObject.getClass();
Class[] methodClassParams = null;
if (_plAction.getIsAvailableExpression() instanceof Function) {
methodClassParams = new Class[_plAction.getIsAvailableExpressionArgs().size()];
for (int i = 0; i < _plAction.getIsAvailableExpressionArgs().size(); i++) {
Expression arg = _plAction.getIsAvailableExpressionArgs().get(i);
if (arg instanceof StringConstant) {
methodClassParams[i] = String.class;
} else if (arg == ObjectSymbolicConstant.NULL) {
methodClassParams[i] = Object.class;
} else if (arg == ObjectSymbolicConstant.THIS) {
methodClassParams[i] = paramObject.getClass();
}
}
} else {
if (_plAction.type.equals(PropertyListAction.STATIC_ACTION_TYPE)) {
methodClassParams = new Class[0];
} else if (paramObject != null) {
methodClassParams = new Class[1];
methodClassParams[0] = paramObject.getClass();
}
}
try {
_isAvailableMethod = lookupMethod(targetClass, methodName, methodClassParams);
// System.out.println("Found method "+_isAvailableMethod);
} catch (SecurityException e) {
// Warns about the exception
if (logger.isLoggable(Level.WARNING)) {
logger.warning("SecurityException raised. See console for details.");
}
e.printStackTrace();
} catch (NoSuchMethodException e) {
// Warns about the exception
if (logger.isLoggable(Level.WARNING)) {
logger.warning("NoSuchMethodException raised. See console for details.");
}
e.printStackTrace();
}
} else {
logger.info("Pas de modele");
}
}
return _isAvailableMethod;
}
// TODO: rewrite this property with AnTAR (Expression.evaluateExpression())...
private boolean isAvailable(InspectableObject paramObject) {
if (getAvailableMethod(paramObject) != null) {
// System.out.println("Available "+getAvailableMethod(paramObject));
Object[] params;
if (_plAction.getIsAvailableExpression() instanceof Function) {
params = new Object[_plAction.getIsAvailableExpressionArgs().size()];
for (int i = 0; i < _plAction.getIsAvailableExpressionArgs().size(); i++) {
Expression arg = _plAction.getIsAvailableExpressionArgs().get(i);
if (arg instanceof StringConstant) {
params[i] = ((StringConstant) arg).getValue();
} else if (arg == ObjectSymbolicConstant.NULL) {
params[i] = null;
} else if (arg == ObjectSymbolicConstant.THIS) {
params[i] = paramObject;
}
}
} else {
if (getAvailableMethod(paramObject).getParameterTypes().length == 0) {
params = new Object[0];
} else if (getAvailableMethod(paramObject).getParameterTypes().length == 1) {
params = new Object[1];
params[0] = paramObject;
} else {
return false;
}
}
try {
Object targetObject = getTargetObject(getModel(), _plAction.getIsAvailableMethodName());
if (logger.isLoggable(Level.FINE)) {
logger.fine("invoking " + getAvailableMethod(paramObject) + " on object" + targetObject);
}
return ((Boolean) getAvailableMethod(paramObject).invoke(targetObject, params)).booleanValue();
} catch (IllegalArgumentException e) {
// Warns about the exception
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Exception raised: " + e.getClass().getName() + ". See console for details.");
}
e.printStackTrace();
} catch (IllegalAccessException e) {
// Warns about the exception
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Exception raised: " + e.getClass().getName() + ". See console for details.");
}
e.printStackTrace();
} catch (InvocationTargetException e) {
// Warns about the exception
if (logger.isLoggable(Level.WARNING)) {
logger.warning("Exception raised: " + e.getClass().getName() + ". See console for details.");
}
e.printStackTrace();
}
}
return false;
}
public Vector<InspectableObject> getSelectedObjects() {
return selectedObjects;
}
public void setSelectedObjects(Vector<InspectableObject> selectedObjects) {
this.selectedObjects = selectedObjects;
}
public static Method lookupMethod(Class aClass, String methodName, Class[] parameterTypes) throws SecurityException,
NoSuchMethodException {
/*String s = "";
for (Class c : parameterTypes) s += c.getName()+" ";
System.out.println("Search method: "+methodName+" ( "+s+")");*/
if (parameterTypes == null || parameterTypes.length == 0) {
return aClass.getMethod(methodName, parameterTypes);
}
if (parameterTypes.length == 1) {
while (parameterTypes[0] != null) {
try {
return aClass.getMethod(methodName, parameterTypes);
} catch (NoSuchMethodException e) {
}
parameterTypes[0] = parameterTypes[0].getSuperclass();
}
logger.warning("Could not find method " + methodName + " on " + aClass);
throw new NoSuchMethodException();
} else {
// TODO same code for multiple parameters, trying to generalize parameters
return aClass.getMethod(methodName, parameterTypes);
}
}
}