/*
* (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.Iterator;
import java.util.Vector;
import java.util.WeakHashMap;
import org.openflexo.foundation.FlexoEditor;
import org.openflexo.foundation.FlexoException;
import org.openflexo.foundation.FlexoModelObject;
import org.openflexo.foundation.rm.FlexoProject;
import org.openflexo.foundation.rm.FlexoStorageResource;
import org.openflexo.foundation.rm.StorageResourceData;
/**
*
* Abstract representation of an action on Flexo model (model edition primitive) which can be undone and redone
*
* @author sguerin
*/
public abstract class FlexoUndoableAction<A extends FlexoUndoableAction<A, T1, T2>, T1 extends FlexoModelObject, T2 extends FlexoModelObject>
extends FlexoAction<A, T1, T2> {
private WeakHashMap<FlexoStorageResource<?>, Object> _modifiedResources;
public FlexoUndoableAction(FlexoActionType<A, T1, T2> actionType, T1 focusedObject, Vector<T2> globalSelection, FlexoEditor editor) {
super(actionType, focusedObject, globalSelection, editor);
_modifiedResources = new WeakHashMap<FlexoStorageResource<?>, Object>();
}
protected FlexoProject getProject() {
if (getEditor() != null) {
return getEditor().getProject();
}
return null;
}
/**
* Overrides doAction
*
* @see org.openflexo.foundation.action.FlexoAction#doAction(java.awt.event.ActionEvent)
*/
@Override
public final A doActionInContext() throws FlexoException {
// Let's keep in memory the modified resources
_modifiedResources.clear();
if (getProject() != null) {
for (FlexoStorageResource<? extends StorageResourceData> r : getProject().getStorageResources()) {
if (!r.isModified()) {
_modifiedResources.put(r, null);
}
}
}
A action;
try {
action = super.doActionInContext();
} catch (FlexoException e1) {
_modifiedResources.clear();
throw e1;
}
// Now we remove all the resources that are still not modified. The left delta are the resources that have been directly modified by
// this action (and the embedded ones)
if (getProject() != null) {
for (FlexoStorageResource<? extends StorageResourceData> r : getProject().getStorageResources()) {
if (!r.isModified()) {
_modifiedResources.remove(r);
}
}
}
return action;
}
public final A undoActionInContext() throws FlexoException {
// Let's keep in memory the modified resources
executionStatus = ExecutionStatus.EXECUTING_UNDO_CORE;
_modifiedResources.clear();
if (getProject() != null) {
for (FlexoStorageResource<? extends StorageResourceData> r : getProject().getStorageResources()) {
if (!r.isModified()) {
_modifiedResources.put(r, null);
}
}
}
try {
undoAction(getContext());
executionStatus = ExecutionStatus.HAS_SUCCESSFULLY_UNDONE;
} catch (FlexoException e1) {
executionStatus = ExecutionStatus.FAILED_UNDO_EXECUTION;
_modifiedResources.clear();
throw e1;
}
// Now we remove all the resources that are still not modified. The left delta are the resources that have been directly modified by
// this action (and the embedded ones)
if (getProject() != null) {
for (FlexoStorageResource<? extends StorageResourceData> r : getProject().getStorageResources()) {
if (!r.isModified()) {
_modifiedResources.remove(r);
}
}
}
Iterator<FlexoStorageResource<?>> i = _modifiedResources.keySet().iterator();
while (i.hasNext()) {
FlexoStorageResource<?> r = i.next();
r.getResourceData().clearIsModified(true);
}
return (A) this;
}
public final A undoAction() {
if (getEditor() != null) {
getEditor().performUndoAction((A) this, null);
} else {
try {
undoActionInContext();
} catch (FlexoException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return (A) this;
}
protected abstract void undoAction(Object context) throws FlexoException;
public final A redoActionInContext() throws RedoException {
try {
executionStatus = ExecutionStatus.EXECUTING_REDO_CORE;
redoAction(getContext());
executionStatus = ExecutionStatus.HAS_SUCCESSFULLY_REDONE;
} catch (FlexoException e) {
executionStatus = ExecutionStatus.FAILED_REDO_EXECUTION;
throw new RedoException(e);
}
return (A) this;
}
public final A redoAction() {
if (getEditor() != null) {
getEditor().performRedoAction((A) this, null);
} else {
try {
redoActionInContext();
} catch (FlexoException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return (A) this;
}
protected abstract void redoAction(Object context) throws FlexoException;
@Override
public void delete() {
_modifiedResources.clear();
super.delete();
}
}