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

Java tutorial

Introduction

Here is the source code for eu.planets_project.tb.impl.services.mockups.workflow.WorkflowDroidXCDLExtractorComparator.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.File;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.Arrays;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.namespace.QName;
import javax.xml.ws.Service;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;

import eu.planets_project.services.PlanetsException;
import eu.planets_project.services.PlanetsServices;
import eu.planets_project.services.compare.Compare;
import eu.planets_project.services.datatypes.Content;
import eu.planets_project.services.datatypes.DigitalObject;
import eu.planets_project.services.datatypes.Property;
import eu.planets_project.services.identify.Identify;
import eu.planets_project.services.identify.IdentifyResult;
import eu.planets_project.services.migrate.Migrate;
import eu.planets_project.tb.api.model.eval.EvaluationExecutable;
import eu.planets_project.tb.api.services.mockups.workflow.Workflow;
import eu.planets_project.tb.impl.model.eval.EvaluationExecutableImpl;

/**
 * @author lindleyA
 * This mockup implements the following scenario:
 * In-->Takes two files as input
 * a) identify using Droid: to analyze a given file and to extract it's pronom Id(s)
 * b) extract using XCDL Extractor: to extract it's XCDL representation (if it is supported)
 * c) compare using XCDL Comparator: compares the two XCDL descriptions.
 * Out<--returns the comparator's responds 
 * 
 * It is fully functional in terms of service execution
 * Due to the abstinence of a technical registry, the logic of pronom ID mapping to XCEL selection 
 * is currently provided within this workflow.
 * At the moment TIFF and PNG are supported
 * 
 * It however does not follow the Planets (IF) patterns of designing workflows and
 * therefore is marked as mockup
 *
 */
@Deprecated
public class WorkflowDroidXCDLExtractorComparator implements Workflow {

    private static final String URL_DROID = "http://localhost:8080/pserv-pc-droid/Droid?wsdl";
    //private static final String URL_XCDLEXTRACTOR = "http://localhost:8080/pserv-pc-extractor/Extractor2Binary?wsdl";
    private static final String URL_XCDLEXTRACTOR = "http://planetarium.hki.uni-koeln.de:8080/pserv-pc-extractor/Extractor2Binary?wsdl";
    private static final String URL_XCDLCOMPARATOR = "http://localhost:8080/pserv-pp-comparator/ComparatorBasicCompareTwoXcdlValues?wsdl";

    //the new extractor interface does not require to hand over the xcel anymore
    //private static final String PATH_TO_xcel_tiff = "Planets_XCEL_Exctractor/res/xcl/xcel/xcel_docs/xcel_tiff.xml";
    //private static final String PATH_TO_xcel_png = "Planets_XCEL_Exctractor/res/xcl/xcel/xcel_docs/xcel_png.xml";

    enum supportedTypes {
        TIFF(new String[] { "info:pronom/fmt/7", "info:pronom/fmt/8", "info:pronom/fmt/9", "info:pronom/fmt/10",
                "info:pronom/fmt/152", "info:pronom/fmt/153", "info:pronom/fmt/154", "info:pronom/fmt/155",
                "info:pronom/fmt/156", "info:pronom/x-fmt/387", "info:pronom/x-fmt/388",
                "info:pronom/x-fmt/399" }/*,PATH_TO_xcel_tiff*/), PNG(
                        new String[] { "info:pronom/fmt/11", "info:pronom/fmt/12",
                                "info:pronom/fmt/13" }/*,PATH_TO_xcel_png*/), JPEG(
                                        new String[] { "info:pronom/fmt/41", "info:pronom/fmt/42",
                                                "info:pronom/fmt/43", "info:pronom/fmt/44", "info:pronom/fmt/112",
                                                "info:pronom/fmt/149", "info:pronom/x-fmt/390",
                                                "info:pronom/x-fmt/391",
                                                "info:pronom/x-fmt/398" }/*,PATH_TO_xcel_jpeg*/), GIF(
                                                        new String[] { "info:pronom/fmt/3",
                                                                "info:pronom/fmt/4" }/*,PATH_TO_xcel_gif*/), BMP(
                                                                        new String[] { "info:pronom/fmt/114",
                                                                                "info:pronom/fmt/115",
                                                                                "info:pronom/fmt/116",
                                                                                "info:pronom/fmt/117",
                                                                                "info:pronom/fmt/118",
                                                                                "info:pronom/fmt/119",
                                                                                "info:pronom/x-fmt/25",
                                                                                "info:pronom/x-fmt/270" }/*,PATH_TO_xcel_bmp*/);
        private String[] idsForType;
        //private String xcelPath;

