r1266 - in jaxx/trunk: jaxx-compiler-api/src/main/java/jaxx/compiler jaxx-runtime-swing/src/main/java/jaxx/runtime jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard
Author: tchemit Date: 2009-03-14 19:24:14 +0000 (Sat, 14 Mar 2009) New Revision: 1266 Added: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationAction.java jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationActionThread.java jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationModel.java jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationState.java jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationStep.java Removed: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationAction.java jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationActionThread.java jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModelWithOperations.java Modified: jaxx/trunk/jaxx-compiler-api/src/main/java/jaxx/compiler/CompiledObject.java jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/SwingUtil.java jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModel.java jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperation.java jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUI.java jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java Log: wizard framework done Modified: jaxx/trunk/jaxx-compiler-api/src/main/java/jaxx/compiler/CompiledObject.java =================================================================== --- jaxx/trunk/jaxx-compiler-api/src/main/java/jaxx/compiler/CompiledObject.java 2009-03-13 22:00:34 UTC (rev 1265) +++ jaxx/trunk/jaxx-compiler-api/src/main/java/jaxx/compiler/CompiledObject.java 2009-03-14 19:24:14 UTC (rev 1266) @@ -20,75 +20,61 @@ import java.util.List; import java.util.Map; - /** * Represents an object in the <code>.java</code> file being generated during compilation. There is * a <code>CompiledObject</code> for each class tag encountered, and certain tags may generate * additional objects for various reasons. */ public class CompiledObject { + /** The object's id. */ private String id; - /** Java code referring to the object. */ private String javaCode; - /** The object's class. */ private ClassDescriptor objectClass; - /** The style class. */ private String styleClass; - /** The container containing this CompiledObject. */ private CompiledObject parent; - /** true if this object overrides an object of the same id in a superclass of the object being compiled */ private boolean override; - /** * Comma-separated Java code snippets representing the parameters that should be passed to the object's * constructor. */ private String constructorParams; - /** * Java code snippet which performs basic initialization of the object (after it has already been constructed). * Because CompiledObject initialization order cannot be guaranteed, it is not safe to refer to other * CompiledObjects from initializationCode -- you must refer to them from additionCode instead. */ private StringBuffer initializationCode = new StringBuffer(); - /** * Java code snippet which completes setup by adding any child objects, or otherwise manipulates any refererenced * objects. Because CompiledObject initialization order cannot be guaranteed, it is not safe to refer to other * CompiledObjects from initializationCode -- you must refer to them from additionCode instead. */ private StringBuffer additionCode = new StringBuffer(); - /** List of all registered event handlers. */ private List<EventHandler> eventHandlers = new ArrayList<EventHandler>(); - /** All properties that have been applied to this CompiledObject. */ private Map<String, String> properties = new HashMap<String, String>(); - /** generic types of the compiled object */ private String[] genericTypes; - /** a flag to indicate if javaBean full support must be support for this object by root object */ private boolean javaBean; - /** code to initialize the bean (can be null) */ private String javaBeanInitCode; - /** the type of the override object (can be null if no oveeride) */ private ClassDescriptor overrideType; - /** * the decorator (if null will use {@link DefaultCompiledObjectDecorator}). */ private CompiledObjectDecorator decorator; - + public class ChildRef { + CompiledObject child; String constraints; String childJavaCode; @@ -142,7 +128,6 @@ buffer.append(JAXXCompiler.getLineSeparator()); } } - private List<ChildRef> childs; /** @@ -158,7 +143,6 @@ this(id, objectClass, compiler, false); } - /** * Creates a new <code>CompiledObject</code>. To be useful, the object should be registered with a * <code>JAXXCompiler</code> using {@link JAXXCompiler#registerCompiledObject registerCompiledObject}. @@ -173,7 +157,6 @@ this(id, id, objectClass, compiler, force); } - /** * Creates a new <code>CompiledObject</code>. To be useful, the object should be registered with a * <code>JAXXCompiler</code> using {@link JAXXCompiler#registerCompiledObject registerCompiledObject}. @@ -202,7 +185,6 @@ this.childs = new ArrayList<ChildRef>(); } - public static boolean isValidID(String id) { boolean valid = true; if (id.length() == 0) { @@ -224,7 +206,6 @@ return valid; } - /** * True if this object overrides an object in the superclass of the class being compiled. For this to be true, the * class currently being compiled must be a subclass of another <code>JAXXObject</code> which has an @@ -237,7 +218,6 @@ return override; } - /** * Sets whether this class overrides an identically-named object in the parent class. * @@ -248,7 +228,6 @@ this.override = override; } - /** * Returns this object's CSS style class. * @@ -258,7 +237,6 @@ return styleClass; } - /** * Sets this object's CSS style class. * @@ -268,7 +246,6 @@ this.styleClass = styleClass; } - /** * Returns this object's parent container. Non-visual components (and the root container) return <code>null</code>. * @@ -278,7 +255,6 @@ return parent; } - /** * Sets this object's parent container. * @@ -291,7 +267,6 @@ this.parent = parent; } - /** * Returns the name of the method that should be generated in the compiled <code>.java</code> file * in order to create this object. This is just a suggestion and may be ignored. @@ -302,7 +277,6 @@ return "create" + org.apache.commons.lang.StringUtils.capitalize(getId()); } - /** * Returns the name of the method that should be generated in the compiled <code>.java</code> file * in order to add children to this object. This is just a suggestion and may be ignored. @@ -313,7 +287,6 @@ return "addChildrenTo" + org.apache.commons.lang.StringUtils.capitalize(getId()); } - /** * Returns the type of this object. * @@ -323,7 +296,6 @@ return objectClass; } - /** * Returns this object's id. Generally, a field with this name will be created in the compiled <code>.java</code> * file in order to represent this object. @@ -334,7 +306,6 @@ return id; } - /** * Returns Java code used to refer to this object in the compiled Java file. This is usually the same as its * id. @@ -382,7 +353,6 @@ return constructorParams; } - /** * Sets the parameters to pass to this object's constructor. * @@ -393,7 +363,6 @@ this.constructorParams = constructorParams; } - /** * Returns the code that performs basic initialization of this object, after it has already been constructed. * This basic code should not reference any other <code>CompiledObjects</code> as they may not have @@ -411,7 +380,6 @@ return result.toString(); } - protected String getInitializationCode(EventHandler handler, JAXXCompiler compiler) { MethodDescriptor addMethod = handler.getAddMethod(); ClassDescriptor listenerClass = addMethod.getParameterTypes()[0]; @@ -421,7 +389,6 @@ TypeManager.getJavaCode(compiler.getEventHandlerMethodName(handler)) + "));" + JAXXCompiler.getLineSeparator(); } - /** * Returns Java code to complete final setup on this object. This code may reference other * <code>CompiledObjects</code>, as they are guaranteed to have all been created by this point. @@ -432,7 +399,6 @@ return additionCode.toString(); } - /** * Appends code to the initialization code block. A line separator is automatically appended to the end. * @@ -444,7 +410,6 @@ this.initializationCode.append(JAXXCompiler.getLineSeparator()); } - /** * Appends code to the addition code block. A line separator is automatically appended to the end. * @@ -456,7 +421,6 @@ this.additionCode.append(JAXXCompiler.getLineSeparator()); } - /** * Stores a property for this object. The only effect of calling this method is that the property will * be returned by <code>getProperties()</code>. @@ -469,7 +433,6 @@ properties.put(property, value); } - /** * Returns all properties which have been set for this object. * @@ -480,7 +443,6 @@ return properties; } - // TODO: remove this temporary method and complete switchover to MethodDescriptors public void addEventHandler(String eventId, Method addMethod, Method listenerMethod, String code, JAXXCompiler compiler) { try { @@ -490,13 +452,11 @@ MethodDescriptor addMethodDescriptor = descriptor.getMethodDescriptor(addMethod.getName(), listenerDescriptor); MethodDescriptor listenerMethodDescriptor = listenerDescriptor.getMethodDescriptor(listenerMethod.getName(), ClassDescriptorLoader.getClassDescriptor(listenerMethod.getParameterTypes()[0].getName())); addEventHandler(eventId, addMethodDescriptor, listenerMethodDescriptor, code, compiler); - } - catch (Exception e) { + } catch (Exception e) { throw new RuntimeException(e); } } - /** * Adds an event listener to this object. The generated code will appear in the initialization block. * @@ -517,7 +477,6 @@ } } - /** * Adds a child component to this container. The child is added without layout constraints. * @@ -530,7 +489,6 @@ addChild(child, null, compiler); } - /** * Adds a child component to this container. This variant allows the Java code for a layout constraints * object to be specified. @@ -546,8 +504,7 @@ if (constraints != null) { constraints = compiler.checkJavaCode(constraints); } - } - catch (CompilerException e) { + } catch (CompilerException e) { compiler.reportError("While parsing 'constraints' attribute: " + e.getMessage()); } @@ -561,7 +518,7 @@ String delegateCode = containerDelegate != null ? "." + containerDelegate + "()" : ""; child.setParent(this); - + childs.add(new ChildRef(child, constraints, child.getJavaCode(), delegateCode)); } } @@ -571,7 +528,6 @@ return getObjectClass().getName() + "[id='" + id + "']"; } - public void registerDataBinding(String src, String property, String assignment, JAXXCompiler compiler) throws CompilerException { compiler.registerDataBinding(src, getId() + "." + property, assignment); } @@ -584,7 +540,7 @@ for (int i = 0, j = getGenericTypesLength(); i < j; i++) { result += ", " + genericTypes[i]; } - return "< " + result.substring(1) + " >"; + return "< " + result.substring(2) + " >"; } public void setGenericTypes(String[] genericTypes) { Modified: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/SwingUtil.java =================================================================== --- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/SwingUtil.java 2009-03-13 22:00:34 UTC (rev 1265) +++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/SwingUtil.java 2009-03-14 19:24:14 UTC (rev 1266) @@ -409,7 +409,10 @@ public void reset() { setReverse(reverse); } - + + public int size() { + return tabs.getTabCount(); + } public TabbedPaneIterator<O> reverse() { setReverse(!reverse); return this; Deleted: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationAction.java =================================================================== --- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationAction.java 2009-03-13 22:00:34 UTC (rev 1265) +++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationAction.java 2009-03-14 19:24:14 UTC (rev 1266) @@ -1,94 +0,0 @@ -package jaxx.runtime.swing.wizard; - -import javax.swing.SwingWorker; -import jaxx.runtime.JAXXContext; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * - * @author tony - * @param <E> - * @param <O> - * @param <R> - * @param <M> - * @since 1.3 - */ -public abstract class WizardAbstractOperationAction<E extends Enum<E>,O extends Enum<O>, R extends Enum<R>, M extends WizardModelWithOperations<E,O,R>> extends SwingWorker<R, String> { - - /** to use log facility, just put in your code: log.info(\"...\"); */ - private static final Log log = LogFactory.getLog(WizardAbstractOperationAction.class); - O operation; - Exception error; - - public WizardAbstractOperationAction(O operation) { - super(); - this.operation = operation; - } - - public O getOperation() { - return operation; - } - - public abstract void start(JAXXContext context); - - public abstract void beforeAction(JAXXContext context, M model) throws Exception; - - public abstract R doAction(M model) throws Exception; - - public abstract R onError(M model, Exception e); - - public abstract R onCancel(M model, Exception e); - - public abstract void afterAction(M model, R result, Exception error); - - protected abstract M getModel(); - - protected abstract JAXXContext getContext(); - - @Override - public String toString() { - return super.toString() + " < operation: " + operation + ", state: " + getState() + " >"; - } - - @Override - protected R doInBackground() throws Exception { - R result; - M model = getModel(); - try { - log.info(this); - beforeAction(getContext(), model); - result = doAction(model); - } catch (Exception e) { - error = e; - result = onError(model, e); - } - return result; - } - - @Override - protected void done() { - R result = null; - log.info(this); - M model = getModel(); - try { - if (isCancelled()) { - - result = onCancel(model, error); - } else { - result = get(); - } - } catch (Exception e) { - // ne devrait jamais arrivé ? - log.error(e.getMessage(), e); - throw new RuntimeException(e); - } finally { - // on enregistre le resultat de l'opération - - model.setOperationResult(operation, result); - - // on notifie le resultat de l'action - firePropertyChange(WizardModelWithOperations.OPERATION_RESULT_PROPERTY_NAME, null, result); - } - } -} Deleted: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationActionThread.java =================================================================== --- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationActionThread.java 2009-03-13 22:00:34 UTC (rev 1265) +++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationActionThread.java 2009-03-14 19:24:14 UTC (rev 1266) @@ -1,265 +0,0 @@ -package jaxx.runtime.swing.wizard; - -import java.beans.PropertyChangeEvent; -import java.beans.PropertyChangeListener; -import java.beans.PropertyChangeSupport; -import java.util.Date; -import jaxx.runtime.JAXXContext; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * Thread qui réalise les opérations. - * - * Pour exécuter une nouvelle opération, on utilise la méthode - * {@link #launchOperation(SynchroActionWorker)}. - * - * Le thread possède 2 états internes : - * - * - busy lorsqu'il exécute une opération - * - * - canceled lorqu'une annulation a été demandée via la méthode {@link #setCanceled(boolean)} - * - * Note: Pour bloquer (ou débloquer) le thread, on utilise la méthode {@link #setwaiting(boolean)} - * @param <E> le type des etapes - * @param <O> le type des operations - * @param <R> le type des resultats d'operation - * @param <M> le type de modele - * @param <A> le type d'action d'operation - * - * @author tony - * @since 1.3 - */ -public abstract class WizardAbstractOperationActionThread<E extends Enum<E>, O extends Enum<O>, R extends Enum<R>, M extends WizardModelWithOperations<E, O, R>, A extends WizardAbstractOperationAction<E, O, R, M>> extends Thread implements PropertyChangeListener { - - /** to use log facility, just put in your code: log.info(\"...\"); */ - private static final Log log = LogFactory.getLog(WizardAbstractOperationActionThread.class); - public static final String BUSY_PROPERTY_NAME = "busy"; - public static final String CANCELED_PROPERTY_NAME = "canceled"; - /** - * l'état du thread pendant les étapes non interactives - */ - private boolean busy; - /** - * l'état du thread si annulé - */ - private boolean canceled; - /** suport of modification propagation */ - protected PropertyChangeSupport pcs; - /** le context applicatif */ - protected JAXXContext cotext; - protected Class<M> modelClass; - protected A currentAction; - /** - * un lock pour permettre la suspension et la reprise du thread - * lors du mode interactif. - */ - private final Object LOCK = new Object(); - - protected abstract M getModel(); - protected abstract JAXXContext getContext(); - - public WizardAbstractOperationActionThread(Class<M> modelClass) throws IllegalArgumentException { - super(WizardAbstractOperationActionThread.class.getSimpleName() + " " + new Date()); - this.modelClass = modelClass; - this.pcs = new PropertyChangeSupport(this); - } - - public boolean isBusy() { - return busy; - } - - public boolean isCanceled() { - return canceled; - } - - public void cancel() { - setCanceled(true); - //currentAction = null; - setBusy(false); - setWaiting(false); - } - - public void launchOperation(A action) { - - if (busy || currentAction != null) { - // 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"); - } - currentAction = action; - // on libere le thread pour qu'il execute l'opération - setWaiting(false); - } - - @Override - public void propertyChange(PropertyChangeEvent evt) { - if (WizardModelWithOperations.OPERATION_RESULT_PROPERTY_NAME.equals(evt.getPropertyName())) { - // on rend la main au thread pour qu'il attende une prochaine operation - setWaiting(false); - } - } - - @Override - public void run() { - try { - - // on vérifie que le context contient bien le modèle - if (getModel()==null) { - throw new NullPointerException("could not find model "+modelClass+" for "+this); - } - - while (!canceled) { - - if (canceled) { - // une annulation a été demandé - // donc même si une opération est demandée, on ne la traite - // pas - break; - } - - // en attente qu'une opération - // le block est bloqué jusqu'à arrivée d'une opération - // ou une demande d'annulation - setWaiting(true); - - // le thread a repris la main, donc plus en attente - log.trace("no more waiting " + this); - - if (!canceled) { - // une opération a été demandée - - // le thread passe en éta occupé - setBusy(true); - // le thread écoute les modifications de l'action - currentAction.addPropertyChangeListener(this); - // démarrage de l'opération - currentAction.start(getContext()); - // le thread est bloqué jusqu'à la fin de l'opération - // ou une demande d'annulation - setWaiting(true); - // la main a ete rendue, le thread n'est plus actif - setBusy(false); - } - - // le thread reprend la main des que l'operation - // est terminée ou a été annulée, on passera alors - // dans la méthode onPropertyChanged - if (currentAction != null) { - // le thread n'écoute plus l'action car elle est terminée - // ou annulée - currentAction.removePropertyChangeListener(this); - // suppression de l'action - currentAction = null; - } - - } - - } catch (Exception e) { - throw new RuntimeException(e); - } finally { - if (busy) { - setBusy(false); - setWaiting(false); - } - - log.info(this + " will close..."); - close(); - } - } - - /** - * La méthode pour nettoyer le thread, a la fermeture. - * - */ - protected void close() { - // par defaut, on ne fait rien - log.info(this); - } - - // PropertyChanged support - public void addPropertyChangeListener(PropertyChangeListener listener) { - pcs.addPropertyChangeListener(listener); - } - - public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { - pcs.addPropertyChangeListener(propertyName, listener); - } - - public void removePropertyChangeListener(PropertyChangeListener listener) { - pcs.removePropertyChangeListener(listener); - } - - public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { - pcs.removePropertyChangeListener(propertyName, listener); - } - - public synchronized boolean hasListeners(String propertyName) { - return pcs.hasListeners(propertyName); - } - - public synchronized PropertyChangeListener[] getPropertyChangeListeners(String propertyName) { - return pcs.getPropertyChangeListeners(propertyName); - } - - public synchronized PropertyChangeListener[] getPropertyChangeListeners() { - return pcs.getPropertyChangeListeners(); - } - - protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { - pcs.firePropertyChange(propertyName, oldValue, newValue); - } - - protected void setBusy(boolean busy) { - boolean oldValue = this.busy; - this.busy = busy; - firePropertyChange(BUSY_PROPERTY_NAME, oldValue, busy); - } - - protected void setCanceled(boolean canceled) { - boolean oldValue = this.canceled; - this.canceled = canceled; - if (currentAction != null) { - log.info("cancel action " + currentAction); - // on a une action en cours, on l'annule - currentAction.cancel(true); - } - // on annule aussi le model - getModel().cancel(); - //on notifie les écouteur que le thread est annulé - firePropertyChange(CANCELED_PROPERTY_NAME, oldValue, canceled); - } - - protected void setWaiting(boolean waiting) { - - if (waiting && !canceled) { - // locking thread - try { - lockThread(); - } catch (InterruptedException ex) { - log.error(ex.getMessage(), ex); - canceled = true; - } - } - - if (!waiting) { - // release lock - unlockThread(); - } - } - - protected void lockThread() throws InterruptedException { - synchronized (LOCK) { - log.trace(this); - // lock - LOCK.wait(); - } - } - - protected void unlockThread() { - synchronized (LOCK) { - log.trace(this); - // unlock - LOCK.notify(); - } - } -} Modified: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModel.java =================================================================== --- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModel.java 2009-03-13 22:00:34 UTC (rev 1265) +++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModel.java 2009-03-14 19:24:14 UTC (rev 1266) @@ -19,7 +19,6 @@ public static final String PREVIOUS_STEP_PROPERTY_NAME = "previousStep"; public static final String NEXT_STEP_PROPERTY_NAME = "nextStep"; public static final String VALID_STEP_PROPERTY_NAME = "validStep"; - /** * le type d'une etape du model (doit etre une enumeration) */ @@ -134,7 +133,7 @@ // la propriete nextStep peut avoir changee firePropertyChange(NEXT_STEP_PROPERTY_NAME, null, getNextStep()); } - + public boolean validate(E s) { return step != null; } @@ -160,6 +159,7 @@ pcs.removePropertyChangeListener(l); } } + protected Class<E> getStepClass() { return stepClass; } @@ -190,7 +190,10 @@ pcs.firePropertyChange(propertyName, oldValue, newValue); } + protected void fireIndexedPropertyChange(String propertyName, int index, Object oldValue, Object newValue) { + pcs.fireIndexedPropertyChange(propertyName, index, oldValue, newValue); + } + protected void updateUniverse() { - } } Deleted: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModelWithOperations.java =================================================================== --- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModelWithOperations.java 2009-03-13 22:00:34 UTC (rev 1265) +++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModelWithOperations.java 2009-03-14 19:24:14 UTC (rev 1266) @@ -1,96 +0,0 @@ -package jaxx.runtime.swing.wizard; - -import java.util.EnumMap; -import java.util.EnumSet; - -/** - * Un modèle de wizard. - * - * @param <E> le type de l'énumération contenant les etapes. - * - * @param <O> le type de l'énumeration des opérations - * @param <R> le type de l'énumération des résultats d'opération - * @author tony - * @since 1.3 - */ -public abstract class WizardModelWithOperations<E extends Enum<E>, O extends Enum<O>, R extends Enum<R>> extends WizardModel<E> { - - public static final String OPERATIONS_PROPERTY_NAME = "operations"; - public static final String OPERATION_RESULT_PROPERTY_NAME = "operationResult"; - /** - * La liste des opérations à effectuer - */ - protected EnumSet<O> operations; - /** - * Pour conserver les résultats des opérations - */ - protected EnumMap<O, R> operationResults; - protected Class<O> operationClass; - protected Class<R> operationResultClass; - - public abstract void cancel(); - - //protected abstract boolean isCancelResult(R operationResult); - //protected abstract boolean isErrorResult(R operationResult); - - public WizardModelWithOperations(Class<E> stepClass, Class<O> operationClass, Class<R> operationResultClass, E... steps) { - super(stepClass, steps); - this.operationClass = operationClass; - this.operationResultClass = operationResultClass; - operationResults = new EnumMap<O, R>(operationClass); - } - - public EnumSet<O> getOperations() { - if (operations == null) { - operations = EnumSet.noneOf(operationClass); - } - return operations; - } - - public R getOperationResult(O operation) { - return operationResults.get(operation); - } - - public void setOperationResult(O operation, R operationResult) { - R oldValue = getOperationResult(operation); - operationResults.put(operation, operationResult); - firePropertyChange(OPERATION_RESULT_PROPERTY_NAME, oldValue, operationResult); - } - - @Override - public void start() { - super.start(); - firePropertyChange(OPERATIONS_PROPERTY_NAME, null, operations); - } - - public WizardModelWithOperations<E, O, R> addOperation(O operation) { - getOperations().add(operation); - /*if (operation == SynchroOperation.EXPORT_DATA) { - // pour exporter les données utilisateurs - // les operations synchronisation de référentiel et validation - // sont necessaires - getOperations().add(SynchroOperation.SYNCHRONIZE_REFERENTIEL); - getOperations().add(SynchroOperation.VALIDATION); - }*/ - // on force la propagation de la nouvelle liste - firePropertyChange(OPERATIONS_PROPERTY_NAME, null, operations); - - updateUniverse(); - validate(); - return this; - } - - public void removeOperation(O operation) { - getOperations().remove(operation); - /*if (operation == SynchroOperation.SYNCHRONIZE_REFERENTIEL || operation == SynchroOperation.VALIDATION) { - // pour exporter les données utilisateurs - // les operations synchronisation de référentiel et validation - // sont necessaires - getOperations().remove(SynchroOperation.EXPORT_DATA); - }*/ - // on force la propagation de la nouvelle liste - firePropertyChange(OPERATIONS_PROPERTY_NAME, null, operations); - updateUniverse(); - validate(); - } -} Modified: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperation.java =================================================================== --- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperation.java 2009-03-13 22:00:34 UTC (rev 1265) +++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperation.java 2009-03-14 19:24:14 UTC (rev 1266) @@ -6,7 +6,7 @@ * @author tony * @since 1.3 */ -public interface WizardOperation<Action extends WizardAbstractOperationAction> { +public interface WizardOperation<Action extends WizardOperationAction> { String name(); Copied: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationAction.java (from rev 1265, jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationAction.java) =================================================================== --- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationAction.java (rev 0) +++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationAction.java 2009-03-14 19:24:14 UTC (rev 1266) @@ -0,0 +1,94 @@ +package jaxx.runtime.swing.wizard; + +import javax.swing.SwingWorker; +import jaxx.runtime.JAXXContext; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author tony + * @param <E> le type d'étapes + * @param <O> le type d'opérations + * @param <M> le type de modèle + * @since 1.3 + */ +public abstract class WizardOperationAction<E extends Enum<E>, O extends Enum<O>, M extends WizardOperationModel<E, O>> extends SwingWorker<WizardOperationState, String> { + + /** to use log facility, just put in your code: log.info(\"...\"); */ + private static final Log log = LogFactory.getLog(WizardOperationAction.class); + O operation; + WizardOperationState operationState; + Exception error; + + public WizardOperationAction(O operation) { + super(); + this.operation = operation; + } + + public O getOperation() { + return operation; + } + + public abstract void start(JAXXContext context); + + public abstract void beforeAction(JAXXContext context, M model) throws Exception; + + public abstract WizardOperationState doAction(M model) throws Exception; + + public abstract WizardOperationState onError(M model, Exception e); + + public abstract WizardOperationState onCancel(M model, Exception e); + + public abstract void afterAction(M model, WizardOperationState result, Exception error); + + protected abstract M getModel(); + + public WizardOperationState getOperationState() { + return operationState; + } + + protected abstract JAXXContext getContext(); + + @Override + public String toString() { + return super.toString() + " < operation: " + operation + ", state: " + getState() + " >"; + } + + @Override + protected WizardOperationState doInBackground() throws Exception { + log.trace(this); + WizardOperationState result; + M model = getModel(); + try { + beforeAction(getContext(), model); + result = doAction(model); + } catch (Exception e) { + error = e; + result = onError(model, e); + } + return result; + } + + @Override + protected void done() { + log.trace(this); + WizardOperationState result = null; + try { + if (isCancelled()) { + + result = onCancel(getModel(), error); + } else { + result = get(); + } + } catch (Exception e) { + result = WizardOperationState.FAILED; + error = e; + // ne devrait jamais arrivé ? + log.error(e.getMessage(), e); + } finally { + // on enregistre le resultat de l'opération + this.operationState = result; + } + } +} Property changes on: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationAction.java ___________________________________________________________________ Name: svn:mergeinfo + Copied: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationActionThread.java (from rev 1265, jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardAbstractOperationActionThread.java) =================================================================== --- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationActionThread.java (rev 0) +++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationActionThread.java 2009-03-14 19:24:14 UTC (rev 1266) @@ -0,0 +1,235 @@ +package jaxx.runtime.swing.wizard; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; +import java.util.Date; +import javax.swing.SwingWorker.StateValue; +import jaxx.runtime.JAXXContext; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * Thread qui réalise les opérations. + * + * Pour exécuter une nouvelle opération, on utilise la méthode + * {@link #launchOperation(SynchroActionWorker)}. + * + * Note: Pour bloquer (ou débloquer) le thread, on utilise la méthode {@link #setWaiting(boolean)} + * + * @param <E> le type des etapes + * @param <O> le type des operations + * @param <M> le type de modele + * @param <A> le type d'action d'operation + * + * @author tony + * @since 1.3 + */ +public abstract class WizardOperationActionThread<E extends Enum<E>, O extends Enum<O>, M extends WizardOperationModel<E, O>, A extends WizardOperationAction<E, O, 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); + /** + * l'état du thread si annulé + */ + private boolean canceled; + /** suport of modification propagation */ + protected PropertyChangeSupport pcs; + protected Class<M> modelClass; + protected A currentAction; + /** + * un lock pour permettre la suspension et la reprise du thread + * lors du mode interactif. + */ + private final Object LOCK = new Object(); + + protected abstract M getModel(); + + protected abstract JAXXContext getContext(); + + public WizardOperationActionThread(Class<M> modelClass) throws IllegalArgumentException { + super(WizardOperationActionThread.class.getSimpleName() + " " + new Date()); + this.modelClass = modelClass; + this.pcs = new PropertyChangeSupport(this); + } + + public void cancel() { + if (currentAction != null) { + log.debug("cancel action " + currentAction); + // on a une action en cours, on l'annule + currentAction.cancel(true); + } + // on annule aussi le modele + getModel().cancel(); + this.canceled = true; + // on rend la main au thread + setWaiting(false); + } + + public void launchOperation(A action) { + + if (currentAction != null) { + // 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"); + } + currentAction = action; + // on libere le thread pour qu'il execute l'opération + setWaiting(false); + } + + @Override + public void propertyChange(PropertyChangeEvent evt) { + log.info(evt.getPropertyName() + " <" + evt.getOldValue() + " - " + evt.getNewValue() + ">"); + if ("state".equals(evt.getPropertyName())) { + //@SuppressWarnings("unchecked") + //A action = (A) evt.getSource(); + StateValue state = (StateValue) evt.getNewValue(); + if (state == StateValue.DONE) { + // on rend la main au thread pour qu'il attende une prochaine operation + //getModel().setOperationState(action.getOperation(), action.getOperationState()); + setWaiting(false); + } + } + } + + @Override + public void run() { + try { + + // on vérifie que le context contient bien le modèle + if (getModel() == null) { + throw new NullPointerException("could not find model " + modelClass + " for " + this); + } + + while (!canceled) { + + if (canceled) { + // une annulation a été demandé + // donc même si une opération est demandée, on ne la traite + // pas + break; + } + + // en attente qu'une opération + // le block est bloqué jusqu'à arrivée d'une opération + // ou une demande d'annulation + setWaiting(true); + + // le thread a repris la main, donc plus en attente + log.trace("no more waiting " + this); + + if (!canceled) { + // une opération a été demandée + + // le thread écoute les modifications de l'action + currentAction.addPropertyChangeListener(this); + + // l'opération passe en etant en cours + getModel().setOperationState(WizardOperationState.RUNNING); + + // démarrage de l'opération dans un worker + currentAction.start(getContext()); + // le thread est bloqué jusqu'à la fin de l'opération + // ou une demande d'annulation + setWaiting(true); + + // le thread reprend la main des que l'operation + // est terminée ou a été annulée, on passera alors + // dans la méthode onPropertyChanged + + getModel().setOperationState(currentAction.getOperationState()); + + // le thread n'écoute plus l'action car elle est terminée + // ou annulée + currentAction.removePropertyChangeListener(this); + // suppression de l'action + currentAction = null; + } + + } + + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + unlockThread(); + log.trace(this + " will close..."); + close(); + } + } + + /** + * La méthode pour nettoyer le thread, a la fermeture. + * + */ + protected void close() { + // par defaut, on ne fait rien + log.trace(this); + } + + // PropertyChanged support + public void addPropertyChangeListener(PropertyChangeListener listener) { + pcs.addPropertyChangeListener(listener); + } + + public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) { + pcs.addPropertyChangeListener(propertyName, listener); + } + + public void removePropertyChangeListener(PropertyChangeListener listener) { + pcs.removePropertyChangeListener(listener); + } + + public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) { + pcs.removePropertyChangeListener(propertyName, listener); + } + + public synchronized boolean hasListeners(String propertyName) { + return pcs.hasListeners(propertyName); + } + + public synchronized PropertyChangeListener[] getPropertyChangeListeners(String propertyName) { + return pcs.getPropertyChangeListeners(propertyName); + } + + public synchronized PropertyChangeListener[] getPropertyChangeListeners() { + return pcs.getPropertyChangeListeners(); + } + + protected void firePropertyChange(String propertyName, Object oldValue, Object newValue) { + pcs.firePropertyChange(propertyName, oldValue, newValue); + } + + protected void setWaiting(boolean waiting) { + + if (waiting && !canceled) { + // locking thread + try { + lockThread(); + } catch (InterruptedException ex) { + log.error(ex.getMessage(), ex); + canceled = true; + } + } + + if (!waiting) { + // release lock + unlockThread(); + } + } + + protected void lockThread() throws InterruptedException { + synchronized (LOCK) { + log.trace(this); + // lock + LOCK.wait(); + } + } + + protected void unlockThread() { + synchronized (LOCK) { + log.trace(this); + // unlock + LOCK.notify(); + } + } +} Property changes on: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationActionThread.java ___________________________________________________________________ Name: svn:mergeinfo + Copied: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationModel.java (from rev 1265, jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardModelWithOperations.java) =================================================================== --- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationModel.java (rev 0) +++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationModel.java 2009-03-14 19:24:14 UTC (rev 1266) @@ -0,0 +1,191 @@ +package jaxx.runtime.swing.wizard; + +import java.util.EnumMap; +import java.util.EnumSet; + +/** + * Un modèle de wizard avec des opérations. + * + * @param <E> le type des étapes. + * @param <O> le type des opérations. + * @author tony + * @since 1.3 + */ +public class WizardOperationModel<E extends Enum<E>, O extends Enum<O>> extends WizardModel<E> { + + public static final String OPERATIONS_PROPERTY_NAME = "operations"; + public static final String OPERATION_STATE_PROPERTY_NAME = "operationState"; + public static final String MODEL_STATE_PROPERTY_NAME = "modelState"; + public static final String WAS_STARTED_PROPERTY_NAME = "wasStarted"; + /** + * le type d'une opération + */ + protected Class<O> operationClass; + /** + * La liste des opérations à effectuer + */ + protected EnumSet<O> operations; + /** + * Pour conserver les états des opérations + */ + protected EnumMap<O, WizardOperationState> operationStates; + /** + * L'état générale du modèle + */ + protected WizardOperationState modelState; + /** + * un drapeau pour savoir siune opération a été lancée + */ + protected boolean wasStarted; + + public WizardOperationModel(Class<E> stepClass, Class<O> operationClass, E... steps) { + super(stepClass, steps); + this.operationClass = operationClass; + this.operationStates = new EnumMap<O, WizardOperationState>(operationClass); + } + + public EnumSet<O> getOperations() { + if (operations == null) { + operations = EnumSet.noneOf(operationClass); + } + return operations; + } + + public WizardOperationState getModelState() { + return modelState; + } + + public boolean isWasStarted() { + return wasStarted; + } + + @SuppressWarnings("unchecked") + public O getOperation() { + return ((WizardOperationStep<O>) getStep()).getOperation(); + } + + public WizardOperationState getOperationState() { + O operation = getOperation(); + return getOperationState(operation); + } + + public WizardOperationState getOperationState(O operation) { + return operationStates.get(operation); + } + + public void setOperationState(WizardOperationState operationState) { + O operation = getOperation(); + setOperationState(operation, operationState); + } + + public void setOperationState(O operation, WizardOperationState operationState) { + WizardOperationState oldValue = getOperationState(operation); + this.operationStates.put(operation, operationState); + firePropertyChange(OPERATION_STATE_PROPERTY_NAME, oldValue, operationState); + //fireIndexedPropertyChange(OPERATION_STATE_PROPERTY_NAME, getOperationIndex(operation), oldValue, operationStates); + updateModelState(operation, operationState); + validate(); + } + + @Override + public void start() { + super.start(); + // le modèle n'est pas démarré + setModelState(WizardOperationState.PENDING); + firePropertyChange(OPERATIONS_PROPERTY_NAME, null, operations); + } + + public void cancel() { + for (O op : operations) { + if (getOperationState(op) == WizardOperationState.PENDING) { + // on annule l'opération à venir + setOperationState(op, WizardOperationState.CANCELED); + } + } + } + + public WizardOperationModel<E, O> addOperation(O operation) { + getOperations().add(operation); + // on force la propagation de la nouvelle liste + firePropertyChange(OPERATIONS_PROPERTY_NAME, null, operations); + // mis a jour de l'univers des etapes et operations + updateUniverse(); + // validation + validate(); + return this; + } + + public void removeOperation(O operation) { + getOperations().remove(operation); + // on force la propagation de la nouvelle liste + firePropertyChange(OPERATIONS_PROPERTY_NAME, null, operations); + // mis a jour de l'univers des etapes et operations + updateUniverse(); + // validation + validate(); + } + + protected void setModelState(WizardOperationState modelState) { + WizardOperationState oldValue = this.modelState; + this.modelState = modelState; + firePropertyChange(MODEL_STATE_PROPERTY_NAME, oldValue, modelState); + if (!wasStarted) { + if ((oldValue == null || oldValue == WizardOperationState.PENDING) && modelState == WizardOperationState.RUNNING) { + this.wasStarted = true; + firePropertyChange(WAS_STARTED_PROPERTY_NAME, false, true); + } + } + } + + protected void updateModelState(O operation, WizardOperationState operationState) { + + switch (operationState) { + case RUNNING: + //le model est occupé + setModelState(WizardOperationState.RUNNING); + break; + case FAILED: + //le model est en attente + setModelState(WizardOperationState.PENDING); + break; + case CANCELED: + //le model devient annulé + setModelState(WizardOperationState.CANCELED); + break; + case PENDING: + //le model est en attente + setModelState(WizardOperationState.PENDING); + break; + case NEED_FIX: + //le model est en attente + setModelState(WizardOperationState.PENDING); + break; + case SUCCESSED: + // on regarde si on peut passer le model a l'état success + boolean valid = true; + for (O o : operations) { + if (getOperationState(o) != WizardOperationState.SUCCESSED) { + valid = false; + break; + } + } + if (valid) { + setModelState(WizardOperationState.SUCCESSED); + } else { + setModelState(WizardOperationState.PENDING); + } + break; + } + } + + protected int getOperationIndex(O operation) { + int index = 0; + for (O o : operations) { + if (operation == o) { + return index; + } + index++; + } + return -1; + } +} Property changes on: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationModel.java ___________________________________________________________________ Name: svn:mergeinfo + Added: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationState.java =================================================================== --- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationState.java (rev 0) +++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationState.java 2009-03-14 19:24:14 UTC (rev 1266) @@ -0,0 +1,32 @@ +package jaxx.runtime.swing.wizard; + +/** + * Pour caractériser l'état d'une opération. + */ +public enum WizardOperationState { + + /** + * quand l'opération n'a pas encore été réalisée + */ + PENDING, + /** + * quand l'opération est en cours + */ + RUNNING, + /** + * quand l'opération est annulé en cours d'exécution + */ + CANCELED, + /** + * quand une erreur s'est produite pendant l'exécution + */ + FAILED, + /** + * quand l'exécution s'est terminée mais requière des corrections + */ + NEED_FIX, + /** + * quand l'exécution s'est terminée et ne requière pas de correction + */ + SUCCESSED +} Added: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationStep.java =================================================================== --- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationStep.java (rev 0) +++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardOperationStep.java 2009-03-14 19:24:14 UTC (rev 1266) @@ -0,0 +1,20 @@ +package jaxx.runtime.swing.wizard; + +/** + * + * @param <Operation> + * @author tony + * @since 1.3 + */ +public interface WizardOperationStep<Operation extends Enum<Operation>> { + + String name(); + + int ordinal(); + + String getLabel(); + + String getDescription(); + + Operation getOperation(); +} Modified: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUI.java =================================================================== --- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUI.java 2009-03-13 22:00:34 UTC (rev 1265) +++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUI.java 2009-03-14 19:24:14 UTC (rev 1266) @@ -18,8 +18,6 @@ M getModel(); - void init(); - void start(); JTabbedPane getTabs(); Modified: jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java =================================================================== --- jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java 2009-03-13 22:00:34 UTC (rev 1265) +++ jaxx/trunk/jaxx-runtime-swing/src/main/java/jaxx/runtime/swing/wizard/WizardUILancher.java 2009-03-14 19:24:14 UTC (rev 1266) @@ -20,18 +20,14 @@ protected UI ui; - protected abstract void doAction(UI ui); - @SuppressWarnings("unchecked") public WizardUILancher(JAXXContext context, JFrame mainUI, Class<UI> uiClass, Class<M> modelClass) { super(); try { + // instanciate ui parent context JAXXInitialContext uiContext = new JAXXInitialContext(); - // instanciate ui - // parent context uiContext.add(mainUI == null ? context : mainUI); - // parent context - // model + // parent context model uiContext.add(modelClass.newInstance()); // apply action uiContext.add("apply", new Runnable() { @@ -51,7 +47,7 @@ }); // instanciate ui - ui = (UI) ConstructorUtils.invokeConstructor(uiClass, new Object[]{mainUI, uiContext}); + ui = (UI) ConstructorUtils.invokeConstructor(uiClass, new Object[]{mainUI, uiContext}, new Class[]{JFrame.class, JAXXContext.class}); } catch (Exception ex) { throw new RuntimeException("could not instanciate launcher for reason " + ex.getMessage(), ex); @@ -59,20 +55,28 @@ } public void start() { - init(ui); - //ui.start(); + try { + init(ui); + ui.start(); + } finally { + dispose(); + } } + public void dispose() { + ui = null; + } + protected void init(UI ui) { } - protected void afterInit(UI ui) { + protected void doAction(UI ui) { } protected void doCancel(UI ui) { } - public <T> T getContextValue(Class<T> clazz, String name) { + protected <T> T getContextValue(Class<T> clazz, String name) { if (ui == null) { throw new NullPointerException("ui can not be null"); } @@ -83,11 +87,7 @@ return ((JAXXObject) ui).getContextValue(clazz, name); } - public <T> T getContextValue(Class<T> clazz) { + protected <T> T getContextValue(Class<T> clazz) { return getContextValue(clazz, null); } - - public void dispose() { - ui = null; - } }
participants (1)
-
tchemit@users.labs.libre-entreprise.org