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

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

/*******************************************************************************
* 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.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
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.annotations.datamodel.DataModel;
import org.jboss.seam.annotations.datamodel.DataModelSelection;
import org.jboss.seam.faces.FacesMessages;

import eu.planets_project.pp.plato.action.interfaces.IEvaluateExperiments;
import eu.planets_project.pp.plato.action.interfaces.IRunExperiments;
import eu.planets_project.pp.plato.action.interfaces.IWorkflowStep;
import eu.planets_project.pp.plato.bean.BooleanCapsule;
import eu.planets_project.pp.plato.bean.ExperimentStatus;
import eu.planets_project.pp.plato.bean.PrepareChangesForPersist;
import eu.planets_project.pp.plato.model.Alternative;
import eu.planets_project.pp.plato.model.DetailedExperimentInfo;
import eu.planets_project.pp.plato.model.DigitalObject;
import eu.planets_project.pp.plato.model.Experiment;
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.XcdlDescription;
import eu.planets_project.pp.plato.model.measurement.MeasurableProperty;
import eu.planets_project.pp.plato.model.measurement.Measurement;
import eu.planets_project.pp.plato.model.values.FreeStringValue;
import eu.planets_project.pp.plato.model.values.Value;
import eu.planets_project.pp.plato.services.PlatoServiceException;
import eu.planets_project.pp.plato.services.action.IEmulationAction;
import eu.planets_project.pp.plato.services.action.IMigrationAction;
import eu.planets_project.pp.plato.services.action.IPreservationAction;
import eu.planets_project.pp.plato.services.action.MigrationResult;
import eu.planets_project.pp.plato.services.action.PreservationActionServiceFactory;
import eu.planets_project.pp.plato.services.characterisation.DROIDIntegration;
import eu.planets_project.pp.plato.services.characterisation.FormatIdentification;
import eu.planets_project.pp.plato.services.characterisation.FormatIdentification.FormatIdentificationResult;
import eu.planets_project.pp.plato.services.characterisation.fits.FitsIntegration;
import eu.planets_project.pp.plato.services.characterisation.jhove.JHoveAdaptor;
import eu.planets_project.pp.plato.services.characterisation.xcl.XcdlExtractor;
import eu.planets_project.pp.plato.util.Downloader;
import eu.planets_project.pp.plato.util.FileUtils;
import eu.planets_project.pp.plato.util.OS;
import eu.planets_project.pp.plato.util.PlatoLogger;

/**
* Implements actions for workflow step 'Run Experiments'
*
* Gives the user the opportunity to document the outcome of the experiments per alternative
* and upload the result file. Furthermore the user can run experiments based on action services.
*
* @author Hannes Kulovits
*/
@Stateful
@Scope(ScopeType.SESSION)
@Name("runexperiments")
@Cache(org.jboss.ejb3.cache.NoPassivationCache.class)
public class RunExperimentsAction extends AbstractWorkflowStep implements
        IRunExperiments {
   
    private static final long serialVersionUID = 4241837780040966155L;

    protected boolean needsClearEm() {
        return true;
    }

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

    @In(create = true)
    IEvaluateExperiments evalexperiments;

    @DataModel
    List<Alternative> consideredAlternatives;

    @DataModelSelection
    Alternative selectedAlternative;
   
    private JHoveAdaptor jHoveAdaptor;

    @Out(required = false)
    private DigitalObject up;

    /**
     * Indicates if browse field is displayed.
     */
    @Out(required = false)
    BooleanCapsule showUpload = new BooleanCapsule(false);

    @In (required=false)
    private User user;

    @Out
    private BooleanCapsule hasAutomatedExperiments = new BooleanCapsule();
   
    @Out
    private List<MeasurableProperty> measurableProperties = new ArrayList<MeasurableProperty>();
   
    @Out(required=false)
    Alternative emulationAlternative;
   
    private Map<DigitalObject, String> tempFiles = new HashMap<DigitalObject, String>();
    private File tempDir = null;  
   
    @In(required=false)
    @Out(required=false)
    private DetailedExperimentInfo selectedExperimentInfo;
   
    @In(required=false)
    @Out(required=false)
    private ExperimentStatus experimentStatus = new ExperimentStatus();

    private FitsIntegration fits;// = new FitsIntegration();

    public RunExperimentsAction() {
        requiredPlanState = new Integer(PlanState.EXPERIMENT_DEFINED);
    }

    /**
     * @see AbstractWorkflowStep#getSuccessor()
     */
    protected IWorkflowStep getSuccessor() {
        return evalexperiments;
    }

    /**
     * @see AbstractWorkflowStep#save()
     */
    public String save() {

        prepareAlternatives();

       
        // maybe some XCDLs have been added to the sample records, save them too
//        for (SampleObject r : selectedPlan.getSampleRecordsDefinition().getRecords()) {
//            prep.prepare(r);
//            em.persist(em.merge(r));
//        }
       
        prepareTempFileSaving();
       
//       
//        // save the bytestreams into the database -
//        // not directly through our digitalobjects, because
//        // then they would stay in memory, but rather
//        // through an extra "channel" so that they can be loaded lazily.
//        // hence the temporary variables and the merging.
//        for (DigitalObject o: tempFiles.keySet()) {
//            try {
//                File file = new File(tempFiles.get(o));
//                byte[] data = FileUtils.getBytesFromFile(file);
//               
//                // we get a merged instance of our DigitalObject to save the bytestream into the database.
//                // we do NOT want the bytestream to be in our loaded object instance, as this costs too much
//                // memory. Lazy loading will be able to re-load that bytestream into our loaded instance...
//                // hopefully :)
//                DigitalObject digitalObject = em.merge(o);
//               
//                digitalObject.getData().setData(data);
//               
//                em.persist(digitalObject);
//                o.setId(digitalObject.getId());
//               
//            } catch (IOException e) {
//                log.error(e);
//            }
//        }

        super.save(selectedPlan.getAlternativesDefinition());
        changed = "";
       
        selectedPlan.getTree().initValues(
                selectedPlan.getAlternativesDefinition().getConsideredAlternatives(),
                selectedPlan.getSampleRecordsDefinition().getRecords()
                        .size());
        super.save(selectedPlan.getTree());

        doClearEm();
        init();
        return null;
    }

    public void prepareTempFileSaving() {
        for (Alternative a: selectedPlan.getAlternativesDefinition().getConsideredAlternatives()) {
            for (SampleObject so: selectedPlan.getSampleRecordsDefinition().getRecords()) {
                DigitalObject result = a.getExperiment().getResults().get(so);
                if (tempFiles.containsKey(result)) {
                    try {
                        File file = new File(tempFiles.get(result));
                        byte[] data = FileUtils.getBytesFromFile(file);
                        DigitalObject storedResult = em.merge(result);
                        storedResult.getData().setData(data);
                        a.getExperiment().getResults().put(so,storedResult);
                    } catch (IOException e) {
                        log.error(e);
                    }
                }
            }
        }
    }

    public void prepareAlternatives() {
        /** dont forget to prepare changed entities e.g. set current user */
        PrepareChangesForPersist prep = new PrepareChangesForPersist(user.getUsername());
        for (Alternative alt : selectedPlan.getAlternativesDefinition()
                .getAlternatives()) {
            prep.prepare(alt);
            //em.persist(em.merge(alt));
            // alternativesdefinition is saved further down
        }
    }
   
    protected void doClearEm() {
        OS.deleteDirectory(tempDir);
        tempFiles.clear();
        super.doClearEm();
    }

    /**
     * @see AbstractWorkflowStep#init()
     */
    public void init() {
        if (tempDir != null) {
            OS.deleteDirectory(tempDir);
        }
        tempDir = new File(OS.getTmpPath() + "digitalobjects" + System.nanoTime());
        tempDir.mkdir();
        tempDir.deleteOnExit();
        tempFiles.clear();
        log.debug("using temp directory " + tempDir.getAbsolutePath());
       
        try {
            fits = new FitsIntegration();
        } catch (Throwable e) {
            fits = null;
            log.error("Could not instantiate FITS, it is not configured properly.", e);
            FacesMessages.instance().add(FacesMessage.SEVERITY_WARN, "Could not instantiate FITS, it is not configured properly.");
        }
       
        consideredAlternatives = selectedPlan.getAlternativesDefinition()
                .getConsideredAlternatives();
        jHoveAdaptor=new JHoveAdaptor();

        // are there experiments which can be run automated?
        hasAutomatedExperiments.setBool(false);
        Iterator<Alternative> iter = consideredAlternatives.iterator();
        while (iter.hasNext() && !hasAutomatedExperiments.isBool()) {
            Alternative a = iter.next();
            if (a.isExecutable()) {
                hasAutomatedExperiments.setBool(true);
            }
        }

        // add empty result files where missing (only for considered alternatives!)
       
        List<SampleObject> allRecords = selectedPlan.getSampleRecordsDefinition().getRecords();
        for (Alternative alternative : consideredAlternatives) {
            Experiment exp = alternative.getExperiment();

            for (SampleObject record : allRecords) {
                DigitalObject u = exp.getResults().get(record);

                if (u == null) {
                    exp.addRecord(record)
                    u = exp.getResults().get(record);
                }
               
//                if (exp.getDetailedInfo().get(record) == null) {
//                   
//                    DetailedExperimentInfo detailedExperimentInfo = new DetailedExperimentInfo();
//                    detailedExperimentInfo.setSuccessful(true);
//                    exp.getDetailedInfo().put(record, detailedExperimentInfo);
//                }
            }
        }
        showUpload.setBool(false);
        refreshMeasurableProperties();       
    }
    private void refreshMeasurableProperties() {
        measurableProperties.clear();
        measurableProperties.addAll(selectedPlan.getMeasurableProperties());
        for (MeasurableProperty p: measurableProperties) {
            log.debug("prop:: "+p.getName());
        }
    }

    /**
     * @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 AbstractWorkflowStep#validate(boolean)
     */
    public boolean validate(boolean showValidationErrors) {
        return true;
    }

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

    /**
     * Adds an error message with {@link javax.faces.application.FacesMessage#SEVERITY_ERROR}
     * to FacesMessages.
     *
     * @param message error message
     */
    private void failure(String message) {
        FacesMessages.instance().add(FacesMessage.SEVERITY_ERROR,
                message);
        showUpload.setBool(false);
    }

    /**
     * Removes a result file from an alternative's experiment.
     *
     * @param object {@link eu.planets_project.pp.plato.model.SampleObject}
     */
    public void removeUpload(Object object) {
        log.debug("Object: " + object);
        if (object instanceof SampleObject) {
            SampleObject sample = (SampleObject) object;
            selectedAlternative.getExperiment().getResults().put(sample, new DigitalObject());
            log.debug("File in RunExperiment removed");
            showUpload.setBool(false);
        } else {
            failure("Couldn't remove upload");
        }
    }

    /**
     * Determines upload file to a specific sample record.
     *
     * @param object sample record
     */
    public void setUpload(Object object) {
        log.debug("Number: " + object);
        //log.debug("File in RunExperiment uploaded");
        if (object instanceof SampleObject) {
            SampleObject sample = (SampleObject) object;
            up = em.merge(selectedAlternative.getExperiment().getResults().get(sample));
            selectedAlternative.getExperiment().getResults().put(sample,up);
            if(up == null){
                failure("Couldn't start upload process");
            } else {
                showUpload.setBool(true);
            }
        } else {
            failure("Couldn't start upload process");
        }
    }
  
   
    public void upload() {
        saveTempFile(up, up);
        //characterise(up);
        characteriseFits(up);
        showUpload.setBool(false);
    }

    /**
     * Downloads the result file of a specific sample record.
     *
     * @param object sample record the user wants to download the result file.
     */
//    public void download(Object object) {
//        if (object instanceof SampleObject) {
//            SampleObject sample = (SampleObject) object;
//            up = selectedAlternative.getExperiment().getResults().get(sample);
//            if(up == null){
//                failure("Couldn't start download process");
//            }else{
//                if (tempFiles.containsKey(up)) {
//                    //download TEMPFILE
//                    Downloader.instance().download(up,tempFiles.get(up));
//                } else {
//                    // we have to merge it back into the session because we the data bytestream
//                    // is lazy loaded
//                    DigitalObject u = (DigitalObject)em.merge(up);
//                    Downloader.instance().download(u);
//                }
//            }
//        } else {
//            failure("Couldn't start download process");
//        }
//    }

    /**
     * Downloads the a digital object
     * @param object the object the user wants to download
     */
    public void download(Object object) {
        if (object == null) {
           failure("Couldn't start download process");
        }else{
            DigitalObject up = (DigitalObject)object;
            if (tempFiles.containsKey(up)) {
                //download TEMPFILE
                Downloader.instance().download(up,tempFiles.get(up));
            } else {
                // we have to merge it back into the session because we the data bytestream
                // is lazy loaded
                DigitalObject u = (DigitalObject)em.merge(up);
                Downloader.instance().download(u);
            }
        }
    }

   

    private void runSingle(Alternative a) {
        if (!a.isExecutable()) {
            // this alternative has to be evaluated manually, nothing to do here
            return;
        }

        IPreservationAction action =
            PreservationActionServiceFactory.getPreservationAction(a.getAction());

        // if the action is null the service isn't accessible (anymore)
        // we have to set an error message for each sample record
        if (action == null) {

            String msg = String.format("Preservation action %s - %s is not registered or accessible and cant be executed. (Please check the registry.)",
                    a.getAction().getShortname(), a.getAction().getInfo());


            setUniformProgramOutput(a, msg, false);
        }
        this.changed="T";
        // das sieht verd�chtig aus - pad wird auch geschrieben.
        // ABER die settings, die in pad eingetragen werden, brauchen wir nicht zum persistieren, sondern nur zum
        // ausf�hren der action - stehen ja in experiment.settings. daher ist es ok, dass wir die merged instance ver�ndern.
        PreservationActionDefinition pad = em.merge(a.getAction());
        pad.setExecute(a.getAction().isExecute());

        String settings = a.getExperiment().getSettings();
        pad.setParamByName("settings", settings);

        StringBuffer runDescription = new StringBuffer();

        if (action instanceof IMigrationAction) {
            DigitalObject migrationResultObject;
            DigitalObject experimentResultObject;
            MigrationResult migrationResult = null;
            IMigrationAction migrationAction = (IMigrationAction) action;
            //                int nextIndex = experimentStatus.getNextSampleIndex();
            SampleObject record = experimentStatus.getNextSample(); //null;
            //                if (nextIndex >= 0 && nextIndex < selectedPlan.getSampleRecordsDefinition().getRecords().size()) {
            //                    record = selectedPlan.getSampleRecordsDefinition().getRecords().get(nextIndex);
            //                }
            //experimentStatus.getNextSample();
            while (record != null) {
                if (record.isDataExistent()) {

                    // objectTomigrate is only being read, needs to be merged to lazily get the data out
                    SampleObject objectToMigrate = em.merge(record);

                    try {
                        // ACTION HAPPENS HERE:
                        migrationResult =  migrationAction.migrate(pad, objectToMigrate);
                    } catch (NullPointerException npe) {
                        log.error("Caught nullpointer exception when running a migration tool. ### WRONG CONFIGURATION? ###",npe);
                    } catch (Throwable t) {
                        log.error("Caught unchecked exception when running a migration tool: "+t.getMessage(),t);
                        //throw new PlatoServiceException("Could not run service "+a.getName()+" on object "+record.getShortName(),t);
                    }

                    if (migrationResult != null) {

                        if (migrationResult.isSuccessful() && migrationResult.getMigratedObject() != null) {
                           
                            experimentResultObject = a.getExperiment().getResults().get(record);
                            migrationResultObject = migrationResult.getMigratedObject();
                            experimentResultObject.setContentType(migrationResultObject.getContentType());
                            experimentResultObject.getFormatInfo().assignValues(migrationResultObject.getFormatInfo());

                            int size = saveTempFile(experimentResultObject,migrationResultObject);
                            experimentResultObject.getData().setSize(size);
                            experimentResultObject.setFullname(migrationResultObject.getFullname());

                            characterise(experimentResultObject);
                            characteriseFits(experimentResultObject);
                            experimentResultObject.setJhoveXMLString(jHoveAdaptor.describe(tempFiles.get(experimentResultObject)));
                        }

                        // set detailed infos depending on migration result
                        extractDetailedInfos(a.getExperiment(), record, migrationResult);

                    } else {
                        DetailedExperimentInfo info = a.getExperiment().getDetailedInfo().get(record);
                        if (info == null) {
                            info = new DetailedExperimentInfo();
                            a.getExperiment().getDetailedInfo().put(record,info);
                        }
                        info.setProgramOutput(
                                String.format("Applying action %s to sample %s failed.",
                                        a.getAction().getShortname(),
                                        record.getFullname()));
                    }
                }
                record = experimentStatus.getNextSample();
            }
        }

        refreshMeasurableProperties();       
    }
   
    public void characterise(DigitalObject dobject) {
        //characteriseFits(dobject);
       
       
        /**
         * DROID is used for file identification.
         */
        FormatIdentification ident = null;
       
        String filename = tempFiles.get(dobject);
       
        if (filename == null || "".equals(filename)) {
            DigitalObject o2 = em.merge(dobject);
            try {
                ident = DROIDIntegration.getInstance().identifyFormat(
                        o2.getData().getData(),
                        o2.getFullname());
            } catch (Exception e) {
                log.error(e.getMessage(),e);
            }   
        } else {
            ident = DROIDIntegration.getInstance().identify(filename);
        }
       
        if (ident == null)  {
            return;
        }
        if (ident.getResult() == FormatIdentificationResult.ERROR) {
            /*
             * DROID could not identify this file.
             */
            log.error("DROID could not identify the format of the file." + ident.getInfo());
        } else if (ident.getResult() == FormatIdentificationResult.NOHIT) {
            /*
             * DROID could not identify this file.
             */
            log.info("DROID did not get a hit identifying the file. "+ident.getInfo());
        } else if ((ident.getResult() == FormatIdentificationResult.POSITIVE)){
            /*
             *  match, format identification successful:
             *  if it is a multiple match, we simply take the first one here.
             */
            dobject.getFormatInfo().assignValues(ident.getFormatHits().get(0).getFormat());
            dobject.touch();
        }
        }
   
    /**
     * Processes an experiment.
     *
     * @param alt alternative which in this case is a preservation action.
     */
    public void run(Object alt) {
        if (! (alt instanceof Alternative)) {
            return;
        }
        if (experimentStatus == null)  {
         experimentStatus = new ExperimentStatus();
        }
        experimentStatus.experimentSetup(Arrays.asList((Alternative)alt), selectedPlan.getSampleRecordsDefinition().getRecords());
    }
    /**
     * Runs experiments of all considered alternatives.
     *
     */
    public void runAllExperiments(){
        if (experimentStatus == null)  {
            experimentStatus = new ExperimentStatus();
           }
        experimentStatus.experimentSetup(consideredAlternatives, selectedPlan.getSampleRecordsDefinition().getRecords());
    }
   
    /**
     * runs all experiments scheduled in experimentStatus
     */
    public void startExperiments() {
        if (experimentStatus == null)  {
            experimentStatus = new ExperimentStatus();
           }
        Alternative alt = experimentStatus.getNextAlternative();
        while ((alt != null)&&(! experimentStatus.isCanceled())) {
            runSingle(alt);
            alt = experimentStatus.getNextAlternative();
        }
        System.gc();
    }

    /**
     * for the given alternative the program output of all experiment infos is set to <param>msg</param>.
     * 
     */
    private void setUniformProgramOutput(Alternative a, String msg, boolean successful) {
        List<SampleObject> sampleObjects = selectedPlan.getSampleRecordsDefinition().getRecords();
        for (SampleObject o : sampleObjects) {
            DetailedExperimentInfo info = a.getExperiment().getDetailedInfo().get(o);
           
            if (info == null) {
                info = new DetailedExperimentInfo();
                a.getExperiment().getDetailedInfo().put(o, info);
            }
           
            info.setProgramOutput(msg);
            info.setSuccessful(successful);
        }
    }

    /**
     *
     * @param migratedObject the object that shall be used as KEY for storing the result bytestream
     * @param resultObject the object that contains the actual bytestream to be stored
     * @return the size of the bytestream
     */
    private int saveTempFile(DigitalObject migratedObject,
            DigitalObject resultObject) {
        String tempFileName = tempDir.getAbsolutePath()+"/"+System.nanoTime();
        OutputStream fileStream;
        try {
            fileStream = new  BufferedOutputStream (new FileOutputStream(tempFileName));
            byte[] data = resultObject.getData().getData();
            fileStream.write(data);
            fileStream.close();
            tempFiles.put(migratedObject, tempFileName);
            return data.length;
        } catch (FileNotFoundException e) {
            log.error(e);
        } catch (IOException e) {
            log.error(e);
        }
        return 0;
    }

    /**
     * stores {@link MigrationResult migration results} for the given sample object in {@link DetailedExperimentInfo experiment info} of experiment <param>e</param>.
     */
    private void extractDetailedInfos(Experiment e, SampleObject rec, MigrationResult r) {
        DetailedExperimentInfo info = e.getDetailedInfo().get(rec);
        // remove previous results
        if (info != null) {
            info.getMeasurements().clear();
        } else {
            info = new DetailedExperimentInfo();
            e.getDetailedInfo().put(rec, info);
        }
        if (r == null) {
            // nothing to add
            return;
        }
        // write info of migration result to experiment's detailedInfo
        info.getMeasurements().putAll(r.getMeasurements());
        info.setSuccessful(r.isSuccessful());
       
        if (r.getReport() == null) {
            info.setProgramOutput("The tool didn't provide any output.");
        } else {
            info.setProgramOutput(r.getReport());
        }
       
        int sizeMigratedObject = (r.getMigratedObject() == null || r.getMigratedObject().getData() == null) ? 0 : r.getMigratedObject().getData().getSize();
       
        // if the executing programme claims to have migrated the object, but the result file has size 0 than something must have
        // gone wrong. so we set the migration result to 'false' and add some text to the program output.
        if (r.isSuccessful() && sizeMigratedObject == 0) {
           info.setSuccessful(false);
           String programOutput = info.getProgramOutput();
          
           programOutput += "\nSomething went wrong during migration. No result file has been generated.";
          
           info.setProgramOutput(programOutput);
        }
    }
   

   
    /**
     * Extracts object properties of all experiment results.
     */
    public void extractObjectProperties(){
        List<SampleObject> records = selectedPlan.getSampleRecordsDefinition().getRecords();
        XcdlExtractor extractor = new XcdlExtractor();
       
        boolean missingResultfiles = false;
        ArrayList<String> failed = new ArrayList<String>();
       
        for(Alternative alt : consideredAlternatives) {
            for (SampleObject record : records) {
                // each experiment has one experiment result per sample record
                DigitalObject result = alt.getExperiment().getResults().get(record);
               
                XcdlDescription xcdl = null;
                if ((result != null)&&(result.isDataExistent())) {
                    try {
                        String filepath = tempFiles.get(result);
                        if ((filepath != null) && (!"".equals(filepath))) {
                            xcdl = extractor.extractProperties(result.getFullname(), filepath);
                        } else {
                            // we have to merge it back into the session because we the data bytestream
                            // is lazy loaded
                            DigitalObject u = (DigitalObject)em.merge(result);
                            xcdl = extractor.extractProperties(u);
                            // Should we call System.gc afterwards?
                        }
                        // there should be a file now
                        if (xcdl == null) {
                            failed.add(alt.getName()+ ", " + record.getFullname() + ": The description service returned an empty result.");
                        }                                              
                    } catch (PlatoServiceException e) {
                        failed.add(alt.getName()+ ", " + record.getFullname() + ": " + e.getMessage());
                    }
                } else {
                    if (record.isDataExistent()) {
                        // The sample record has values, so there should be some result files
                        missingResultfiles = true;                       
                    }
                }
                result.setXcdlDescription(xcdl);
            }
        }
        if (missingResultfiles) {
            FacesMessages.instance().add(FacesMessage.SEVERITY_INFO, "Some result files could not be described, because they are missing. Please upload them first.");           
        }
        if (failed.size() > 0) {
            StringBuffer msg = new StringBuffer();
            msg.append("Description failed for following result files:<br/><br/>");
            msg.append("<ul>");
            for (String f : failed) {
                msg.append("<li>").append(f).append("</li>");
            }
            msg.append("</ul>");
           
            FacesMessages.instance().add(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Some result files could not be decribed successfully.", msg.toString()));
        }
        if ((!missingResultfiles)&&(failed.size() == 0)) {
            FacesMessages.instance().add(FacesMessage.SEVERITY_INFO, "Successfully described all result files.");
        }
       
    }
    public void selectEmulationAlternative(Object alt){
        emulationAlternative = (Alternative)alt;
    }
    public void runEmulation(Object rec){
        if (rec instanceof SampleObject) {
            SampleObject sample = (SampleObject)rec;
            Alternative a = emulationAlternative;
            if (!a.isExecutable()) {
                // this alternative has to be evaluated manually, nothing to do here
                return;
            }
            IPreservationAction action =
                PreservationActionServiceFactory.getPreservationAction(a.getAction());
            /*
             * clear old run description
             */
            if (action == null) {
               
                String msg = String.format("Preservation action %s - %s is not registered or accessible and cant be executed. (Please check the registry.)",
                        a.getAction().getShortname(), a.getAction().getInfo());
               
                setUniformProgramOutput(a, msg, false);
            }
           
            if (action instanceof IEmulationAction) {
//              GRATE does only work on files up to 2.88 MB in size
//                if (sample.getData().getSize() > (1024 * 1024 * 2.8)) {
//                    FacesMessages.instance().add(FacesMessage.SEVERITY_WARN,
//                            "Emulation actions are currently only supported on samples up to a size of 2,88 MB.");
//                    return;
//                }
                try {
                   
                    DetailedExperimentInfo info = a.getExperiment().getDetailedInfo().get(sample);
                    String sessionID = null;
                    if (info == null) {
                        info = new DetailedExperimentInfo();                           
                        a.getExperiment().getDetailedInfo().put(sample, info);
                    } else {
                        Value sid = info.getMeasurements().get("sessionid").getValue();
                        if (sid != null && (sid instanceof FreeStringValue)) {
                       //     sessionID = ((FreeStringValue)sid).getValue();
                        }
                    }
                   
                    // objectTomigrate is only being read, needs to be merged to lazily get the data out
                    SampleObject objectToView = em.merge(sample);
                   
                    byte[] b = objectToView.getData().getData();
                   
                    if (sessionID == null) {
                        sessionID = ((IEmulationAction)action).startSession(a.getAction(), objectToView);
                    }
                    a.getExperiment().getDetailedInfo().get(sample).setSuccessful(true);
                    // we cannot use SETTINGS here because settings are not PER SAMPLE OBJECT!
                    info.getMeasurements().put("sessionid", new Measurement("sessionID",sessionID));
                } catch (PlatoServiceException e) {
                    String errorMsg = "Could not start emulation service." + e.getMessage();
                    setUniformProgramOutput(a, errorMsg, false);
                    FacesMessages.instance().add(FacesMessage.SEVERITY_ERROR,
                            "Could not start emulation service." + e.getMessage());
                    log.error("Could not start emulation service." + e.getMessage() + ": ", e.getCause());
                }
            }
        }
    }
   
    /**
     * ensures that there is a detaild experiment info per sample object
     */
    public void updateSelectedExperimentInfo(Object alternative, Object sampleObject) {
       
        Alternative a = (Alternative)alternative;
        SampleObject so = (SampleObject)sampleObject;
       
        DetailedExperimentInfo info = a.getExperiment().getDetailedInfo().get(sampleObject);
       
        if (info == null) {
            info = new DetailedExperimentInfo();
            a.getExperiment().getDetailedInfo().put(so, info);
        }
       
        this.selectedExperimentInfo = info;

        if (this.selectedExperimentInfo.getProgramOutput() == null) {
            this.selectedExperimentInfo.setProgramOutput("");
        }       
    }
  
    public void saveDetailedExperimentInfo() {
        // nothing to do here
    }

    /**
     * @param object
     * @return null
     */
    public String characteriseFits(Object object) {
        if (fits == null) {
            log.debug("FITS is not available and needs to be reconfigured.");
            return null;
        }
        if(object instanceof DigitalObject){
            DigitalObject dObject = (DigitalObject)object;
            if (dObject != null && dObject.isDataExistent()) {
                try {
                    String fitsXML = null;
                    String filepath =  tempFiles.get(dObject);
                    if ((filepath != null) && (!"".equals(filepath))) {
                        fitsXML = fits.characterise(new File(filepath));
                    } else {
                        DigitalObject mergedObj = em.merge(dObject);
                        saveTempFile(mergedObj, dObject);
                        filepath =  tempFiles.get(dObject);
                        fitsXML = fits.characterise(new File(filepath));
                    }
                    dObject.setFitsXMLString(fitsXML);
                } catch (PlatoServiceException e) {
                    log.error("characterisation with FITS failed.",e);
                    return null;
                }
            }
        }
   
        return null;
    }
   
}
TOP

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

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.