        supportedTypes(String[] ids /*, String xcelPath*/) {
            this.idsForType = ids;
            //this.xcelPath = xcelPath;
        }

        public String[] pronomIDs() {
            return this.idsForType;
        }

        /*public String xcelPath(){
           return xcelPath;
        }*/
        /**
         * Returns the XCEL - parsed from the definition files
         * @return
         * @throws UnsupportedEncodingException
         */
        /*private String xcel() throws UnsupportedEncodingException{
           return new String(ByteArrayHelper.read(new File(xcelPath())),"UTF-8");
        }*/

    }

    /**
     * Returns an EvaluationExecutable containing the XCDLs, etc.
     * @param f1
     * @param f2
     * @return
     * @throws Exception
     */
    public EvaluationExecutable execute(File f1, File f2) {

        //check if the results can be returned from the cache else - perform the workflow
        if (this.isResultCached(f1, f2)) {
            //results already cached
            return (this.getResultFromCache(f1, f2));
        }

        //the execution results are packed within this executable
        //please note this mockup is not using the concept of the TestbedServiceTemplate
        EvaluationExecutable executable = new EvaluationExecutableImpl();
        executable.setExecutionStartDate(new GregorianCalendar().getTimeInMillis());
        executable.setExecutableInvoked(true);
        executable.setExecutionCompleted(false);

        try {
            //step1: identify using Pronom;
            String[] sPronomIDs1 = runDroid(f1);
            String[] sPronomIDs2 = runDroid(f2);

            //if-else logic - linking pronom results as input for xcdl extraction   
            @SuppressWarnings("unused")
            supportedTypes typeF1, typeF2;
            typeF1 = getType(sPronomIDs1);
            typeF2 = getType(sPronomIDs2);

            //step2: extract the xcdl descriptions
            String XCDL1 = runXCDLExtractor(f1 /*, typeF1.xcel()*/);
            String XCDL2 = runXCDLExtractor(f2 /*, typeF2.xcel()*/);

            //step3: run the XCDL comparison
            String result = runXCDLComparator(XCDL1, XCDL2);

            executable.setXCDLForSource(XCDL1);
            executable.setXCDLForTarget(XCDL2);
            executable.setXCDLsComparisonResult(result);
            executable.setExecutionSuccess(true);

        } catch (Exception e) {
            executable.setExecutionSuccess(false);
        }
        //End Workflow; write back the results into the executable
        executable.setExecutionEndDate(new GregorianCalendar().getTimeInMillis());
        executable.setExecutionCompleted(true);

        //add the result to the cache
        this.addResultToCache(executable, f1, f2);

        return executable;
    }

    /**
     * Takes an Array of PronomIDs and returns the supported type e.g. TIFF, PNG
     * If no type is known, supportedTypes = null;
     * @param pronomIDs
     * @return
     */
    private supportedTypes getType(String[] pronomIDs) throws Exception {
        supportedTypes typeFound = null;
        //iterate over all supportedTypes and check if we match one
        for (supportedTypes type : supportedTypes.values()) {
            List<String> lIDs = Arrays.asList(type.idsForType);
            for (int j = 0; j < pronomIDs.length; j++) {
                if (lIDs.contains(pronomIDs[j])) {
                    //we've found a supported type as e.g. TIFF, PNG, etc.
                    typeFound = type;
                }
            }
        }
        if (typeFound == null) {
            throw new Exception("The specified file type is currently not supported by this workflow");
        }
        return typeFound;
    }

