Package eu.planets_project.pp.plato.action.workflow

Source Code of eu.planets_project.pp.plato.action.workflow.DefineAlternativesAction

/*******************************************************************************
* Copyright (c) 2006-2010 Vienna University of Technology,
* Department of Software Technology and Interactive Systems
*
* All rights reserved. This program and the accompanying
* materials are made available under the terms of the
* Apache License, Version 2.0 which accompanies
* this distribution, and is available at
* http://www.apache.org/licenses/LICENSE-2.0
*******************************************************************************/

package eu.planets_project.pp.plato.action.workflow;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.ejb.Remove;
import javax.ejb.Stateful;
import javax.faces.application.FacesMessage;

import org.apache.commons.logging.Log;
import org.jboss.annotation.ejb.cache.Cache;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Destroy;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Out;
import org.jboss.seam.annotations.RaiseEvent;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.datamodel.DataModel;
import org.jboss.seam.annotations.datamodel.DataModelSelection;
import org.jboss.seam.faces.FacesMessages;

import eu.planets_project.pp.plato.action.interfaces.IDefineAlternatives;
import eu.planets_project.pp.plato.action.interfaces.IGoNoGo;
import eu.planets_project.pp.plato.action.interfaces.IWorkflowStep;
import eu.planets_project.pp.plato.bean.PrepareChangesForPersist;
import eu.planets_project.pp.plato.model.Alternative;
import eu.planets_project.pp.plato.model.AlternativesDefinition;
import eu.planets_project.pp.plato.model.FormatInfo;
import eu.planets_project.pp.plato.model.PlanState;
import eu.planets_project.pp.plato.model.PreservationActionDefinition;
import eu.planets_project.pp.plato.model.SampleObject;
import eu.planets_project.pp.plato.model.User;
import eu.planets_project.pp.plato.model.Values;
import eu.planets_project.pp.plato.model.tree.Leaf;
import eu.planets_project.pp.plato.model.tree.ObjectiveTree;
import eu.planets_project.pp.plato.services.PlatoServiceException;
import eu.planets_project.pp.plato.services.action.IPreservationActionRegistry;
import eu.planets_project.pp.plato.services.action.PreservationActionRegistryDefinition;
import eu.planets_project.pp.plato.services.action.PreservationActionRegistryFactory;
import eu.planets_project.pp.plato.util.PlatoLogger;
/**
* Implements actions for workflow step 'Define Sample Records'
* where sample records can be added and described, and their format can be identified.
*
* @author Michael Kraxner
*/

