/*
* 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 org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Properties;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import at.asit.pdfover.gui.components.BKUSelectionComposite;
import at.asit.pdfover.gui.components.MainWindow;
import at.asit.pdfover.gui.workflow.states.BKUSelectionState;
import at.asit.pdfover.gui.workflow.states.DataSourceSelectionState;
import at.asit.pdfover.gui.workflow.states.PositioningState;
import at.asit.pdfover.gui.workflow.states.PrepareConfigurationState;
import at.asit.pdfover.gui.workflow.states.BKUSelectionState.BKUs;
import at.asit.pdfover.signator.Signator;
import at.asit.pdfover.signator.SignatureParameter;
import at.asit.pdfover.signator.Signer;
/**
* Workflow holds logical state of signing process and updates the current
* logical state
*/
public class StateMachineImpl implements StateMachine {
/**
* SFL4J Logger instance
**/
private static final Logger log = LoggerFactory.getLogger(StateMachineImpl.class);
/**
* Default constructor
*
* @param cmdLineArgs
*/
public StateMachineImpl(String[] cmdLineArgs) {
setCmdLineAargs(cmdLineArgs);
}
/**
* @uml.property name="state"
* @uml.associationEnd multiplicity="(1 1)" aggregation="shared"
* inverse="workflow1:at.asit.pdfover.gui.workflow.WorkflowState"
*/
private State state = new PrepareConfigurationState();
/**
* Getter of the property state
*
* @return Returns the state.
* @uml.property name="state"
*/
public State getState() {
return this.state;
}
/**
* 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 void setState(State state) {
if (this.state != state && state != null) {
this.state = state;
if (state instanceof PositioningState) {
// User jumps to positioning state !
// restore possible default for bku selection / forget BKU
// selection
this.setSelectedBKU(PrepareConfigurationState
.readSelectedBKU(this.getConfigurationValues()));
// forget position
this.getParameter().setSignaturePosition(null);
} else if (state instanceof BKUSelectionState) {
// User jumps to bku selection state !
// forget bku selection
this.setSelectedBKU(BKUs.NONE);
} else if (state instanceof DataSourceSelectionState) {
// User jumps to data source selection state !
// forget bku selection / restore possible default for bku
// selection
this.setSelectedBKU(PrepareConfigurationState
.readSelectedBKU(this.getConfigurationValues()));
// forget position / restore possible default for position
this.getParameter().setSignaturePosition(
PrepareConfigurationState.readDefinedPosition(this
.getConfigurationValues()));
// forget data source selection
this.setDataSource(null);
}
this.update();
}
}
/**
* Update Workflow logic and let state machine do its job...
*/
@Override
public void update() {
State next = null;
while (this.state != null) {
this.state.run();
if (this.mainWindow != null && !this.mainWindow.getShell().isDisposed()) {
log.debug("Allowing MainWindow to update its state for " + this.state.toString());
this.mainWindow.UpdateNewState();
this.mainWindow.doLayout();
}
next = this.state.nextState();
if (next == this.state) {
break;
}
// this.state.hideGUI();
log.debug("Changing state from: " + this.state.toString() + " to "
+ next.toString());
this.state = next;
}
if (this.state != null) {
this.setCurrentStateMessage(this.state.toString());
} else {
this.setCurrentStateMessage("");
}
}
/**
* Invoke Update in UI (Main) Thread
*/
public void InvokeUpdate() {
if(this.display != null) {
this.display.asyncExec(new Runnable() {
@Override
public void run() {
StateMachineImpl.this.update();
}
});
}
}
private Display display = null;
private Shell shell = null;
private Composite container = null;
private MainWindow mainWindow = null;
/**
* Helper method for developing
*
* @param value
*/
public void setCurrentStateMessage(String value) {
if (this.mainWindow != null) {
this.mainWindow.setStatus(value);
}
}
/**
* Used by active workflow state to show its own gui component
*
* @param ctrl
*/
public void setTopControl(final Control ctrl) {
this.mainWindow.setTopControl(ctrl);
}
private void createMainWindow() {
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();
}
/**
* Gets the Shell for drawing the ui
*
* @return Composite
*/
@Override
public Composite getComposite() {
// Main window will be build on first call
// returns SWT Composite container for states to draw their GUI
if (this.container == null) {
this.createMainWindow();
}
if (this.container == null) {
// TODO throw Exception...
}
return this.container;
}
@Override
public T createComposite(Class compositeClass) {
T composite = null;
try {
Constructor constructor = compositeClass.getDeclaredConstructor(Composite.class, int.class, BKUSelectionState.class);
composite = constructor.newInstance(getComposite(), SWT.RESIZE, this);
} 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;
}
/**
* Exists the Workflow
*/
@Override
public void exit() {
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 ...
this.update();
// if a user interaction is required we have a shell ...
Shell shell = this.nonCreatingGetShell();
Display display = this.nonCreatingGetDisplay();
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() {
// TODO Auto-generated method stub
return null;
}
/* (non-Javadoc)
* @see at.asit.pdfover.gui.workflow.StateMachine#getStatus()
*/
@Override
public Status getStatus() {
// TODO Auto-generated method stub
return null;
}
// Data Section
// =============================================================================
// Command Line Arguments
// -------------------------------------------------------
private String[] cmdLineArgs = new String[] {};
/**
* sets the command line arguments
*
* @param cmdLineArgs
*/
private void setCmdLineAargs(String[] cmdLineArgs) {
this.cmdLineArgs = cmdLineArgs;
}
/**
* Gets the command line arguments
*
* @return the command line arguments
*/
public String[] getCmdArgs() {
return this.cmdLineArgs;
}
// Key Value String properties
// -------------------------------------------------------
private Properties configurationValues = new Properties();
/**
* Gets the persistent state
*
* @return the persistent state
*/
public Properties getConfigurationValues() {
return this.configurationValues;
}
// Data source
// -------------------------------------------------------
private File dataSource = null;
/**
* Gets the DataSource
*
* @return The data source file
*/
public File getDataSource() {
return this.dataSource;
}
/**
* Sets the DataSource
*
* @param file
*/
public void setDataSource(File file) {
this.dataSource = file;
}
// Selected BKU
// -------------------------------------------------------
/**
* The selected BKU
*/
private BKUs selectedBKU = BKUs.NONE;
/**
* Gets the selected BKU
*
* @return the selectedBKU
*/
public BKUs getSelectedBKU() {
return this.selectedBKU;
}
/**
* Sets the selected BKU
*
* @param selectedBKU
* the selectedBKU to set
*/
public void setSelectedBKU(BKUs selectedBKU) {
this.selectedBKU = selectedBKU;
}
private Signator.Signers usedSignerLib = Signator.Signers.PDFAS;
/**
* The PDF Signer
*/
private Signer pdfSigner = null;
/**
* @return the pdfSigner
*/
public Signer getPdfSigner() {
return this.pdfSigner;
}
/**
* @param pdfSigner
* the pdfSigner to set
*/
public void setPdfSigner(Signer pdfSigner) {
this.pdfSigner = pdfSigner;
}
private SignatureParameter parameter = null;
/**
* @return the parameter
*/
public SignatureParameter getParameter() {
return this.parameter;
}
/**
* @param parameter
* the parameter to set
*/
public void setParameter(SignatureParameter parameter) {
this.parameter = parameter;
}
/**
* @return the usedSignerLib
*/
public Signator.Signers getUsedSignerLib() {
return this.usedSignerLib;
}
/**
* @param usedSignerLib
* the usedSignerLib to set
*/
public void setUsedSignerLib(Signator.Signers usedSignerLib) {
this.usedSignerLib = usedSignerLib;
}
}