    /**
     * Runs droid on a given File and returns an Array of PronomIDs
     * @param f1
     * @return
     * @throws Exception
     */
    private String[] runDroid(File f1) throws Exception {
        //Step1: identify using droid - returns a status and a list of IDs
        URL url = null;
        try {
            url = new URL(URL_DROID);
        } catch (MalformedURLException e) {
            e.printStackTrace();
            throw e;
        }
        Service service = Service.create(url, new QName(PlanetsServices.NS, Identify.NAME));
        Identify droid = service.getPort(Identify.class);
        byte[] array = FileUtils.readFileToByteArray(f1);

        //invoke the service and extract results
        IdentifyResult identify = droid.identify(new DigitalObject.Builder(Content.byValue(array)).build(), null);
        List<URI> result = identify.getTypes();
        String status = identify.getReport().getMessage();

        if (!status.equals("Positive")) {
            throw new Exception("Service execution failed");
        }
        if (result.size() < 1) {
            throw new Exception("The specified file type is currently not supported by this workflow");
        }

        String[] strings = new String[result.size()];
        for (int i = 0; i < result.size(); i++) {
            String string = result.get(i).toASCIIString();
            //received 1..n Pronom IDs
            strings[i] = string;
        }
        return strings;
    }

    /**
     * Runs the XCDL extractor on a given file and for a given xcel descriptor
     * Returns the XCDL description (UTF-8 encoded) for the provided file
     * @param f1
     * @param xcel
     * @return
     * @throws Exception
     */
    private String runXCDLExtractor(File f1 /*, String xcel*/) throws Exception {
        URL url = null;
        try {
            url = new URL(URL_XCDLEXTRACTOR);

            Service service = Service.create(url, new QName(PlanetsServices.NS, Migrate.NAME));
            Migrate extractor = service.getPort(Migrate.class);

            //the service's input
            byte[] array = FileUtils.readFileToByteArray(f1);

            //the service call and it's result
            DigitalObject digitalObject = extractor
                    .migrate(new DigitalObject.Builder(Content.byValue(array)).build(), null, null, null)
                    .getDigitalObject();
            byte[] results = IOUtils.toByteArray(digitalObject.getContent().getInputStream());
            String xcdl = new String(results, "UTF-8");

            if (xcdl == null) {
                throw new Exception("XCDL extraction failed - please check service logs for details");
            }

            return xcdl;

        } catch (MalformedURLException e) {
            e.printStackTrace();
            throw e;
        } catch (UnsupportedEncodingException e) {
            //xcel file was not UTF-8 encodable
            e.printStackTrace();
            throw e;
        } catch (PlanetsException e) {
            //error calling the web-service
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * Runs the XCDLComparator on two given xcdls and returns the comparison result.
     * @param xcdl1
     * @param xcdl2
     * @return
     * @throws Exception
     */
    private String runXCDLComparator(String xcdl1, String xcdl2) throws Exception {

        URL url = null;
        try {
            url = new URL(URL_XCDLCOMPARATOR);

            Service service = Service.create(url, new QName(PlanetsServices.NS, Compare.NAME));
            Compare comparator = service.getPort(Compare.class);

            //the service call and it's result
            DigitalObject x1 = new DigitalObject.Builder(Content.byValue(xcdl1.getBytes())).build();
            DigitalObject x2 = new DigitalObject.Builder(Content.byValue(xcdl2.getBytes())).build();
            List<Property> result = comparator.compare(x1, x2, null).getProperties();

            if (result == null) {
                throw new Exception("XCDL comparison failed - please check service logs for details");
            }

            return result.toString();

        } catch (MalformedURLException e) {
            e.printStackTrace();
            throw e;
        }
    }

    //Info: Map<f1.getAbsolutePath()+f2.getAbsolutePath(), EvaluationExecutable>
    private Map<String, EvaluationExecutableImpl> cache = new HashMap<String, EvaluationExecutableImpl>();

    /**
     *@see isStaticAutoEvaluationWorkflowResultCached
     */
    private EvaluationExecutable getResultFromCache(File f1, File f2) {
        if (cache.containsKey(f1.getAbsolutePath() + f2.getAbsolutePath())) {
            return (cache.get(f1.getAbsolutePath() + f2.getAbsolutePath())).clone();
        } else {
            return null;
        }
    }

    /**
     * Check if for a given data pair input and output file if the service
     * request has already been issued. If yes the results will be the same and therefore may
     * be returned from this cache
     * @param f1
     * @param f2
     * @return
     */
    private boolean isResultCached(File f1, File f2) {
        return cache.containsKey(f1.getAbsolutePath() + f2.getAbsolutePath());
    }

    /**
     *@see isStaticAutoEvaluationWorkflowResultCached
     */
    private void addResultToCache(EvaluationExecutable executable, File f1, File f2) {
        cache.put((f1.getAbsolutePath() + f2.getAbsolutePath()), (EvaluationExecutableImpl) executable);
    }

}