package org.rr.jeborker.gui.action;
import java.awt.event.ActionEvent;
import java.util.HashMap;
import java.util.logging.Level;
import javax.swing.AbstractAction;
import javax.swing.Action;
import org.rr.commons.log.LoggerFactory;
import org.rr.commons.utils.BooleanUtils;
import org.rr.commons.utils.compression.truezip.TrueZipUtils;
import org.rr.jeborker.app.FileRefreshBackground;
/**
* {@link ApplicationAction} is an Action delegate which is delivered if
* an action is requested from the {@link ActionFactory}.
*/
public class ApplicationAction extends AbstractAction {
private static final long serialVersionUID = -2641414612764259731L;
/**
* Can be used as key for the actions to get marked as singleton.
* Example: <code>putValue(ApplicationAction.SINGLETON_ACTION_KEY, Boolean.TRUE);</code>
*/
public static final String SINGLETON_ACTION_KEY = "singletonAction";
/**
* Can be used as key for the actions to get marked they're not invoked in a separate thread.
* Example: <code>putValue(ApplicationAction.NON_THREADED_ACTION_KEY, Boolean.TRUE);</code>
*/
public static final String NON_THREADED_ACTION_KEY = "nonThreadedAction";
private static final HashMap<Class<?>, ApplicationAction> singletonInstances = new HashMap<Class<?>, ApplicationAction>();
private final Action realAction;
private ActionCallback callback;
public static ApplicationAction getInstance(Action realAction, ActionCallback callback) {
Object isSingleton = realAction.getValue(SINGLETON_ACTION_KEY);
if(isSingleton instanceof Boolean && ((Boolean)isSingleton).booleanValue()) {
Class<?> realActionClass = realAction.getClass();
if(singletonInstances.containsKey(realActionClass)) {
ApplicationAction action = singletonInstances.get(realActionClass);
action.setCallback(callback);
return action;
} else {
ApplicationAction action = new ApplicationAction(realAction, callback);
singletonInstances.put(realActionClass, action);
return action;
}
}
return new ApplicationAction(realAction, callback);
}
private ApplicationAction(Action realAction, ActionCallback callback) {
this.callback = callback;
this.realAction = realAction;
this.setEnabled(realAction.isEnabled());
}
public void invokeAction() {
this.invokeAction(null);
}
public void invokeAction(final ActionEvent e) {
this.invokeAction(e, null);
}
void setCallback(ActionCallback callback) {
this.callback = callback;
}
public void invokeAction(final ActionEvent e, final Runnable invokeLater) {
final Object noRealActionThreading = realAction.getValue(NON_THREADED_ACTION_KEY);
final boolean noRealActionThreadingValue = BooleanUtils.toBoolean(noRealActionThreading, Boolean.FALSE);
final Object noAppActionThreading = this.getValue(NON_THREADED_ACTION_KEY);
final boolean noAppActionThreadingValue = BooleanUtils.toBoolean(noAppActionThreading, Boolean.FALSE);
if(noRealActionThreadingValue || noAppActionThreadingValue) {
startAction();
try {
this.realAction.actionPerformed(e);
if(this.realAction instanceof IFinalizeAction) {
((IFinalizeAction)this.realAction).finalizeAction(0);
}
} finally {
endAction();
fireAfterAction();
}
if(invokeLater != null) {
invokeLater.run();
}
} else {
ActionEventQueue.addActionEvent(this, e, invokeLater);
}
}
void invokeRealAction(ActionEvent e) {
startAction();
try {
this.realAction.actionPerformed(e);
if(this.realAction instanceof IFinalizeAction) {
((IFinalizeAction) this.realAction).finalizeAction(0);
}
} catch(Exception ex) {
LoggerFactory.getLogger(this.getClass()).log(Level.WARNING, "Failed to invoke action", ex);
} finally {
endAction();
fireAfterAction();
}
}
@Override
public void actionPerformed(ActionEvent e) {
startAction();
try {
this.invokeAction(e);
} finally {
endAction();
}
}
@Override
public Object getValue(String key) {
return realAction.getValue(key);
}
@Override
public void setEnabled(boolean newValue) {
super.setEnabled(newValue);
realAction.setEnabled(newValue);
}
@Override
public void putValue(String key, Object newValue) {
super.putValue(key, newValue);
realAction.putValue(key, newValue);
}
private void startAction() {
FileRefreshBackground.setDisabled(true);
}
private void endAction() {
FileRefreshBackground.setDisabled(false);
TrueZipUtils.unmout();
}
private void fireAfterAction() {
if(callback != null) {
try {
callback.afterAction();
} catch(Exception e) {
LoggerFactory.getLogger(this).log(Level.WARNING, "after action callback caused an exception", e);
}
}
}
}