summaryrefslogtreecommitdiff
path: root/pdf-over-gui/src/main/java/at/asit/pdfover/gui/workflow/StateMachine.java
diff options
context:
space:
mode:
authorJakob Heher <jakob.heher@iaik.tugraz.at>2022-07-06 14:22:19 +0200
committerJakob Heher <jakob.heher@iaik.tugraz.at>2022-07-06 14:22:19 +0200
commit7ed30d78c576e5c6f7193ee917309bafb0eb35ea (patch)
treefbe976b1a6688f628390c0fcdc943cf2ba7da4bc /pdf-over-gui/src/main/java/at/asit/pdfover/gui/workflow/StateMachine.java
parent18b4c5edd2a2d88d5efa69a1023a13926c53e8fd (diff)
downloadpdf-over-7ed30d78c576e5c6f7193ee917309bafb0eb35ea.tar.gz
pdf-over-7ed30d78c576e5c6f7193ee917309bafb0eb35ea.tar.bz2
pdf-over-7ed30d78c576e5c6f7193ee917309bafb0eb35ea.zip
YAGNI: StateMachine interface
Diffstat (limited to 'pdf-over-gui/src/main/java/at/asit/pdfover/gui/workflow/StateMachine.java')
-rw-r--r--pdf-over-gui/src/main/java/at/asit/pdfover/gui/workflow/StateMachine.java308
1 files changed, 258 insertions, 50 deletions
diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/workflow/StateMachine.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/workflow/StateMachine.java
index 85539eb5..9a71bde2 100644
--- a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/workflow/StateMachine.java
+++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/workflow/StateMachine.java
@@ -15,93 +15,301 @@
*/
package at.asit.pdfover.gui.workflow;
+//Imports
+import java.lang.reflect.Constructor;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.asit.pdfover.gui.MainWindow;
+import at.asit.pdfover.gui.controls.Dialog.BUTTONS;
+import at.asit.pdfover.gui.controls.ErrorDialog;
+import at.asit.pdfover.commons.Messages;
import at.asit.pdfover.gui.workflow.config.ConfigManipulator;
import at.asit.pdfover.gui.workflow.config.ConfigOverlayManipulator;
import at.asit.pdfover.gui.workflow.config.ConfigProvider;
+import at.asit.pdfover.gui.workflow.config.ConfigProviderImpl;
import at.asit.pdfover.gui.workflow.config.PersistentConfigProvider;
+import at.asit.pdfover.gui.workflow.states.PrepareConfigurationState;
import at.asit.pdfover.gui.workflow.states.State;
/**
- *
+ * Workflow holds logical state of signing process and updates the current
+ * logical state
*/
-public interface StateMachine {
- /**
- * Get the ConfigProvider
- * @return the ConfigProvider
- */
- public ConfigProvider getConfigProvider();
+public class StateMachine implements GUIProvider {
- /**
- * Get the PersistentConfigProvider
- * @return the PersistentConfigProvider
- */
- public PersistentConfigProvider getPersistentConfigProvider();
+ private static final Logger log = LoggerFactory.getLogger(StateMachine.class);
+
+ private Status status;
+
+ private PDFSignerImpl pdfSigner;
+
+ private ConfigProviderImpl configProvider;
/**
- * Gets the Config Manipulator
- * @return the config manipulator
+ * Default constructor
+ *
+ * @param cmdLineArgs
*/
- public ConfigManipulator getConfigManipulator();
+ public StateMachine(String[] cmdLineArgs) {
+ this.status = new Status();
+ this.status.setCurrentState(new PrepareConfigurationState(this));
+ this.pdfSigner = new PDFSignerImpl();
+ this.configProvider = new ConfigProviderImpl();
+ setCmdLineArgs(cmdLineArgs);
+ }
/**
- * Gets the Config Overlay Manipulator
- * @return the config overlay manipulator
+ * Sets the workflow state
+ * This method should be used to let the user jump
+ * around between states. This Method also resets certain properties defined
+ * by later states then state
+ *
+ * @param state
*/
- public ConfigOverlayManipulator getConfigOverlayManipulator();
+ public void jumpToState(State state) {
+ this.status.setCurrentState(state);
+ this.invokeUpdate();
+ }
/**
- * Get the PDF Signer
- * @return the PDF Signer
+ * Update workflow logic and let state machine do its job...
*/
- public PDFSigner getPDFSigner();
+ public synchronized void update() {
+ State next = null;
+ while (this.status.getCurrentState() != null) {
+ State current = this.status.getCurrentState();
+ try {
+ current.run();
+ } catch (Exception e) {
+ log.error("StateMachine update: ", e);
+ ErrorDialog errorState = new ErrorDialog(this.getMainShell(),
+ Messages.getString("error.Unexpected"), BUTTONS.OK);
+ //errorState.setException(e);
+ //jumpToState(errorState);
+ errorState.open();
+ this.exit();
+ }
+
+ if (this.exit) {
+ // exit request ignore
+ next = null;
+ this.status.setCurrentState(next);
+ } else {
+
+ if (this.mainWindow != null
+ && !this.mainWindow.getShell().isDisposed()) {
+ log.debug("Allowing MainWindow to update its state for "
+ + current);
+ current.updateMainWindowBehavior();
+ this.mainWindow.applyBehavior();
+ this.mainWindow.doLayout();
+ }
+ next = current.nextState();
+ if (next == current) {
+ break;
+ }
+
+ if (next == null) {
+ log.info("Next state is null -> exit");
+ this.status.setCurrentState(next);
+ break;
+ }
+
+ log.debug("Changing state from: "
+ + current + " to "
+ + next.toString());
+ this.status.setCurrentState(next);
+ }
+ }
+ }
/**
- * Get the Status
- * @return the Status
+ * Invoke Update in UI (Main) Thread
*/
- public Status getStatus();
+ public void invokeUpdate() {
+ if (this.display != null) {
+ this.display.asyncExec(() -> {
+ this.update();
+ });
+ }
+ }
- /**
- * Gets the GUI provider
- * @return the GUI provider
+ private Display display = null;
+
+ private Shell shell = null;
+
+ private Composite container = null;
+
+ private MainWindow mainWindow = null;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * at.asit.pdfover.gui.workflow.StateMachine#display(org.eclipse.swt.widgets
+ * .Composite)
*/
- public GUIProvider getGUIProvider();
+ public void display(Composite composite) {
+ this.mainWindow.setTopControl(composite);
+ }
+
+ private void createMainWindow() {
+ try {
+
+ this.display = Display.getDefault();
+
+ this.mainWindow = new MainWindow(this);
+ this.mainWindow.open();
+
+ this.shell = this.mainWindow.getShell();
+
+ this.container = this.mainWindow.getContainer();
+
+ this.shell.open();
+ this.shell.layout();
+ } catch (Exception e) {
+ log.warn("Main-Window creation FAILED. Reason: " + e.getMessage());
+ this.display = null;
+ this.mainWindow = null;
+ this.shell = null;
+ this.container = null;
+ throw e;
+ }
+ }
/**
- * Jump to specific state
- *
- * Sets the state machine state this method should be used to let the user jump
- * around between states. This Method also resets certain properties defined
- * by later states then the target state.
- *
- * Example: Usually the MainWindow allows the user to jump to the states:
- * DataSourceSelectionState, PositioningState and BKUSelectionState
+ * Gets the Shell for drawing the ui
*
- * @param state the state to jump to
+ * @return Composite
*/
- public void jumpToState(State state);
+ public synchronized Composite getComposite() {
+ // Main window will be built on first call
+ // returns SWT Composite container for states to draw their GUI
+
+ if (this.container == null) {
+ this.createMainWindow();
+ }
+
+ return this.container;
+ }
+
+ public <T> T createComposite(Class<T> compositeClass, int style, State state) {
+ T composite = null;
+ try {
+ Constructor<T> constructor = compositeClass.getDeclaredConstructor(
+ Composite.class, int.class, State.class);
+ composite = constructor.newInstance(getComposite(), style, state);
+ } catch (Exception e) {
+ log.error("Could not create Composite for Class "
+ + compositeClass.getName(), e);
+ }
+ return composite;
+ }
/**
- * Update state machine
- * Calls the next state.
+ * Only returns a shell if one was already created ...
+ *
+ * @return
*/
- public void update();
+ private Shell nonCreatingGetShell() {
+ return this.shell;
+ }
+
+ private boolean exit = false;
/**
- * Update state machine from other thread
- * Calls the next state within the main thread
+ * Exists the Workflow
*/
- public void invokeUpdate();
+ public void exit() {
+ this.exit = true;
+ if (this.shell != null) {
+ this.shell.dispose();
+ }
+ }
/**
- * Exit state machine execution
+ * Only returns a shell if one was already created ...
+ *
+ * @return
*/
- public void exit();
+ private Display nonCreatingGetDisplay() {
+ return this.display;
+ }
/**
- * Gets the command line arguments
- *
- * @return the command line arguments
+ * Workflow main entrance point
*/
- public String[] getCmdArgs();
+ public void start() {
+
+ // Call update to start processing ...
+ update();
+
+ // if a user interaction is required we have a shell ...
+ Shell shell = nonCreatingGetShell();
+ Display display = nonCreatingGetDisplay();
+
+ if (this.status.getCurrentState() == null) {
+ if (shell != null) {
+ this.shell.dispose();
+ }
+ }
+
+ if (shell != null && display != null) {
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch()) {
+ display.sleep();
+ }
+ }
+ display.dispose();
+ }
+ }
+ public ConfigProvider getConfigProvider() {
+ return this.configProvider;
+ }
+ public PersistentConfigProvider getPersistentConfigProvider() {
+ return this.configProvider;
+ }
+ public ConfigManipulator getConfigManipulator() {
+ return this.configProvider;
+ }
+ public ConfigOverlayManipulator getConfigOverlayManipulator() {
+ return this.configProvider;
+ }
+ public Status getStatus() {
+ return this.status;
+ }
+
+ public PDFSigner getPDFSigner() {
+ return this.pdfSigner;
+ }
+
+ public GUIProvider getGUIProvider() {
+ return this;
+ }
+
+ private String[] cmdLineArgs = new String[] {};
+ private void setCmdLineArgs(String[] cmdLineArgs) {
+ this.cmdLineArgs = cmdLineArgs;
+ }
+ public String[] getCmdArgs() {
+ return this.cmdLineArgs;
+ }
+
+
+ public synchronized Shell getMainShell() {
+ if(this.shell == null) {
+ this.createMainWindow();
+ }
+
+ return this.shell;
+ }
+
+ public void reloadResources() {
+ this.mainWindow.reloadLocalization();
+ }
}