Author: tchemit Date: 2010-05-30 11:21:32 +0200 (Sun, 30 May 2010) New Revision: 1940 Url: http://nuiton.org/repositories/revision/jaxx/1940 Log: introduce model for each operation (WizardOperationActionModel) Added: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardOperationActionModel.java Modified: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardOperationAction.java trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardOperationActionThread.java trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardOperationModel.java Modified: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardOperationAction.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardOperationAction.java 2010-05-30 09:20:57 UTC (rev 1939) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardOperationAction.java 2010-05-30 09:21:32 UTC (rev 1940) @@ -28,7 +28,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import javax.swing.*; +import javax.swing.SwingWorker; /** * La classe de base a implanter pour definir l'action d'une operation dans un @@ -39,46 +39,63 @@ * @param <M> le type de modèle * @since 1.3 */ -public abstract class WizardOperationAction<E extends WizardOperationStep, M extends WizardOperationModel<E>> extends SwingWorker<WizardOperationState, String> { +public abstract class WizardOperationAction<E extends WizardOperationStep, M extends WizardOperationModel<E>, O extends WizardOperationActionModel<E>> extends SwingWorker<WizardOperationState, String> { - /** to use log facility, just put in your code: log.info(\"...\"); */ - private static final Log log = - LogFactory.getLog(WizardOperationAction.class); + /** Logger */ + private static final Log log = LogFactory.getLog(WizardOperationAction.class); - E operation; + protected O operationModel; - WizardOperationState operationState; + public WizardOperationAction(O operationModel) { + this.operationModel = operationModel; + } - Exception error; + public E getOperation() { + return operationModel.getOperation(); + } - public WizardOperationAction(E operation) { - if (!operation.isOperation()) { - throw new IllegalArgumentException( - "the step " + operation + " has no operation defined"); - } - this.operation = operation; + public O getOperationModel() { + return operationModel; } - public E getOperation() { - return operation; + public WizardOperationState getOperationState() { + return operationModel.getOperationState(); } public Exception getError() { - return error; + return operationModel.getError(); } + /** + * @param e the error to set + * @deprecated since 2.1 prefer use the {@link WizardOperationActionModel#setError(Exception)} + */ + @Deprecated public void setError(Exception e) { - error = e; + operationModel.setError(e); } public void sendMessage(String msg) { firePropertyChange("message", null, msg); } + /** + * Recopie les états d'une action vers une nouvelle action. + * <p/> + * Cette méthode est appellé quand une action se déroule en plusieurs + * étapes. Du fait que les {@link SwingWorker} ne sont utilisable qu'une + * seule fois, on recopie les états de l'action courante vers la nouvelle + * action à exécuter. + * + * @param newAction la nouvelle action + */ + public void copyTo(WizardOperationAction<?, ?, ?> newAction) { + ((WizardOperationAction<?, ?, O>)newAction).operationModel = operationModel; + } + public abstract void start(JAXXContext context); - public abstract void beforeAction(JAXXContext context, - M model) throws Exception; + public abstract void beforeAction(JAXXContext context, M model) throws Exception; public abstract WizardOperationState doAction(M model) throws Exception; @@ -88,15 +105,11 @@ protected abstract M getModel(); - public WizardOperationState getOperationState() { - return operationState; - } - protected abstract JAXXContext getContext(); @Override public String toString() { - return super.toString() + " < operation: " + operation + ", state: " + + return super.toString() + " < operation: " + getOperation() + ", state: " + getState() + " >"; } @@ -109,7 +122,7 @@ beforeAction(getContext(), model); result = doAction(model); } catch (Exception e) { - error = e; + operationModel.setError(e); result = onError(model, e); } return result; @@ -122,18 +135,35 @@ try { if (isCancelled()) { - result = onCancel(getModel(), error); + result = onCancel(getModel(), operationModel.getError()); } else { result = get(); } } catch (Exception e) { result = WizardOperationState.FAILED; - error = e; + operationModel.setError(e); // ne devrait jamais arrivé ? log.error(e.getMessage(), e); } finally { // on enregistre le resultat de l'opération - operationState = result; + operationModel.setOperationState(result); + getModel().setBusy(false); } } + + public void destroy() { + if (operationModel != null) { + operationModel.destroy(); + operationModel = null; + } + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + if (log.isDebugEnabled()) { + log.debug("Will destroy " + this); + } + destroy(); + } } Added: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardOperationActionModel.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardOperationActionModel.java (rev 0) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardOperationActionModel.java 2010-05-30 09:21:32 UTC (rev 1940) @@ -0,0 +1,98 @@ +package jaxx.runtime.swing.wizard; + +import jaxx.runtime.JAXXUtil; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +/** + * Abstract model of {@link WizardOperationAction}. + * + * @author tchemit <chemit@codelutin.com> + * @see WizardOperationAction + * @since 2.1 + */ +public abstract class WizardOperationActionModel<E extends WizardOperationStep> { + + /** Logger */ + private static final Log log = + LogFactory.getLog(WizardOperationActionModel.class); + + /** pour propager les changements dans le modèle vers l'ui */ + private final PropertyChangeSupport pcs; + + protected final E operation; + + protected WizardOperationState operationState; + + protected Exception error; + + protected WizardOperationActionModel(E operation) { + this.operation = operation; + pcs = new PropertyChangeSupport(this); + } + + public final E getOperation() { + return operation; + } + + public final WizardOperationState getOperationState() { + return operationState; + } + + public final Exception getError() { + return error; + } + + public void setError(Exception error) { + this.error = error; + } + + public void setOperationState(WizardOperationState operationState) { + this.operationState = operationState; + } + + public final void addPropertyChangeListener(PropertyChangeListener listener) { + pcs.addPropertyChangeListener(listener); + } + + public final void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + pcs.addPropertyChangeListener(propertyName, listener); + } + + + public final void removePropertyChangeListener(PropertyChangeListener listener) { + pcs.removePropertyChangeListener(listener); + } + + public final void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + pcs.removePropertyChangeListener(propertyName, listener); + } + + public void destroy() { + if (log.isDebugEnabled()) { + log.debug("will destroy " + this); + } + + // remove all listeners + JAXXUtil.destroy(pcs); + } + + @Override + protected void finalize() throws Throwable { + super.finalize(); + destroy(); + } + + protected final void firePropertyChange(String propertyName, + Object oldValue, + Object newValue) { + pcs.firePropertyChange(propertyName, oldValue, newValue); + } + + protected final void firePropertyChange(String propertyName, Object newValue) { + pcs.firePropertyChange(propertyName, null, newValue); + } +} Property changes on: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardOperationActionModel.java ___________________________________________________________________ Added: svn:keywords + Author Date Id Revision HeadURL Modified: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardOperationActionThread.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardOperationActionThread.java 2010-05-30 09:20:57 UTC (rev 1939) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardOperationActionThread.java 2010-05-30 09:21:32 UTC (rev 1940) @@ -48,7 +48,7 @@ * @param <A> le type d'action d'operation * @since 1.3 */ -public abstract class WizardOperationActionThread<E extends WizardOperationStep, M extends WizardOperationModel<E>, A extends WizardOperationAction<E, M>> extends Thread implements PropertyChangeListener { +public abstract class WizardOperationActionThread<E extends WizardOperationStep, M extends WizardOperationModel<E>, A extends WizardOperationAction<E, M,?>> extends Thread implements PropertyChangeListener { /** to use log facility, just put in your code: log.info(\"...\"); */ private static final Log log = LogFactory.getLog(WizardOperationActionThread.class); @@ -89,7 +89,7 @@ @SuppressWarnings("unchecked") public A launchOperation(E operation) { - if (currentAction != null && (!currentAction.isDone() || currentAction.operationState == WizardOperationState.RUNNING)) { + if (currentAction != null && (!currentAction.isDone() || currentAction.getOperationModel().getOperationState() == WizardOperationState.RUNNING)) { // on ne peut traiter qu'une seule opération à la fois throw new IllegalStateException("can not add a operation when thread is busy, or has another operation to be done"); } Modified: trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardOperationModel.java =================================================================== --- trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardOperationModel.java 2010-05-30 09:20:57 UTC (rev 1939) +++ trunk/jaxx-runtime/src/main/java/jaxx/runtime/swing/wizard/WizardOperationModel.java 2010-05-30 09:21:32 UTC (rev 1940) @@ -24,8 +24,16 @@ */ package jaxx.runtime.swing.wizard; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + import javax.swing.SwingWorker.StateValue; -import java.util.*; +import java.util.Arrays; +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * Un modèle de wizard avec des opérations. @@ -36,6 +44,12 @@ */ public class WizardOperationModel<E extends WizardOperationStep> extends WizardModel<E> { + + /** Logger */ + private static final Log log = LogFactory.getLog(WizardOperationModel.class); + + public static final String BUSY_PROPERTY_NAME = "busy"; + public static final String OPERATIONS_PROPERTY_NAME = "operations"; public static final String OPERATION_STATE_PROPERTY_NAME = "operationState"; @@ -47,10 +61,13 @@ /** La liste des opérations à effectuer */ protected Set<E> operations; + /** le dictionnaire des modèles d'opération */ + protected final Map<E, WizardOperationActionModel<E>> models; + /** Pour conserver les états des opérations */ protected Map<E, WizardOperationState> operationStates; - protected Map<E, WizardOperationAction<E, ? extends WizardOperationModel<E>>> operationActions; + protected Map<E, WizardOperationAction<?, ? extends WizardOperationModel<E>, ? extends WizardOperationActionModel<E>>> operationActions; /** L'état générale du modèle */ protected WizardOperationState modelState; @@ -58,6 +75,9 @@ /** un drapeau pour savoir siune opération a été lancée */ protected boolean wasStarted; + /** un drapeau pour savoir si le modèle est occupé. */ + protected boolean busy; + @SuppressWarnings("unchecked") public <T extends Enum<T>> WizardOperationModel(Class<E> stepClass, E... steps) { super(stepClass, steps); @@ -65,6 +85,17 @@ operationStates = new EnumMap(k); operations = (Set<E>) EnumSet.noneOf(k); operationActions = new EnumMap(k); + models = (Map<E, WizardOperationActionModel<E>>) new EnumMap(k); + for (T o : EnumSet.allOf(k)) { + E step = (E) o; + if (step.isOperation()) { + + // initialisation du modèle associé à l'opération + WizardOperationActionModel<E> model = (WizardOperationActionModel<E>) step.newModel(); + log.info("[" + step + "] Add an operation model " + model); + models.put(step, model); + } + } } public Set<E> getOperations() { @@ -79,6 +110,16 @@ return wasStarted; } + public boolean isBusy() { + return busy; + } + + public void setBusy(boolean busy) { + boolean oldValue = this.busy; + this.busy = busy; + firePropertyChange(BUSY_PROPERTY_NAME, oldValue, busy); + } + public boolean containsOperation(E step) { return getOperations().contains(step); } @@ -97,12 +138,16 @@ return operationStates.get(operation); } - public WizardOperationAction<E, ? extends WizardOperationModel<E>> getOperationAction(E operation) { - WizardOperationAction<E, ? extends WizardOperationModel<E>> action = operationActions.get(operation); + public WizardOperationAction<?, ?, ?> getOperationAction(E operation) { + if (operation==null || !operation.isOperation()) { + return null; + } + WizardOperationAction<?, ?, ?> action = operationActions.get(operation); if (action == null) { try { - action = (WizardOperationAction<E, ? extends WizardOperationModel<E>>) operation.getActionClass().newInstance(); - operationActions.put(operation, action); + WizardOperationActionModel<?> operationModel = getOperationModel(operation); + action = operation.newAction(operationModel); + operationActions.put(operation, (WizardOperationAction<E, ? extends WizardOperationModel<E>, ? extends WizardOperationActionModel<E>>) action); } catch (Exception ex) { throw new RuntimeException(ex); } @@ -118,12 +163,14 @@ public void setOperationState(E operation, WizardOperationState operationState) { WizardOperationState oldValue = getOperationState(operation); operationStates.put(operation, operationState); + getOperationModel(operation).setOperationState(operationState); fireIndexedPropertyChange(OPERATION_STATE_PROPERTY_NAME, getSteps().indexOf(operation), oldValue, operationState); updateModelState(operation, operationState); validate(); } public boolean[] getAccessibleSteps() { + log.info("compute with steps "+getSteps()); boolean[] result = new boolean[getSteps().size()]; int index = getSteps().indexOf(getStep()); if (index != -1) { @@ -143,15 +190,16 @@ (!previousStep.isOperation() || getOperationState(previousStep) == WizardOperationState.SUCCESSED); } } - //System.out.println("accessibles steps -------- " + java.util.Arrays.toString(result)); + log.info("accessibles steps -------- " + Arrays.toString(result)); return result; } @Override public void start() { super.start(); + + // update universe of steps and actions updateUniverse(); - //setSteps(steps.toArray((E[]) Array.newInstance(stepClass, steps.size()))); // le modèle n'est pas démarré setModelState(WizardOperationState.PENDING); @@ -167,7 +215,7 @@ } setModelState(WizardOperationState.CANCELED); if (getStep() != null && getStep().isOperation()) { - WizardOperationAction<E, ? extends WizardOperationModel<E>> action = getOperationAction(getStep()); + WizardOperationAction<?, ?, ?> action = getOperationAction(getStep()); if (action != null) { if (!action.isCancelled() && !action.isDone() && action.getState() == StateValue.STARTED) { // on annule l'action @@ -203,6 +251,16 @@ updateOperationStates(Arrays.asList(steps)); } + public WizardOperationActionModel<E> getOperationModel(E operation) { + if (operation==null) { + return null; + } + if (!operation.isOperation()) { + throw new IllegalStateException("step [" + operation + "] is not an operation."); + } + return models.get(operation); + } + public void updateOperationStates(List<E> steps) { int index = 0; for (E e : steps) { @@ -211,9 +269,9 @@ firePropertyChange(MODEL_STATE_PROPERTY_NAME, null, modelState); } - public WizardOperationAction<E, ? extends WizardOperationModel<E>> reloadOperation(E operation) { + public WizardOperationAction<?, ?, ?> reloadOperation(E operation) { operationActions.remove(operation); - WizardOperationAction<E, ? extends WizardOperationModel<E>> newOp = getOperationAction(operation); + WizardOperationAction<?, ?, ?> newOp = getOperationAction(operation); return newOp; } @@ -277,6 +335,35 @@ setSteps(newSteps); } + @Override + public void destroy() { + super.destroy(); + Set<E> operations = getOperations(); + for (E op : operations) { + WizardOperationAction<?, ?, ?> action = getOperationAction(op); + if (log.isDebugEnabled()) { + log.debug("destroy action " + action); + } + action.destroy(); + } + } + + @Override + protected E[] updateStepUniverse() { + // on met a jour les opérations + for (E op : operations) { + if (!operationStates.containsKey(op)) { + operationStates.put(op, WizardOperationState.PENDING); + } + } + for (E op : operationStates.keySet()) { + if (!operations.contains(op)) { + operationStates.remove(op); + } + } + return null; + } + protected int getOperationIndex(E operation) { int index = 0; for (E o : operations) {
participants (1)
-
tchemit@users.nuiton.org