Package eu.planets_project.pp.plato.services.characterisation.xcl

Source Code of eu.planets_project.pp.plato.services.characterisation.xcl.XclPropertiesExplorer

/*******************************************************************************
* 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.services.characterisation.xcl;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.digester.Digester;
import org.apache.commons.logging.Log;
import org.xml.sax.SAXException;

import eu.planets_project.pp.plato.model.ObjectProperty;
import eu.planets_project.pp.plato.model.characterisation.xcl.XCLObjectProperty;
import eu.planets_project.pp.plato.model.measurement.Metric;
import eu.planets_project.pp.plato.model.scales.Scale;
import eu.planets_project.pp.plato.services.PlatoServiceException;
import eu.planets_project.pp.plato.services.characterisation.ICharacterisationService;
import eu.planets_project.pp.plato.util.CommandExecutor;
import eu.planets_project.pp.plato.util.OS;
import eu.planets_project.pp.plato.util.PlatoLogger;
import eu.planets_project.pp.plato.xml.StrictErrorHandler;

/**
* This class deals with the current implementation of the PP5 characterisation tool.
* Based on a list of pronom unique identifiers (puid) it returns all measurable properties.
*
* @author Hannes Kulovits
*/
public class XclPropertiesExplorer implements ICharacterisationService, Serializable {

    private static final long serialVersionUID = 3499698474788470264L;

    private static final Log log = PlatoLogger.getLogger(XclPropertiesExplorer.class);
   
    private Set<ObjectProperty> propertiesSet;
    private List<String> warnings;
    private String format;
    private String status;
    private String error;
   
    private String xclExplorerPath;
   
    private String makeTempDir() {
        String tempDir = OS.getTmpPath() + "xclexplorer" + System.nanoTime() + "/";
        new File(tempDir).mkdir();
        return tempDir;
    }
   
    public XclPropertiesExplorer() {
       
        xclExplorerPath = System.getenv("XCLEXPLORER_HOME");
        if (xclExplorerPath != null) {
            xclExplorerPath = xclExplorerPath + (xclExplorerPath.endsWith(File.separator) ? "": File.separator);
        } else {
            log.error("Environment variable XCLEXPLORER_HOME is not defined!");
        }
    }

    /**
     * @param PUIDs colon seperated list of "planets puids", i.e. pronom unique identifieres using an
     *        underscore character instead of a forward slash. The list must end with a colon.
     *        Example: fmt_10:fmt_13:
     */
    public List<ObjectProperty> characterise(String PUIDs, List<String> warnings) throws PlatoServiceException{

        if (("".equals(PUIDs)) || (xclExplorerPath == null)) {
            return new ArrayList<ObjectProperty>();
        }

        String xcelString;
        String tempDir = makeTempDir();
        String command = xclExplorerPath+"XCLExplorer "+PUIDs+ " -o "+tempDir;
       
        try {
            CommandExecutor cmdExecutor = new CommandExecutor();
            cmdExecutor.setWorkingDirectory(xclExplorerPath);
            try {
                int exitStatus = cmdExecutor.runCommand(command);
                // r.setSuccess(exitStatus == 0);
                //r.setReport(cmdExecutor.getCommandError());
            } catch (Exception e) {
              log.error(e.getMessage(),e);
            }
      
            String outputFile = tempDir+"fpm.fpm";
           
            // we use a set as we don't want dublicate properties
            propertiesSet = new HashSet<ObjectProperty>();
            this.warnings = warnings;
            status = null;
            format = null;
            error = null;


            Digester digester = new Digester();
            digester.setValidating(false);
            digester.setErrorHandler(new StrictErrorHandler());

            digester.push(this);
           
            digester.addCallMethod("*/XCLExplorer/fpmError", "setError",0);

            // maybe there is a warning in the property "status"
            digester.addSetProperties("*/XCLExplorer/format");
            digester.addCallMethod("*/XCLExplorer/format", "addWarning", 0 );
           
            digester.addObjectCreate("*/XCLExplorer/format/property", XCLObjectProperty.class);
            digester.addBeanPropertySetter("*/XCLExplorer/format/property/id", "propertyId");
            digester.addBeanPropertySetter("*/XCLExplorer/format/property/name", "name");
            digester.addBeanPropertySetter("*/XCLExplorer/format/property/description", "description");
            digester.addBeanPropertySetter("*/XCLExplorer/format/property/unit", "unit");
            digester.addBeanPropertySetter("*/XCLExplorer/format/property/type", "type");

            digester.addObjectCreate("*/XCLExplorer/format/property/metrics/m", Metric.class);
            digester.addBeanPropertySetter("*/XCLExplorer/format/property/metrics/m/mId", "metricId");
            digester.addBeanPropertySetter("*/XCLExplorer/format/property/metrics/m/mName", "name");
            digester.addBeanPropertySetter("*/XCLExplorer/format/property/metrics/m/mDescription", "description");
            digester.addBeanPropertySetter("*/XCLExplorer/format/property/metrics/m/mType", "type");
            digester.addSetNext("*/XCLExplorer/format/property/metrics/m", "addMetric");

            digester.addSetNext("*/XCLExplorer/format/property", "addProperty");

            try {
                digester.setUseContextClassLoader(true);

                digester.parse( new FileInputStream(outputFile));
               
                if (error != null) {
                    throw new PlatoServiceException("XCLExplorer failed: " + error);
                }
               
                return new ArrayList<ObjectProperty>(propertiesSet);
               
            } catch (IOException e) {
                throw new PlatoServiceException("The response of XCLExplorer is invalid.", e);
            } catch (SAXException e) {
                throw new PlatoServiceException("The response of XCLExplorer is invalid.", e);
            } finally {
                new File(tempDir+"fpm.fpm").delete();
                new File(tempDir).delete();
            }
        }  catch (Exception e) {
            log.error(e.getMessage(),e);
            return new ArrayList<ObjectProperty>();
        }
    }
   
    /**
     * Adds the ObjectProperty to the propertiesSet.
     * Used to parse the fpmResponse.
     * 
     * @param p
     */
    public void addProperty(ObjectProperty p) {
        propertiesSet.add(p);
    }
   
    /**
     * Adds the status info to the {@link #warnings}.
     * Used to parse the fpmResponse.
     *
     * @param s
     */
    public void setStatus(String s) {
        status = s;
    }
   
    public void setPuid(String f) {
        format = f;
    }
    public void addWarning(String s) {
        if ((status != null) && !("".equals(status)))
            if ("unavailable".equals(status))
               warnings.add("At the moment the characterisation service at hki.uni-koeln.de does not support the format " + format + ".");               
            else
               warnings.add(format + ": " + status);
       
        format = null;
        status = null;
    }
   
    public static Scale adjustCriterionToMetric(Metric metric) {
        if (metric == null)
            return null;
        /*
         * Plato's Scales are more precise than the result types of XCL metrics:
         * There are not only int, float and boolean values, but a distinction is drawn between
         * positive and negative numbers.
         * Therefore we have to choose the scale according to the metric itself. 
         */
        Scale scale = MetricToScaleMapping.getScale(metric.getMetricId().trim());
        return scale;
       
    }

    public String getError() {
        return error;
    }

    public void setError(String error) {
        this.error = error;
    }   
}
TOP

Related Classes of eu.planets_project.pp.plato.services.characterisation.xcl.XclPropertiesExplorer

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.