eu.planets_project.tb.impl.services.mockups.workflow.IdentifyWorkflow.java Source code

Java tutorial

Introduction

Here is the source code for eu.planets_project.tb.impl.services.mockups.workflow.IdentifyWorkflow.java

Source

/*******************************************************************************
 * Copyright (c) 2007, 2010 The Planets Project Partners.
 *
 * 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.tb.impl.services.mockups.workflow;

import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Vector;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import eu.planets_project.services.datatypes.DigitalObject;
import eu.planets_project.services.datatypes.DigitalObjectContent;
import eu.planets_project.services.datatypes.ServiceReport;
import eu.planets_project.services.datatypes.ServiceReport.Status;
import eu.planets_project.services.datatypes.ServiceReport.Type;
import eu.planets_project.services.identify.Identify;
import eu.planets_project.services.identify.IdentifyResult;
import eu.planets_project.tb.gui.backing.exp.ExperimentStageBean;
import eu.planets_project.tb.impl.model.eval.mockup.TecRegMockup;
import eu.planets_project.tb.impl.model.exec.ExecutionStageRecordImpl;
import eu.planets_project.tb.impl.model.measure.MeasurementImpl;
import eu.planets_project.tb.impl.model.measure.MeasurementTarget;
import eu.planets_project.tb.impl.services.wrappers.IdentifyWrapper;

/**
 * This is the class that carries the code specific to invoking an Identify experiment.
 * 
 * @author <a href="mailto:Andrew.Jackson@bl.uk">Andy Jackson</a>
 *
 */
public class IdentifyWorkflow implements ExperimentWorkflow {
    @SuppressWarnings("unused")
    private static Log log = LogFactory.getLog(IdentifyWorkflow.class);

    /** External property keys */
    public static final String PARAM_SERVICE = "identify.service";

    /** Internal keys for easy referral to the service+stage combinations. */
    public static final String STAGE_IDENTIFY = "Identify";

    /** Observable properties for this service type */
    public static MeasurementImpl MEASURE_IDENTIFY_FORMAT;
    public static MeasurementImpl MEASURE_IDENTIFY_METHOD;

    /* (non-Javadoc)
     * @see eu.planets_project.tb.impl.services.mockups.workflow.ExperimentWorkflow#getStages()
     */
    public List<ExperimentStageBean> getStages() {
        List<ExperimentStageBean> stages = new Vector<ExperimentStageBean>();
        stages.add(new ExperimentStageBean(STAGE_IDENTIFY, "Identify a digital object."));
        return stages;
    }

    private static HashMap<String, List<MeasurementImpl>> manualObservables;
    /** Statically define the observable properties. FIXME Should be built from the TechReg */
    private static HashMap<String, List<MeasurementImpl>> observables;
    static {

        // Set up properties:
        MEASURE_IDENTIFY_FORMAT = TecRegMockup.getObservable(TecRegMockup.PROP_DO_FORMAT);
        MEASURE_IDENTIFY_METHOD = MeasurementImpl.create(TecRegMockup.PROP_SERVICE_IDENTIFY_METHOD,
                "The identification method.", "", "The method the service used to identify the digital object.",
                null, MeasurementTarget.SERVICE_TARGET);

        // Now set up the hash:
        observables = new HashMap<String, List<MeasurementImpl>>();
        observables.put(STAGE_IDENTIFY, new Vector<MeasurementImpl>());
        // The service succeeded
        observables.get(STAGE_IDENTIFY)
                .add(TecRegMockup.getObservable(TecRegMockup.PROP_SERVICE_EXECUTION_SUCEEDED));
        // The service time
        observables.get(STAGE_IDENTIFY).add(TecRegMockup.getObservable(TecRegMockup.PROP_SERVICE_TIME));
        // The object size:
        observables.get(STAGE_IDENTIFY).add(TecRegMockup.getObservable(TecRegMockup.PROP_DO_SIZE));

        // The measured type:
        observables.get(STAGE_IDENTIFY).add(MEASURE_IDENTIFY_FORMAT);

        // The identification method employed by the service:
        observables.get(STAGE_IDENTIFY).add(MEASURE_IDENTIFY_METHOD);

        manualObservables = new HashMap<String, List<MeasurementImpl>>();
        manualObservables.put(STAGE_IDENTIFY, new Vector<MeasurementImpl>());

        /*
        observables.put( IDENTIFY_SUCCESS, 
            TecRegMockup.getObservable(TecRegMockup.PROP_SERVICE_EXECUTION_SUCEEDED, STAGE_IDENTIFY) );
        // The service time
        observables.put( IDENTIFY_SERVICE_TIME, 
            TecRegMockup.getObservable(TecRegMockup.PROP_SERVICE_TIME, STAGE_IDENTIFY) );
        // The object size:
        observables.put( IDENTIFY_DO_SIZE, 
            TecRegMockup.getObservable(TecRegMockup.PROP_DO_SIZE, STAGE_IDENTIFY) );
        // The measured type:
        observables.put( 
            IDENTIFY_FORMAT,
            new MeasurementImpl(
                    PROP_IDENTIFY_FORMAT, 
                    "The format of the Digital Object", "",
                    "The format of a Digital Object, specified as a Planets Format URI.", 
                    STAGE_IDENTIFY, null)
        );
            
        // The identification method employed by the service:
        observables.put( 
            IDENTIFY_METHOD,
            new MeasurementImpl(
                    PROP_IDENTIFY_METHOD, 
                    "The identification method.", "",
                    "The method the service used to identify the digital object.", 
                    STAGE_IDENTIFY, null)
        );
         */

    }

