All Downloads are FREE. Search and download functionalities are using the official Maven repository.

jaxx.runtime.swing.wizard.WizardOperationModel Maven / Gradle / Ivy

/*
 * *##% 
 * JAXX Runtime
 * Copyright (C) 2008 - 2009 CodeLutin
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 *
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * ##%*
 */
package jaxx.runtime.swing.wizard;

import java.util.Arrays;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.swing.SwingWorker.StateValue;

/**
 * Un modèle de wizard avec des opérations.
 *
 * @param  le type des étapes.
 * @author tony
 * @since 1.3
 */
public class WizardOperationModel extends WizardModel {

    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";

    /**
     * La liste des opérations à effectuer
     */
    protected Set operations;
    /**
     * Pour conserver les états des opérations
     */
    protected Map operationStates;
    protected Map operationActions;
    /**
     * 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;

    @SuppressWarnings("unchecked")
    public > WizardOperationModel(Class stepClass, E... steps) {
        super(stepClass, steps);
        Class k = (Class) stepClass;
        this.operationStates = (Map) new EnumMap(k);
        this.operations = (Set) EnumSet.noneOf(k);
        this.operationActions = (Map) new EnumMap(k);
    }

    public Set getOperations() {
        return operations;
    }

    public WizardOperationState getModelState() {
        return modelState;
    }

    public boolean isWasStarted() {
        return wasStarted;
    }

    @SuppressWarnings("unchecked")
    public E getOperation() {
        return getStep() != null && getStep().isOperation() ? getStep() : null;
    }

    public WizardOperationState getOperationState() {
        E operation = getOperation();
        return getOperationState(operation);
    }

    public WizardOperationState getOperationState(E operation) {
        return operationStates.get(operation);
    }

    public WizardOperationAction getOperationAction(E operation) {
        WizardOperationAction action = operationActions.get(operation);
        if (action == null) {
            try {
                action = operation.getActionClass().newInstance();
                operationActions.put(operation, action);
            } catch (Exception ex) {
                throw new RuntimeException(ex);
            }
        }
        return action;
    }

    public void setOperationState(WizardOperationState operationState) {
        E operation = getOperation();
        setOperationState(operation, operationState);
    }

    public void setOperationState(E operation, WizardOperationState operationState) {
        WizardOperationState oldValue = getOperationState(operation);
        this.operationStates.put(operation, operationState);
        fireIndexedPropertyChange(OPERATION_STATE_PROPERTY_NAME, getSteps().indexOf(operation), oldValue, operationState);
        updateModelState(operation, operationState);
        validate();
    }

    public boolean[] getAccessibleSteps() {
        boolean[] result = new boolean[getSteps().size()];
        int index = getSteps().indexOf(getStep());
        if (index != -1) {

            for (int i = 0, j = steps.size(); i < j; i++) {
                if (i <= index) {
                    // tous les onglets inferieur ou egal au courant sont accessibles
                    result[i] = true;
                    continue;
                }
                // les onglets au dela de l'onglet sélectionné sont accessibles
                // uniquement si l'onglet precedent est accessible, valide et son etat est a SUCCESSED
                E previousStep = steps.get(i - 1);
                result[i] = modelState == WizardOperationState.SUCCESSED ||
                        (result[i - 1] &&
                        validate(previousStep) &&
                        (!previousStep.isOperation() || getOperationState(previousStep) == WizardOperationState.SUCCESSED));
            }
        }
        //System.out.println("accessibles steps -------- " + java.util.Arrays.toString(result));
        return result;
    }

    @Override
    public void start() {
        super.start();
        updateUniverse();
        //setSteps(steps.toArray((E[]) Array.newInstance(stepClass, steps.size())));

        // le modèle n'est pas démarré
        setModelState(WizardOperationState.PENDING);
    }

    public void cancel() {

        for (E op : operations) {
            if (getOperationState(op) == WizardOperationState.PENDING) {
                // on annule l'opération à venir
                setOperationState(op, WizardOperationState.CANCELED);
            }
        }
        setModelState(WizardOperationState.CANCELED);
        if (getStep() != null && getStep().isOperation()) {
            WizardOperationAction action = getOperationAction(getStep());
            if (action != null) {
                if (!action.isCancelled() && !action.isDone() && action.getState() == StateValue.STARTED) {
                    System.out.println("cancel action " + action);
                    // on annule l'action
                    action.cancel(true);
                }
            }
        }
    }

    public WizardOperationModel addOperation(E operation) {
        operations.add(operation);
        // mis a jour de l'univers des etapes et operations
        updateUniverse();
        // validation
        validate();
        return this;
    }

    public void removeOperation(E operation) {
        operations.remove(operation);

        // mis a jour de l'univers des etapes et operations
        updateUniverse();
        // validation
        validate();
    }

    @Override
    public void setSteps(E... steps) {
        super.setSteps(steps);
        // on force la propagation de la nouvelle liste
        firePropertyChange(OPERATIONS_PROPERTY_NAME, null, operations);
        updateOperationStates(Arrays.asList(steps));
    }

    public void updateOperationStates(List steps) {
        int index = 0;
        for (E e : steps) {
            fireIndexedPropertyChange(OPERATION_STATE_PROPERTY_NAME, index++, null, getOperationState(e));
        }
        firePropertyChange(MODEL_STATE_PROPERTY_NAME, null, modelState);
    }

    public WizardOperationAction reloadOperation(E operation) {
        operationActions.remove(operation);
        WizardOperationAction newOp = getOperationAction(operation);
        return newOp;
    }

    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(E operation, WizardOperationState operationState) {

        switch (operationState) {
            case RUNNING:
                //le modele est occupé
                setModelState(WizardOperationState.RUNNING);
                break;
            case FAILED:
                //le modele est en erreur
                setModelState(WizardOperationState.FAILED);
                break;
            case CANCELED:
                //le modele devient annulé
                setModelState(WizardOperationState.CANCELED);
                return;
            case PENDING:
                //le modele est en attente
                setModelState(WizardOperationState.PENDING);
                break;
            case NEED_FIX:
                //le modele 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 (E o : operations) {
                    if (getOperationState(o) != WizardOperationState.SUCCESSED) {
                        valid = false;
                        break;
                    }
                }
                if (valid) {
                    setModelState(WizardOperationState.SUCCESSED);
                } else {
                    setModelState(WizardOperationState.PENDING);
                }
                break;
        }
        updateOperationStates(steps);
    }

    @Override
    protected void updateUniverse() {
        E[] newSteps = updateStepUniverse();
        setSteps(newSteps);
    }

    protected int getOperationIndex(E operation) {
        int index = 0;
        for (E o : operations) {
            if (operation == o) {
                return index;
            }
            index++;
        }
        return -1;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy