From 7ed30d78c576e5c6f7193ee917309bafb0eb35ea Mon Sep 17 00:00:00 2001 From: Jakob Heher Date: Wed, 6 Jul 2022 14:22:19 +0200 Subject: YAGNI: StateMachine interface --- .../src/main/java/at/asit/pdfover/gui/Main.java | 9 +- .../at/asit/pdfover/gui/workflow/StateMachine.java | 308 +++++++++++++--- .../pdfover/gui/workflow/StateMachineImpl.java | 388 --------------------- 3 files changed, 261 insertions(+), 444 deletions(-) delete mode 100644 pdf-over-gui/src/main/java/at/asit/pdfover/gui/workflow/StateMachineImpl.java (limited to 'pdf-over-gui/src/main/java') diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/Main.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/Main.java index e603cd5b..c41b59de 100644 --- a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/Main.java +++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/Main.java @@ -22,10 +22,11 @@ import java.io.IOException; import javax.swing.JOptionPane; import at.asit.pdfover.commons.Constants; +import at.asit.pdfover.gui.workflow.StateMachine; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import at.asit.pdfover.gui.workflow.StateMachineImpl; import iaik.security.provider.IAIK; /** @@ -61,12 +62,8 @@ public class Main { // force keystore type (Adoptium JRE 17 still ships with JKS) System.setProperty("javax.net.ssl.trustStoreType", "jks"); - StateMachineImpl stateMachine = new StateMachineImpl(args); - log.debug("Starting stateMachine ..."); - stateMachine.start(); - - + (new StateMachine(args)).start(); log.debug("Ended stateMachine ..."); } catch (Throwable e) { 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 createComposite(Class compositeClass, int style, State state) { + T composite = null; + try { + Constructor 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(); + } } diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/workflow/StateMachineImpl.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/workflow/StateMachineImpl.java deleted file mode 100644 index 640d42bc..00000000 --- a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/workflow/StateMachineImpl.java +++ /dev/null @@ -1,388 +0,0 @@ -/* - * Copyright 2012 by A-SIT, Secure Information Technology Center Austria - * - * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by - * the European Commission - subsequent versions of the EUPL (the "Licence"); - * You may not use this work except in compliance with the Licence. - * You may obtain a copy of the Licence at: - * http://joinup.ec.europa.eu/software/page/eupl - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the Licence is distributed on an "AS IS" basis, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the Licence for the specific language governing permissions and - * limitations under the Licence. - */ -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 class StateMachineImpl implements StateMachine, GUIProvider { - - /** - * SLF4J Logger instance - **/ - private static final Logger log = LoggerFactory - .getLogger(StateMachineImpl.class); - - private StatusImpl status; - - private PDFSignerImpl pdfSigner; - - private ConfigProviderImpl configProvider; - - /** - * Default constructor - * - * @param cmdLineArgs - */ - public StateMachineImpl(String[] cmdLineArgs) { - this.status = new StatusImpl(); - this.status.setCurrentState(new PrepareConfigurationState(this)); - this.pdfSigner = new PDFSignerImpl(); - this.configProvider = new ConfigProviderImpl(); - setCmdLineArgs(cmdLineArgs); - } - - /** - * 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 - */ - @Override - public void jumpToState(State state) { - this.status.setCurrentState(state); - this.invokeUpdate(); - } - - /** - * Update workflow logic and let state machine do its job... - */ - @Override - 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); - } - } - } - - /** - * Invoke Update in UI (Main) Thread - */ - @Override - public void invokeUpdate() { - if (this.display != null) { - this.display.asyncExec(() -> { - StateMachineImpl.this.update(); - }); - } - } - - 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) - */ - @Override - 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; - } - } - - /** - * Gets the Shell for drawing the ui - * - * @return Composite - */ - 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; - } - - @Override - public T createComposite(Class compositeClass, int style, State state) { - T composite = null; - try { - Constructor 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; - } - - /** - * Only returns a shell if one was already created ... - * - * @return - */ - private Shell nonCreatingGetShell() { - return this.shell; - } - - private boolean exit = false; - - /** - * Exists the Workflow - */ - @Override - public void exit() { - this.exit = true; - if (this.shell != null) { - this.shell.dispose(); - } - } - - /** - * Only returns a shell if one was already created ... - * - * @return - */ - private Display nonCreatingGetDisplay() { - return this.display; - } - - /** - * Workflow main entrance point - */ - 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(); - } - } - - /* - * (non-Javadoc) - * @see at.asit.pdfover.gui.workflow.StateMachine#getConfigProvider() - */ - @Override - public ConfigProvider getConfigProvider() { - return this.configProvider; - } - - /* - * (non-Javadoc) - * @see at.asit.pdfover.gui.workflow.StateMachine#getConfigProvider() - */ - @Override - public PersistentConfigProvider getPersistentConfigProvider() { - return this.configProvider; - } - - /* (non-Javadoc) - * @see at.asit.pdfover.gui.workflow.StateMachine#getConfigManipulator() - */ - @Override - public ConfigManipulator getConfigManipulator() { - return this.configProvider; - } - - /* (non-Javadoc) - * @see at.asit.pdfover.gui.workflow.StateMachine#getConfigOverlayManipulator() - */ - @Override - public ConfigOverlayManipulator getConfigOverlayManipulator() { - return this.configProvider; - } - - /* - * (non-Javadoc) - * @see at.asit.pdfover.gui.workflow.StateMachine#getStatus() - */ - @Override - public Status getStatus() { - return this.status; - } - - /* - * (non-Javadoc) - * @see at.asit.pdfover.gui.workflow.StateMachine#getPDFSigner() - */ - @Override - public PDFSigner getPDFSigner() { - return this.pdfSigner; - } - - /* - * (non-Javadoc) - * @see at.asit.pdfover.gui.workflow.StateMachine#getGUIProvider() - */ - @Override - public GUIProvider getGUIProvider() { - return this; - } - - // Data Section - // ============================================================================= - - // Command Line Arguments - // ------------------------------------------------------- - private String[] cmdLineArgs = new String[] {}; - - /** - * sets the command line arguments - * - * @param cmdLineArgs - */ - private void setCmdLineArgs(String[] cmdLineArgs) { - this.cmdLineArgs = cmdLineArgs; - } - - /** - * Gets the command line arguments - * - * @return the command line arguments - */ - @Override - public String[] getCmdArgs() { - return this.cmdLineArgs; - } - - /* (non-Javadoc) - * @see at.asit.pdfover.gui.workflow.GUIProvider#getMainShell() - */ - @Override - public synchronized Shell getMainShell() { - if(this.shell == null) { - this.createMainWindow(); - } - - return this.shell; - } - - /* (non-Javadoc) - * @see at.asit.pdfover.gui.workflow.GUIProvider#reloadResources() - */ - @Override - public void reloadResources() { - this.mainWindow.reloadLocalization(); - } -} -- cgit v1.2.3