/* * (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.foundation.action; import java.util.Hashtable; import java.util.List; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; import org.openflexo.foundation.FlexoModelObject; import org.openflexo.logging.FlexoLogger; public class ExecutionContext { static final Logger logger = FlexoLogger.getLogger(FlexoAction.class.getPackage().getName()); FlexoAction<?, ?, ?> _action; private Hashtable<String, FlexoModelObject> _objectsCreatedWhileExecutingAction; private Hashtable<String, FlexoModelObject> _objectsDeletedWhileExecutingAction; public ExecutionContext(FlexoAction<?, ?, ?> action) { _action = action; _objectsCreatedWhileExecutingAction = new Hashtable<String, FlexoModelObject>(); _objectsDeletedWhileExecutingAction = new Hashtable<String, FlexoModelObject>(); _singleProperties = new Vector<SingleProperty<?>>(); _vectorProperties = new Vector<VectorProperty<?>>(); } public void objectCreated(String key, FlexoModelObject object) { _objectsCreatedWhileExecutingAction.put(key, object); } public void objectDeleted(String key, FlexoModelObject object) { _objectsDeletedWhileExecutingAction.put(key, object); } public Hashtable<String, FlexoModelObject> getObjectsCreatedWhileExecutingAction() { return _objectsCreatedWhileExecutingAction; } public Hashtable<String, FlexoModelObject> getObjectsDeletedWhileExecutingAction() { return _objectsDeletedWhileExecutingAction; } protected class SingleProperty<T> { protected String _propertyKey; protected T _originalValue; protected T _value; protected FlexoAction<?, ?, ?> _actionWhereThisValueWasInstanciated; protected String _keyOfActionWhereThisValueWasInstanciated; protected SingleProperty(String propertyKey, List<FlexoAction<?, ?, ?>> previouslyExecutedActions) { _propertyKey = propertyKey; _value = (T) _action.objectForKey(propertyKey); _originalValue = _value; for (FlexoAction<?, ?, ?> a : previouslyExecutedActions) { Hashtable<String, FlexoModelObject> objectsCreatedByAction = a.getExecutionContext() .getObjectsCreatedWhileExecutingAction(); for (String k : objectsCreatedByAction.keySet()) { if (objectsCreatedByAction.get(k).equals(_value)) { _keyOfActionWhereThisValueWasInstanciated = k; _actionWhereThisValueWasInstanciated = a; if (logger.isLoggable(Level.FINE)) { logger.fine("SingleProperty: " + propertyKey + ": Action " + _action + " property " + propertyKey + " is a value created when executing action " + a.toSimpleString() + " for key " + k); } } } } } protected T getValue() { return _value; } protected void setValue(T newValue) { _action.setObjectForKey(newValue, _propertyKey); _value = newValue; } public void notifyExternalObjectCreatedByAction(T object, FlexoAction<?, ?, ?> action, String key, boolean considerAsOriginal) { if (action == _actionWhereThisValueWasInstanciated && key.equals(_keyOfActionWhereThisValueWasInstanciated)) { if (logger.isLoggable(Level.FINE)) { logger.fine("Object " + object + " was created with key " + key + " and this object is also referenced in " + _action + " with property " + _propertyKey); } T oldValue = getValue(); setValue(object); _action.replacedSinglePropertyValue(_propertyKey, object, oldValue, _originalValue); _originalValue = object; } } public void notifyExternalObjectDeletedByAction(T object, FlexoAction<?, ?, ?> action, String key, boolean considerAsOriginal) { if (action == _actionWhereThisValueWasInstanciated && key.equals(_keyOfActionWhereThisValueWasInstanciated)) { if (logger.isLoggable(Level.FINE)) { logger.fine("Object " + object + " was deleted with key " + key + " and this object is also referenced in " + _action + " with property " + _propertyKey); } T oldValue = getValue(); setValue(null); _action.replacedSinglePropertyValue(_propertyKey, null, oldValue, _originalValue); } } } protected class VectorProperty<T> { protected String _propertyKey; protected Vector<T> _values; protected Vector<PersistentValue> _persistentValues; protected class PersistentValue { protected T _value; protected FlexoAction<?, ?, ?> _actionWhereThisValueWasInstanciated; protected String _keyOfActionWhereThisValueWasInstanciated; protected int index; protected T _originalValue; } protected VectorProperty(String propertyKey, List<FlexoAction<?, ?, ?>> previouslyExecutedActions) { _propertyKey = propertyKey; _values = (Vector<T>) _action.objectForKey(propertyKey); _persistentValues = new Vector<PersistentValue>(); // If there is no values, just return if (_values == null) { return; } int index = 0; for (T value : _values) { for (FlexoAction<?, ?, ?> a : previouslyExecutedActions) { Hashtable<String, FlexoModelObject> objectsCreatedByAction = a.getExecutionContext() .getObjectsCreatedWhileExecutingAction(); for (String k : objectsCreatedByAction.keySet()) { if (objectsCreatedByAction.get(k).equals(value)) { PersistentValue newPersistentValue = new PersistentValue(); newPersistentValue._value = value; newPersistentValue._originalValue = value; newPersistentValue._keyOfActionWhereThisValueWasInstanciated = k; newPersistentValue._actionWhereThisValueWasInstanciated = a; newPersistentValue.index = index; _persistentValues.add(newPersistentValue); if (logger.isLoggable(Level.INFO)) { logger.info("VectorProperty: " + propertyKey + " at index " + index + ": Action " + _action + " property " + propertyKey + " is a value created when executing action " + a.toSimpleString() + " for key " + k); } } } } index++; } } protected Vector<T> getValues() { return _values; } protected T getValueAtIndex(int index) { if (_values != null && index < _values.size()) { return _values.get(index); } return null; } protected void setValueAtIndex(T value, int index) { if (_values != null && index < _values.size()) { _values.setElementAt(value, index); } } public void notifyExternalObjectCreatedByAction(T object, FlexoAction<?, ?, ?> action, String key, boolean considerAsOriginal) { for (PersistentValue persistentValue : _persistentValues) { if (logger.isLoggable(Level.FINEST)) { logger.finest("persistentValue action=" + persistentValue._actionWhereThisValueWasInstanciated + " key=" + persistentValue._keyOfActionWhereThisValueWasInstanciated + " index=" + persistentValue.index); } if (action == persistentValue._actionWhereThisValueWasInstanciated && key.equals(persistentValue._keyOfActionWhereThisValueWasInstanciated)) { if (logger.isLoggable(Level.FINE)) { logger.fine("Object " + object + " was created with key " + key + " and this object is also referenced in " + _action + " with property " + _propertyKey + " at index " + persistentValue.index); } T oldValue = getValueAtIndex(persistentValue.index); setValueAtIndex(object, persistentValue.index); _action.replacedVectorPropertyValue(_propertyKey, persistentValue.index, object, oldValue, persistentValue._originalValue); persistentValue._originalValue = object; } } } public void notifyExternalObjectDeletedByAction(T object, FlexoAction<?, ?, ?> action, String key, boolean considerAsOriginal) { for (PersistentValue persistentValue : _persistentValues) { if (action == persistentValue._actionWhereThisValueWasInstanciated && key.equals(persistentValue._keyOfActionWhereThisValueWasInstanciated)) { if (logger.isLoggable(Level.FINE)) { logger.fine("Object " + object + " was deleted with key " + key + " and this object is also referenced in " + _action + " with property " + _propertyKey + " at index " + persistentValue.index); } T oldValue = getValueAtIndex(persistentValue.index); setValueAtIndex(null, persistentValue.index); _action.replacedVectorPropertyValue(_propertyKey, persistentValue.index, null, oldValue, persistentValue._originalValue); } } } } private Vector<SingleProperty<?>> _singleProperties; private Vector<VectorProperty<?>> _vectorProperties; public void saveExecutionContext(List<FlexoAction<?, ?, ?>> previouslyExecutedActions) { Vector<String> allProperties = new Vector<String>(); allProperties.add("focusedObject"); allProperties.add("globalSelection"); for (String k : _action.getActionType().getPersistentProperties()) { allProperties.add(k); } for (String key : allProperties) { if (_action.isSingleProperty(key)) { _singleProperties.add(createNewSingleProperty(key, _action.getTypeForKey(key), previouslyExecutedActions)); } else if (_action.isVectorProperty(key)) { _vectorProperties.add(createNewVectorProperty(key, _action.getTypeForKey(key), previouslyExecutedActions)); } } for (SingleProperty<?> sp : _singleProperties) { if (logger.isLoggable(Level.FINE)) { logger.fine("Created SingleProperty " + sp._propertyKey + " value: " + sp.getValue()); } } for (VectorProperty<?> sp : _vectorProperties) { if (logger.isLoggable(Level.FINE)) { logger.fine("Created VectorProperty " + sp._propertyKey + " value: " + sp.getValues()); } } } public void notifyExternalObjectCreatedByAction(FlexoModelObject object, FlexoAction<?, ?, ?> action, String key, boolean considerAsOriginal) { for (SingleProperty sp : _singleProperties) { sp.notifyExternalObjectCreatedByAction(object, action, key, considerAsOriginal); } for (VectorProperty sp : _vectorProperties) { sp.notifyExternalObjectCreatedByAction(object, action, key, considerAsOriginal); } } public void notifyExternalObjectDeletedByAction(FlexoModelObject object, FlexoAction<?, ?, ?> action, String key, boolean considerAsOriginal) { for (SingleProperty sp : _singleProperties) { sp.notifyExternalObjectDeletedByAction(object, action, key, considerAsOriginal); } for (VectorProperty sp : _vectorProperties) { sp.notifyExternalObjectDeletedByAction(object, action, key, considerAsOriginal); } } private <T> SingleProperty<T> createNewSingleProperty(String key, Class<T> type, List<FlexoAction<?, ?, ?>> previouslyExecutedActions) { return new SingleProperty<T>(key, previouslyExecutedActions); } private <T> VectorProperty<T> createNewVectorProperty(String key, Class<T> type, List<FlexoAction<?, ?, ?>> previouslyExecutedActions) { return new VectorProperty<T>(key, previouslyExecutedActions); } public void delete() { _objectsCreatedWhileExecutingAction.clear(); _objectsDeletedWhileExecutingAction.clear(); _singleProperties.clear(); _vectorProperties.clear(); } }