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

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

/*******************************************************************************
* 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.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

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.contexts.Contexts;
import org.jboss.seam.faces.FacesMessages;

import eu.planets_project.pp.plato.action.interfaces.IEvaluateExperiments;
import eu.planets_project.pp.plato.action.interfaces.ITransformMeasuredValues;
import eu.planets_project.pp.plato.action.interfaces.IWorkflowStep;
import eu.planets_project.pp.plato.bean.BooleanCapsule;
import eu.planets_project.pp.plato.evaluation.IActionEvaluator;
import eu.planets_project.pp.plato.evaluation.IObjectEvaluator;
import eu.planets_project.pp.plato.evaluation.IStatusListener;
import eu.planets_project.pp.plato.evaluation.MiniRED;
import eu.planets_project.pp.plato.model.Alternative;
import eu.planets_project.pp.plato.model.DigitalObject;
import eu.planets_project.pp.plato.model.EvaluationStatus;
import eu.planets_project.pp.plato.model.PlanState;
import eu.planets_project.pp.plato.model.SampleObject;
import eu.planets_project.pp.plato.model.Values;
import eu.planets_project.pp.plato.model.measurement.MeasurableProperty;
import eu.planets_project.pp.plato.model.tree.Leaf;
import eu.planets_project.pp.plato.model.tree.Node;
import eu.planets_project.pp.plato.model.tree.TreeNode;
import eu.planets_project.pp.plato.model.values.Value;
import eu.planets_project.pp.plato.services.characterisation.jhove.JHoveAdaptor;
import eu.planets_project.pp.plato.services.characterisation.jhove.tree.JHoveTree;
import eu.planets_project.pp.plato.util.MeasurementInfoUri;
import eu.planets_project.pp.plato.util.PlatoLogger;
import eu.planets_project.pp.plato.validators.INodeValidator;
import eu.planets_project.pp.plato.validators.ITreeValidator;
import eu.planets_project.pp.plato.validators.TreeValidator;

/**
* Implements actions for workflow step 'Evaluate Experiments', i.e. enable the user
* to enter the evaluation result per alternative and sample record. The user has to enter
* evaluation result for all leaves in the objective tree.
* @author Hannes Kulovits
*/
@Stateful
@Scope(ScopeType.SESSION)
@Name("evalexperiments")
@Cache(org.jboss.ejb3.cache.NoPassivationCache.class)
public class EvaluateExperimentsAction extends AbstractWorkflowStep implements
        IEvaluateExperiments, INodeValidator, IStatusListener{
    /**
     *
     */
    private static final long serialVersionUID = -3892845379219070784L;


    protected boolean needsClearEm() {
        return true;
    }
    private static final Log log = PlatoLogger.getLogger(EvaluateExperimentsAction.class);

    private StringBuffer evaluationLogBuffer;
   
    @In(create = true)
    ITransformMeasuredValues transform;


    @SuppressWarnings("unused")
    @Out(required=false)
    private JHoveTree jhoveTree1;
   
    @SuppressWarnings("unused")
    @Out(required=false)
    private JHoveTree jhoveTree2;
   
   
    /**
     * Creates from the SampleObject object, retrieved by injection, a Tree with all the
     * characteristics extracted from Jhove
     *
     */
    public JHoveTree characteriseJHove(DigitalObject object) {
        JHoveTree jhoveTree = new JHoveTree();
       
        //returns an empty tree for null
        if(object==null) {
            return jhoveTree;
        }

        if (object.getJhoveXMLString() == null || "".equals(object.getJhoveXMLString())) {
            object.setJhoveXMLString(new JHoveAdaptor().describe(object));
        }
        if(object.getJhoveXMLString()!=null && !"".equals(object.getJhoveXMLString())) {
            jhoveTree= new JHoveAdaptor().digestString(object.getFullname(),object.getJhoveXMLString());
        }
       
        return jhoveTree;
   

    /**
     * the node currently selected in the objective tree.
     */
    @In(required = false)
    @Out(required = false)
    TreeNode node;
   
   
    public EvaluateExperimentsAction() {
        requiredPlanState = new Integer(PlanState.EXPERIMENT_PERFORMED);
    }

    /**
     * List of all leaves for which the evaluation settings shall be displayed to the user.
     */
    @Out(required = false)
    @In(required = false)
    List<Leaf> leaves;
   
    @Out
    private List<MeasurableProperty> measurableProperties = new ArrayList<MeasurableProperty>();

    /**
     * Leaves displayed to the user.
     */
    @Out(required = false)
    @In(required=false)
    List<Leaf> errorleaves;

    @Out
    private BooleanCapsule hasAutomatedMeasurements = new BooleanCapsule();
   
    protected IWorkflowStep getSuccessor() {
        return transform;
    }

    /**
     * initialises the values in the tree and inits/clears the leaf list
     * @see AbstractWorkflowStep#init()
     */
    public void init() {
        clearLogBuffer();
        initLeafLists();
        boolean xcl =  false;
        hasAutomatedMeasurements.setBool(false);
        Iterator<Leaf> iter = selectedPlan.getTree().getRoot().getAllLeaves().iterator();
        while (iter.hasNext()) {
            Leaf l = iter.next();
            if (l.isMapped()) {
                hasAutomatedMeasurements.setBool(true);
               
                if (l.getMeasurementInfo().getProperty().getName().startsWith("xcl/")) {
                    xcl = true;
                }
            }
        }
        if (xcl)  {
            for (DigitalObject o : selectedPlan.getSampleRecordsDefinition().getRecords()) {
                if ((o.getXcdlDescription() == null)|| !o.getXcdlDescription().isDataExistent()) {
                        FacesMessages.instance().add(FacesMessage.SEVERITY_INFO,
                           "Some XCL descriptions for samples are missing, XCL comparison will not work for these samples. ");
                        break;
                }
            }
            for (Alternative a: selectedPlan.getAlternativesDefinition().getAlternatives()) {
                for (DigitalObject r: a.getExperiment().getResults().values()) {
                    if ((r.getXcdlDescription() == null)|| !r.getXcdlDescription().isDataExistent()) {
                        FacesMessages.instance().add(FacesMessage.SEVERITY_INFO,
                           "XCL descriptions for experiment results of "+ a.getName()  +" are missing, " +
                           "XCL comparison will not work for these objects. ");
                        break;
                    }
                }
            }
        }
       
        // TODO for now this is ALWAYS reloaded when entering,
        // but should be cached in the future.
        MiniRED.getInstance().reloadEvaluators();        
        refreshMeasurableProperties();
       
    }

    private void clearLogBuffer() {
        evaluationLogBuffer = new StringBuffer();
        Contexts.getEventContext().remove("evaluationMessage");
    }

    /**
     * @param record sample object the alternative has been carried out on
     * @param alternative alternative which has been carried out on the alternative (we determine the result object from the alternative)
     */
    public void setTreeFromRecordAltern(Object record, Object alternative){
       
        if (!(record instanceof SampleObject) || !(alternative instanceof Alternative)) {
            return;
        }
       
        Alternative a = (Alternative)alternative;
        SampleObject o = (SampleObject)record;
       
        o = em.merge(o);
        jhoveTree1=characteriseJHove(o);
       
        // get the result
        // we have to merge the sample object back into the session to be able to access the byte stream
        DigitalObject result = em.merge(a.getExperiment().getResults().get(record));
        a.getExperiment().getResults().put(o, result);
       
        jhoveTree2=characteriseJHove(result);    
    }
   
    /**
     * Select a node or leaf from the tree.
     */
    public String select(Object ob) {
        initErrorLeaves();
        log.trace("Select Called with: " + ob.toString());
        if (ob instanceof Node) {
            log.debug("Setting all Leaves");
            leaves = ((Node) ob).getAllLeaves();
        } else if (ob instanceof Leaf) {
            log.debug("Setting leaf: " + ob.toString());
            leaves.clear();
            leaves.add((Leaf) ob);
        }
        return null;
    }

    /**
     * @see AbstractWorkflowStep#discard()
     */
    @Override
    @RaiseEvent("reload")
    public String discard() {
        String result = super.discard();
        init();
        return result;
    }

    /**
     * @see AbstractWorkflowStep#destroy()
     */
    @Destroy
    @Remove
    public void destroy() {
    }

    /**
     * @see eu.planets_project.pp.plato.action.workflow.AbstractWorkflowStep#validate()
     */
    public boolean validate(boolean showValidationErrors) {
        ITreeValidator validator = new TreeValidator();
        List<TreeNode> nodes = new ArrayList<TreeNode>();
        boolean valid = validator.validate(selectedPlan.getTree().getRoot(),
                this, nodes, showValidationErrors);
        if (!valid) {
            if (leaves == null) {
                leaves = new ArrayList<Leaf>();
            } else {
                leaves.clear();
            }
            //All invalid leaves should be in the list so that they are displayed
            for (TreeNode node : nodes) {
                if (node.isLeaf()) {
                    this.leaves.add((Leaf) node);
                }
            }
        }
        return valid;
    }

    /**
     * @see eu.planets_project.pp.plato.util.INodeValidator#validateNode(eu.planets_project.pp.plato.model.TreeNode, java.util.List, java.util.List)
     */
    public boolean validateNode(TreeNode node, List<String> nodelist,
            List<TreeNode> nodes) {
        return node.isCompletelyEvaluated(nodelist, nodes, selectedPlan.getAlternativesDefinition().getConsideredAlternatives());
    }

    /**
     * We have the rule that all evaluation settings have to be either changed or confirmed once
     * by the user.
     * This approve function makes it easier to confirm the settings for many leaves at once -
     * It touches all currently displayed leaves so that they are marked as confirmed.
     * @see eu.planets_project.pp.plato.model.values.Value#touch()
     */
    public void approve() {
        for (Leaf leaf : leaves) {
            for (Values values : leaf.getValueMap().values()) {
                for (Value value : values.getList()) {
                    value.touch();
                }
            }
        }
    }

    /**
     * @see AbstractWorkflowStep#getWorkflowstepName()
     */
    protected String getWorkflowstepName() {
        return "evalexperiments";
    }



    /**
     * evaluates the given leaves automatically.
     * This is only possible for criteria, where information on the measurement has been defined.
     * The registered evaluators are applied one after an other,
     * if an evaluator is able to measure a criterion, its value is applied and the criterion is excluded from further evaluation.
     *
     * First per alternative all action related evaluators are called.
     *
     * Then per alternative, for each sample object, all object/runtime related evaluators are called.
     *
     * @param leaves
     */
    private void evaluateLeaves(List<Leaf> leaves) {
        clearLogBuffer();

        // we evaluate measurements and have to assign each result to the corresponding leaf: build a map
        HashMap<MeasurementInfoUri, Leaf> measurementOfLeaf = new HashMap<MeasurementInfoUri, Leaf>();

        // list of measurements which shall be evaluated
        List<MeasurementInfoUri> allMeasurementsToEval = new LinkedList<MeasurementInfoUri>();

        for(Leaf l : leaves) {
            // measure this criterion automatically
            MeasurementInfoUri m = l.getMeasurementInfo().toMeasurementInfoUri();
            if ((m != null) && (m.getAsURI() != null)) {
                measurementOfLeaf.put(m , l);
               allMeasurementsToEval.add(m);
            }
        }           

        try {
            // start evaluation:
            List<MeasurementInfoUri> measurementsToEval = new ArrayList<MeasurementInfoUri>();
            // first action evaluators 
            List<IActionEvaluator> actionEvaluators = MiniRED.getInstance().getActionEvaluationSequence();
            for (Alternative alternative : selectedPlan.getAlternativesDefinition().getConsideredAlternatives()) {
                // we want to evaluate each property only once, by the evaluator with the highest priority
                measurementsToEval.clear();
                measurementsToEval.addAll(allMeasurementsToEval);
                for (IActionEvaluator evaluator : actionEvaluators) {
                    Map<MeasurementInfoUri, Value> results = evaluator.evaluate(alternative, measurementsToEval, this);
                    // apply all results
                    for (MeasurementInfoUri m : results.keySet()) {
                        Value value = results.get(m);
                        if (value != null) {
                            Leaf l = measurementOfLeaf.get(m);
                            value.setScale(l.getScale());
                            l.getValues(alternative.getName()).setValue(0,value);
                        }
                    }
                    // exclude evaluated leaves from further evaluation
                    measurementsToEval.removeAll(results.keySet());
                }
            }
            // then object evaluators
            List<IObjectEvaluator> objEvaluators = MiniRED.getInstance().getObjectEvaluationSequence();
            for (Alternative alternative : selectedPlan.getAlternativesDefinition().getConsideredAlternatives()) {
                // .. for all alternatives
                List<SampleObject> samples = selectedPlan.getSampleRecordsDefinition().getRecords();
                for (int i = 0; i < samples.size(); i++){
                    // we want to evaluate each property only once, by the evaluator with the highest priority
                    measurementsToEval.clear();
                    measurementsToEval.addAll(allMeasurementsToEval);
                   

                   
                    for (IObjectEvaluator evaluator : objEvaluators) {
                        DigitalObject r = alternative.getExperiment().getResults().get(samples.get(i));
                        DigitalObject r2 = (r == null ? null : em.merge(r));
                        try {
                            Map<MeasurementInfoUri, Value> results = evaluator.evaluate(
                                    alternative,
                                    em.merge(samples.get(i)),
                                    r2,
                                    measurementsToEval,
                                    this);
                            // apply all results
                            for (MeasurementInfoUri m : results.keySet()) {
                                Value value = results.get(m);
                                if (value != null) {
                                    Leaf l = measurementOfLeaf.get(m);
                                    value.setScale(l.getScale());
                                    // add evaluation result for the current result-object!
                                    l.getValues(alternative.getName()).setValue(i, value);
                                }
                            }
                            // exclude evaluated leaves from further evaluation
                            measurementsToEval.removeAll(results.keySet());
                        } catch (Exception e) {
                            log.error("evaluator failed" + e.getMessage(),e);
                            continue;
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("Automated evaluation threw exception "+e.getMessage(),e);
            FacesMessages.instance().add(FacesMessage.SEVERITY_ERROR, "Automated evaluation failed:"+ e.getMessage());
            updateStatus("Automated evaluation threw exception "+e.getMessage());
        }
        Contexts.getEventContext().set("evaluationMessage", evaluationLogBuffer.toString());
    }
    public void evaluateAll() {
        evaluateLeaves(selectedPlan.getTree().getRoot().getAllLeaves());
    }
    public void evaluate(Leaf leaf) {
        evaluateLeaves(Arrays.asList(leaf));
    }
   

    private void refreshMeasurableProperties() {
        measurableProperties.clear();
        measurableProperties.addAll(selectedPlan.getMeasurableProperties());
        for (MeasurableProperty p: measurableProperties) {
            log.debug("prop:: "+p.getName());
        }
    }

    public void updateStatus(String msg) {
        log.info(msg);
        evaluationLogBuffer.append(msg).append("\n");
    }
    @Override
    public String save() {
        // initialising the values for free text transformers
        for (Leaf l:selectedPlan.getTree().getRoot().getAllLeaves()) {
            l.initTransformer();
        }
        return super.save();
    }

    /**
     *
     */
    private void initErrorLeaves() {
        if(errorleaves == null){
            errorleaves = new ArrayList<Leaf>();
        } else  {
            errorleaves.clear();
        }
    }

    /**
     *
     */
    private void initLeafLists() {
        if(leaves == null){
            leaves = new ArrayList<Leaf>();
        } else {
            leaves.clear();
        }
        initErrorLeaves();
    }
   
}
TOP

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

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.