    /* ------------------------------------------------------------- */

    /** Parameters for the workflow execution etc */
    HashMap<String, String> parameters = new HashMap<String, String>();
    /** The holder for the identifier service. */
    Identify identifier = null;
    URL identifierEndpoint = null;

    /* ------------------------------------------------------------- */

    /* (non-Javadoc)
     * @see eu.planets_project.tb.impl.services.mockups.workflow.ExperimentWorkflow#getObservables()
     */
    public HashMap<String, List<MeasurementImpl>> getObservables() {
        return observables;
    }

    /* (non-Javadoc)
     * @see eu.planets_project.tb.impl.services.mockups.workflow.ExperimentWorkflow#getManualObservables()
     */
    public HashMap<String, List<MeasurementImpl>> getManualObservables() {
        return manualObservables;
    }

    /* (non-Javadoc)
     * @see eu.planets_project.tb.impl.services.mockups.workflow.ExperimentWorkflow#setParameters(java.util.HashMap)
     */
    public void setParameters(HashMap<String, String> parameters) throws Exception {
        this.parameters = parameters;
        // Attempt to connect to the Identify service.
        identifierEndpoint = new URL(this.parameters.get(PARAM_SERVICE));
        identifier = new IdentifyWrapper(identifierEndpoint);
    }

    public HashMap<String, String> getParameters() {
        return this.parameters;
    }

    /* (non-Javadoc)
     * @see eu.planets_project.tb.impl.services.mockups.workflow.ExperimentWorkflow#execute(eu.planets_project.services.datatypes.DigitalObject, java.util.HashMap)
     */
    public WorkflowResult execute(DigitalObject dob) {

        // Invoke the service, timing it along the way:
        boolean success = true;
        String exceptionReport = "";
        IdentifyResult identify = null;
        long msBefore = 0, msAfter = 0;
        msBefore = System.currentTimeMillis();
        try {
            identify = identifier.identify(dob, null);
        } catch (Exception e) {
            success = false;
            exceptionReport = "<p>Service Invocation Failed!<br/>" + e + "</p>";
        }
        msAfter = System.currentTimeMillis();

        // Now prepare the result:
        WorkflowResult wr = new WorkflowResult();

        // Record this one-stage experiment:
        ExecutionStageRecordImpl idStage = new ExecutionStageRecordImpl(null, STAGE_IDENTIFY);
        wr.getStages().add(idStage);

        // Record the endpoint of the service used for this stage.  FIXME Can this be done more automatically, from above?
        idStage.setEndpoint(identifierEndpoint);

        List<MeasurementImpl> recs = idStage.getMeasurements();
        recs.add(new MeasurementImpl(TecRegMockup.PROP_SERVICE_TIME, "" + ((msAfter - msBefore) / 1000.0)));

        // Now record
        try {
            if (success && identify.getTypes() != null && identify.getTypes().size() > 0) {
                recs.add(new MeasurementImpl(TecRegMockup.PROP_SERVICE_EXECUTION_SUCEEDED, "true"));
                collectIdentifyResults(recs, identify, dob);
                wr.logReport(identify.getReport());
                return wr;
            }
        } catch (Exception e) {
            exceptionReport += "<p>Failed with exception: " + e + "</p>";
        }

        // Build in a 'service failed' property.
        recs.add(new MeasurementImpl(TecRegMockup.PROP_SERVICE_EXECUTION_SUCEEDED, "false"));

        // Create a ServiceReport from the exception.
        // TODO can we distinguish tool and install error here?
        ServiceReport sr = new ServiceReport(Type.ERROR, Status.TOOL_ERROR, "No info");
        if (identify != null && identify.getReport() != null) {
            String info = identify.getReport().toString();
            sr = new ServiceReport(Type.ERROR, Status.TOOL_ERROR, info);
        }
        wr.logReport(sr);

        return wr;
    }

    public static void collectIdentifyResults(List<MeasurementImpl> recs, IdentifyResult ident, DigitalObject dob) {
        if (ident == null)
            return;
        if (ident.getTypes() != null) {
            for (URI format_uri : ident.getTypes()) {
                if (format_uri != null) {
                    recs.add(new MeasurementImpl(TecRegMockup.PROP_DO_FORMAT, format_uri.toString()));
                }
            }
        }
        if (ident.getMethod() != null) {
            recs.add(new MeasurementImpl(TecRegMockup.PROP_SERVICE_IDENTIFY_METHOD, ident.getMethod().name()));
        }
        // Store the size:
        recs.add(new MeasurementImpl(TecRegMockup.PROP_DO_SIZE, "" + getContentSize(dob)));
        return;
    }

    /*
     * Recursive method for computing the total size.
     * TODO A badly-formed DigitalObject could cause this method to recurse forever. Can that be stopped?
     */
    static long getContentSize(DigitalObject dob) {
        long bytes = 0;
        // Get the size at this level:
        if (dob.getContent() != null) {
            bytes += getSizeOfContent(dob.getContent());
        }
        // Return the total:
        return bytes;
    }

    /*
     * Attempts to determine the size of the content of a particular DigitalObject.
     */
    private static long getSizeOfContent(DigitalObjectContent con) {
        if (con == null)
            return 0;
        if (con.length() >= 0)
            return con.length();
        // Otherwise, read it to work out how big it is.
        try {
            // Note that this can be misleading, as the available bytes may be less than the total size.
            return con.getInputStream().available();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return 0;
    }

}