@Stateful
@Scope(ScopeType.SESSION)
@Name("defineAlternatives")
@Cache(org.jboss.ejb3.cache.NoPassivationCache.class)
public class DefineAlternativesAction extends AbstractWorkflowStep implements
        IDefineAlternatives {


    /**
     *
     */
    private static final long serialVersionUID = -277644335068218608L;

    private static final Log log = PlatoLogger
            .getLogger(DefineAlternativesAction.class);

    /**
     * The go/no-go step is the successor
     */
    @In(create = true)
    IGoNoGo gonogo;

    @DataModelSelection
    private Alternative selectedAlternative;

    @In (required=false)
    private User user;

    protected String getWorkflowstepName() {
        return "defineAlternatives";
    }

    /**
     * Contains all alternatives of the preservation planning project:
     * considered and discarded alternatives
     */
    @SuppressWarnings("unused")
    @DataModel
    private List<Alternative> alternativeList;

    /**
     * this private utility list is used for checking for changes of alternative names.
     * this is needed because the name is used for mapping the evaluation values, in the hashmap
     * that maps to {@link Values}
     */
    private HashMap<Alternative,String> alternativeNames = new HashMap<Alternative,String>();
   
    /**
     * The alternative the user has selected to edit - or a newly created one
     */
    @Out(required = false)
    private Alternative alt;

    /**
     * This determines the behaviour of the remove-buttons on the page (see
     * there) - to remove alternatives from the list
     */
    @Out
    private int allowRemove = -1;

    /**
     * A list of all currently defined preservation service registries
     */
    @Out(required = false)
    private List<PreservationActionRegistryDefinition> availableRegistries;

    /**
     * A list of all currently defined preservation services registries,
     * each of them accompanied with a flag if the user wants to search this registry
     */
    @Out(required = false)
    private Map<PreservationActionRegistryDefinition, Boolean> registrySelection;

  
    /**
     * The list of all preservation services found in the selected registries
     */
    @Out(required = false)
    private List<PreservationActionDefinition> availableActions = new ArrayList<PreservationActionDefinition>();

    /**
     *
     * @return Number of found preservation services.
     */
    @Out(required = false)
    private int GetNumOfAvailableActions() {
        return availableActions.size();
    }

    public DefineAlternativesAction() {
        requiredPlanState = new Integer(PlanState.TREE_DEFINED);
    }

    /**
     * Feeds the list allAlternativesList for being displayed. It contains the
     * considered as well as discarded alternatives.
     *
     * Loads the list of all defined preservation service registries.
     */
    public void init() {

        allowRemove = -1;

        alternativeList = selectedPlan.getAlternativesDefinition()
                .getAlternatives();

        alt = null;
       
        resetAlternativeNames();

        // populate the list of preservation service registries
        List<PreservationActionRegistryDefinition> registries =
            PreservationActionRegistryFactory.getAvailableRegistries();
        if (registrySelection == null)
            registrySelection = new HashMap<PreservationActionRegistryDefinition, Boolean>();
        else
            registrySelection.clear();

        for (PreservationActionRegistryDefinition definition : registries) {
            registrySelection.put(definition, false);
        }
        // Map.keySet() is not accessible via EL, therefore we have to outject the list of registries
        availableRegistries = registries;
        availableActions.clear();
     }

    /**
     * gets the names of all alternatives in the list and maps them to their current names -
     * stored in  {@link #alternativeNames} for checking later if some names changed.
     */
    private void resetAlternativeNames() {
        alternativeNames.clear();
        for (Alternative a: alternativeList) {
            alternativeNames.put(a,a.getName());
        }  
    }

    protected IWorkflowStep getSuccessor() {
        return gonogo;
    }

    /**
     * Creates a new alternative in the memory. The alternative is neither added
     * to the list of alternatives nor stored in database (user has to press the
     * save button to store it permanently in the database).
     */
    public String create() {
        log.debug("Creating New Alternative");

        alt = Alternative.createAlternative();

        return null;
    }

    public String select() {
        alt = selectedAlternative;
        allowRemove = -1;
        return null;
    }

    /**
     * Adds a newly created alternative to the list of alternatives Does not
     * persist the alternative in the database!
     */
    public void editAlternative() {

        if (alt == null) {
            log
                    .error("No alternative selected. This method should not have been called.");
            return;
        }
        AlternativesDefinition alternativesDefinition = selectedPlan.getAlternativesDefinition();
        // its a new alternative and the alternative is not yet in list of
        // alternatives
        // note: the user can also edit an alternative that has already been added to the list
        if ((alt.getId() == 0) &&
            (!alternativesDefinition.getAlternatives().contains(alt))) {
            String altName = alt.getName();
            if ((altName.length() > 20)||
                (null != alternativesDefinition.alternativeByName(altName))){
                FacesMessages.instance()
                    .add(FacesMessage.SEVERITY_ERROR,
                        "Please provide a unique name which has no more than 20 characters.");
                return;
            }

            // add it to the preservation planning project
            alternativesDefinition.addAlternative(alt);
            // refresh the datamodel list
            alternativeList = alternativesDefinition.getAlternatives();
            // the alternativesdefinition has been changed
            alternativesDefinition.touch();
        }
        // this alternative has been changed
        alt.touch();

        // exit editing mode
        alt = null;
    }

    @Override
    public String save() {
        /** dont forget to prepare changed entities e.g. set current user */
        /** we have to do this now, so new alternatives get also the current user set */
        PrepareChangesForPersist prep = new PrepareChangesForPersist(user.getUsername());
        prep.prepare(selectedPlan.getAlternativesDefinition());
       
        // if there are new alternatives save them first!
        for (Alternative alt : alternativeList) {
            if (alt.getId() == 0)

                em.persist(alt);
        }
        // update name mappings in the tree
        boolean updatedAlternativeNames = updateAlternativeNames();

       
        save(selectedPlan.getRecommendation());
        save(selectedPlan.getAlternativesDefinition());
       
        // if name mappings were updated, we have to save the tree,
        // or if an alternative has been deleted - so for now we just do it:
        save(selectedPlan.getTree());
       
        if (updatedAlternativeNames) {
            for (Leaf l: selectedPlan.getTree().getRoot().getAllLeaves()) {
                em.persist(em.merge(l));
            }          
        }
       
        changed = "";
       
        resetAlternativeNames();
        return null;
    }

    private boolean updateAlternativeNames() {
        boolean result = false;
        for (Alternative a: alternativeList) {
            String name = alternativeNames.get(a);
            if (name != null && (!name.equals(a.getName()))) {
                selectedPlan.getTree().updateAlternativeName(name,a.getName());
                result = true;
            }
        }
        return result;
    }

    /**
     * The preservation planning project must have at least on alternative
     * defined (considered or discarded alternative)
     */
    public boolean validate(boolean showValidationErrors) {
       
        if (alt != null) {
            FacesMessages
            .instance()
            .add(FacesMessage.SEVERITY_ERROR,
                    "You are currently editing an Alternative. Please save the alternative first before you proceed to the next step.");          
           
            return false;
        }

        int nrOfAlternatives = selectedPlan.getAlternativesDefinition()
                .getAlternatives().size();
        // +
        // selectedPlan.getAlternativesDefinition().getDiscardedAlternatives().size();

        if (nrOfAlternatives <= 0) {

            // we only add a message if we are supposed to do so
            if (showValidationErrors) {
                FacesMessages
                        .instance()
                        .add(FacesMessage.SEVERITY_ERROR,
                                "At least one alternative must be added to proceed with the workflow.");
            }

            return false;
        }

        return true;
    }

    /**
     * Removes an alternative from the list AND also removes all associated
     * evaluation values contained in the tree, if there are any.
     */
    public String removeAlternative() {
        log.info("Removing Alternative from Plan: "+ selectedAlternative.getName());
        updateAlternativeNames();
       
        if (selectedPlan.getRecommendation().getAlternative() == selectedAlternative) {
            selectedPlan.getRecommendation().setAlternative(null);
            selectedPlan.getRecommendation().setReasoning("");
            selectedPlan.getRecommendation().setEffects("");
            FacesMessages.instance().add(FacesMessage.SEVERITY_INFO,
               "You have removed the action which was chosen as the recommended alternative.");
        }
        selectedPlan.getAlternativesDefinition().removeAlternative(selectedAlternative);

        alternativeList = selectedPlan.getAlternativesDefinition()
                .getAlternatives();
        selectedPlan.getAlternativesDefinition().touch();

        selectedPlan.getTree().removeValues(selectedAlternative);

        allowRemove = -1;

        // after the selected alternative was deleted, alt, which is needed to
        // display the currently selected alternative, must be set to null.
        alt = null;
        selectedAlternative = null;
        return null;
    }

    /**
     * Checks if the alternative contains evaluation values. If yes, the user
     * should be asked for confirmation before removing it. If not, the
     * alternative is immediately removed.
     *
     * @see ObjectiveTree#hasValues(int[], Alternative)
     */
    public String askRemoveAlternative() {
        if (selectedAlternative == null || alternativeList.size() == 0) {
            allowRemove = -1;
            return null;
        }

        // We need the indices of all records to be able to check whether values
        // exist.
        // The array needs to be created here because the ObjectiveTree doesn't
        // know how many records exist!
        int records[] = new int[selectedPlan.getSampleRecordsDefinition()
                .getRecords().size()];
        for (int i = 0; i < records.length; i++) {
            records[i] = i;
        }
        Set<String> altName = new HashSet<String>(1);
        altName.add(selectedAlternative.getName());
        if (selectedPlan.getTree().hasValues(records, altName)) {
            allowRemove = selectedAlternative.getId();
        } else {
            removeAlternative();
        }
        return null;
    }
   
    public List<PreservationActionDefinition> queryRegistry(FormatInfo formatInfo,
            PreservationActionRegistryDefinition registry)
            throws PlatoServiceException
    {
        IPreservationActionRegistry serviceLocator = null;
        try {
            serviceLocator = PreservationActionRegistryFactory.getInstance(registry);
        } catch (IllegalArgumentException e1) {
            throw new PlatoServiceException( "Registry:  " + registry.getShortname() + " has changed and needs to be reconfigured.");
        }
        if (serviceLocator == null) {
            throw new PlatoServiceException ("Failed to access " + registry.getShortname());
        }
        // query the registry
        return serviceLocator.getAvailableActions(formatInfo);
    }

    /**
     * Looks up the <code>registry</code> for preservation services
     * that can handle objects which are of the same type as the first sample record.
     */
    public String showPreservationServices(Object registry) {
        // get first sample with data
        SampleObject sample = selectedPlan.getSampleRecordsDefinition().getFirstSampleWithFormat();
        if (sample == null) {
            return null;
        }
        FormatInfo formatInfo = sample.getFormatInfo();

        PreservationActionRegistryDefinition reg = (PreservationActionRegistryDefinition) registry;
        try {
            availableActions.clear();
            List<PreservationActionDefinition> actions = queryRegistry(formatInfo, reg);
            availableActions.addAll(actions);
            // this registry is responsible for the result - mark it as selected
            for (PreservationActionRegistryDefinition r: registrySelection.keySet()) {
                registrySelection.put(r, (registry == r) );
            }
        } catch (PlatoServiceException e) {
            log.error(e.getMessage(),e);
            FacesMessages.instance().add(FacesMessage.SEVERITY_ERROR,
                    "Failed to look up services of: " + reg.getShortname()
                    + ": " + e.getMessage());
        }
        return null;
    }
   
    /**
     * Looks up the <code>registry</code> for preservation services
     * that can handle objects which are of the same type as the first sample record.
     */
//    public String showPreservationServices(Object registry) {
//        // get first sample with data
//        SampleObject sample = selectedPlan.getSampleRecordsDefinition().getFirstSampleWithFormat();
//        if (sample == null) {
//            return null;
//        }
//        FormatInfo formatInfo = sample.getFormatInfo();
//
//        availableActions.clear();
//
//        // get the service locator for the selected registry
//        PreservationActionRegistryDefinition reg = (PreservationActionRegistryDefinition) registry;
// 
//        IPreservationActionRegistry serviceLocator = null;
//        try {
//            serviceLocator = PreservationActionRegistryFactory.getInstance(reg);
//        } catch (IllegalArgumentException e1) {
//            FacesMessages.instance().add(
//                    FacesMessage.SEVERITY_INFO,
//                    "Registry:  " + reg.getShortname()
//                            + " has changed and needs to be reconfigured.");
//            log.error( "Registry:  " + reg.getShortname() + " has changed and needs to be reconfigured.");
//            return null;
//        }
//        try {
//            if (serviceLocator == null) {
//                FacesMessages.instance().add(FacesMessage.SEVERITY_ERROR,
//                        "Failed to access " + reg.getShortname());
//                log.error("Failed to access " + reg.getShortname());
//                return null;
//            }
//            // query the registry
//            List<PreservationActionDefinition> actions = serviceLocator
//                    .getAvailableActions(formatInfo);
//            if ((actions == null) || (actions.size() == 0))
//                // could not find a matching service - something went wrong
//                registryInfoMsg = serviceLocator.getLastInfo();
//            else {
//                /*
//                 * populate the list of available services
//                 */
//                for (PreservationActionDefinition definition : actions) {
//                    availableActions.add(definition);
//
//                }
//            }
//        } catch (PlatoServiceException e) {
//            FacesMessages.instance().add(FacesMessage.SEVERITY_ERROR,
//                    "Failed to look up services of: " + reg.getShortname() + ": " + e.getMessage());
//            log.error("Failed to look up services of: " + reg.getShortname() + ": " + e.getMessage(), e.getCause());
//        }
//
//        // this registry is responsible for the result - mark it as selected
//        for (PreservationActionRegistryDefinition r: registrySelection.keySet()) {
//            registrySelection.put(r, (registry == r) );
//        }
//        return null;
//    }

    /**
     * Creates an alternative for each selected preservation service
     * and adds it to the list of alternatives.
     */
    public String createAlternativesForPreservationActions() {
        availableActions.size();
        /*
         * mark project as changed so the user has to save or discard the
         * project before exporting
         */
        changed = "T";

        for (PreservationActionDefinition action : availableActions) {
            if (action.isSelected()) {
                /*
                 * Create a new alternative for this service
                 */
                String uniqueName = selectedPlan.getAlternativesDefinition().createUniqueName(action.getShortname());
                Alternative a = Alternative.createAlternative(uniqueName, action);
               
                // and add it to the preservation planning project
                selectedPlan.getAlternativesDefinition().addAlternative(a);
            }
        }

        // refresh the datamodel list
        alternativeList = selectedPlan.getAlternativesDefinition()
                .getAlternatives();
        // the alternativesdefinition has been changed
        selectedPlan.getAlternativesDefinition().touch();

        return null;
    }

    @Override
    @RaiseEvent("reload")
    public String discard() {
        String result = super.discard();
        init();
        return result;
    }

    @Destroy
    @Remove
    public void destroy() {
    }

    public int getAllowRemove() {
        return allowRemove;
    }
}
TOP

Related Classes of eu.planets_project.pp.plato.action.workflow.DefineAlternativesAction

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.