Java tutorial
/******************************************************************************* * 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; } }