eu.planets_project.pp.plato.evaluation.evaluators.FITSEvaluator.java Source code

Java tutorial

Introduction

Here is the source code for eu.planets_project.pp.plato.evaluation.evaluators.FITSEvaluator.java

Source

/*******************************************************************************
 * 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.evaluation.evaluators;

import java.io.IOException;
import java.io.StringReader;
import java.util.HashMap;
import java.util.List;

import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.logging.Log;
import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import eu.planets_project.pp.plato.evaluation.EvaluatorException;
import eu.planets_project.pp.plato.evaluation.IObjectEvaluator;
import eu.planets_project.pp.plato.evaluation.IStatusListener;
import eu.planets_project.pp.plato.model.Alternative;
import eu.planets_project.pp.plato.model.DigitalObject;
import eu.planets_project.pp.plato.model.FormatInfo;
import eu.planets_project.pp.plato.model.SampleObject;
import eu.planets_project.pp.plato.model.scales.Scale;
import eu.planets_project.pp.plato.model.values.BooleanValue;
import eu.planets_project.pp.plato.model.values.Value;
import eu.planets_project.pp.plato.services.characterisation.fits.FitsNamespaceContext;
import eu.planets_project.pp.plato.util.FloatFormatter;
import eu.planets_project.pp.plato.util.MeasurementInfoUri;
import eu.planets_project.pp.plato.util.PlatoLogger;

public class FITSEvaluator extends EvaluatorBase implements IObjectEvaluator {
    private static final String FITS_COMPRESSIONSCHEME_UNCOMPRESSED = "Uncompressed";
    private static final String NAME = "FITS/Jhove/Exiftool";
    private static final String SOURCE = "\n- extracted by " + NAME;

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

    private static final String DESCRIPTOR_FILE = "data/evaluation/measurementsFITS.xml";

    public FITSEvaluator() {
        // load information about measurements
        loadMeasurementsDescription(DESCRIPTOR_FILE);
    }

    public HashMap<MeasurementInfoUri, Value> evaluate(Alternative alternative, SampleObject sample,
            DigitalObject result, List<MeasurementInfoUri> measurementInfoUris, IStatusListener listener)
            throws EvaluatorException {

        FloatFormatter formatter = new FloatFormatter();

        HashMap<MeasurementInfoUri, Value> results = new HashMap<MeasurementInfoUri, Value>();

        String fitsXMLResult = result.getFitsXMLString();
        String fitsXMLSample = sample.getFitsXMLString();

        XmlExtractor extractor = new XmlExtractor();
        extractor.setNamespaceContext(new FitsNamespaceContext());
        if ((fitsXMLResult != null) && (fitsXMLSample != null)) {
            // so we have a fits xml, lets analyse it:
            try {
                StringReader reader = new StringReader(fitsXMLResult);
                Document fitsDocResult = extractor.getDocument(new InputSource(reader));
                reader = new StringReader(fitsXMLSample);
                Document fitsDocSample = extractor.getDocument(new InputSource(reader));

                String sampleImageCompressionScheme = extractor.extractText(fitsDocSample,
                        "//fits:compressionScheme/text()");
                String resultImageCompressionScheme = extractor.extractText(fitsDocResult,
                        "//fits:compressionScheme/text()");

                for (MeasurementInfoUri measurementInfoUri : measurementInfoUris) {
                    Value v = null;
                    String propertyURI = measurementInfoUri.getAsURI();
                    Scale scale = descriptor.getMeasurementScale(measurementInfoUri);
                    if (scale == null) {
                        // This means that I am not entitled to evaluate this measurementInfo and therefore supposed to skip it:
                        continue;
                    }
                    if (OBJECT_FORMAT_CORRECT_WELLFORMED.equals(propertyURI)) {
                        v = extractor.extractValue(fitsDocResult, scale,
                                "//fits:well-formed[@status='SINGLE_RESULT']/text()",
                                "//fits:filestatus/fits:message/text()");
                    } else if (OBJECT_FORMAT_CORRECT_VALID.equals(propertyURI)) {
                        v = extractor.extractValue(fitsDocResult, scale,
                                "//fits:filestatus/fits:valid[@status='SINGLE_RESULT']/text()",
                                "//fits:filestatus/fits:message/text()");
                    }
                    if (OBJECT_COMPRESSION_SCHEME.equals(propertyURI)) {
                        v = extractor.extractValue(fitsDocResult, scale, "//fits:compressionScheme/text()", null);
                    }

                    if ((v != null) && (v.getComment() == null || "".equals(v.getComment()))) {
                        v.setComment(SOURCE);
                        results.put(measurementInfoUri, v);
                        listener.updateStatus(String.format("%s: measurement: %s = %s", NAME,
                                measurementInfoUri.getAsURI(), v.toString()));
                        // this leaf has been processed
                        continue;
                    }

                    if (OBJECT_FORMAT_CORRECT_CONFORMS.equals(propertyURI)) {
                        if (alternative.getAction() != null) {
                            String puid = "UNDEFINED";
                            FormatInfo info = alternative.getAction().getTargetFormatInfo();
                            if (info != null) {
                                puid = info.getPuid();
                            }
                            String fitsText = extractor.extractText(fitsDocResult,
                                    "//fits:externalIdentifier[@type='puid']/text()");
                            v = identicalValues(puid, fitsText, scale);
                        }
                    } else if ((OBJECT_IMAGE_DIMENSION_WIDTH + "#equal").equals(propertyURI)) {
                        String sampleValue = extractor.extractText(fitsDocSample, "//fits:imageWidth/text()");
                        String resultValue = extractor.extractText(fitsDocResult, "//fits:imageWidth/text()");
                        v = identicalValues(sampleValue, resultValue, scale);
                    } else if ((OBJECT_IMAGE_DIMENSION_HEIGHT + "#equal").equals(propertyURI)) {
                        String sampleValue = extractor.extractText(fitsDocSample, "//fits:imageHeight/text()");
                        String resultValue = extractor.extractText(fitsDocResult, "//fits:imageHeight/text()");
                        v = identicalValues(sampleValue, resultValue, scale);
                    } else if ((OBJECT_IMAGE_DIMENSION_ASPECTRATIO + "#equal").equals(propertyURI)) {
                        try {
                            int sampleHeight = Integer
                                    .parseInt(extractor.extractText(fitsDocSample, "//fits:imageHeight/text()"));
                            int resultHeight = Integer
                                    .parseInt(extractor.extractText(fitsDocResult, "//fits:imageHeight/text()"));
                            int sampleWidth = Integer
                                    .parseInt(extractor.extractText(fitsDocSample, "//fits:imageWidth/text()"));
                            int resultWidth = Integer
                                    .parseInt(extractor.extractText(fitsDocResult, "//fits:imageWidth/text()"));

                            double sampleRatio = ((double) sampleWidth) / sampleHeight;
                            double resultRatio = ((double) resultWidth) / resultHeight;
                            v = scale.createValue();
                            ((BooleanValue) v).bool(0 == Double.compare(sampleRatio, resultRatio));
                            v.setComment(String.format("Reference value: %s\nActual value: %s",
                                    formatter.formatFloat(sampleRatio), formatter.formatFloat(resultRatio)));
                        } catch (NumberFormatException e) {
                            // not all values are available - aspectRatio cannot be calculated 
                            v = scale.createValue();
                            v.setComment(
                                    "Image width and/or height are not available - aspectRatio cannot be calculated");
                        }
                    } else if ((OBJECT_COMPRESSION_SCHEME + "#equal").equals(propertyURI)) {
                        v = identicalValues(sampleImageCompressionScheme, resultImageCompressionScheme, scale);
                    } else if (OBJECT_COMPRESSION_LOSSLESS.equals(propertyURI)) {
                        // At the moment we only handle compression schemes of images
                        if ((resultImageCompressionScheme != null) && (!"".equals(resultImageCompressionScheme))) {
                            v = scale.createValue();
                            ((BooleanValue) v)
                                    .bool(FITS_COMPRESSIONSCHEME_UNCOMPRESSED.equals(resultImageCompressionScheme));
                        }
                    } else if (OBJECT_COMPRESSION_LOSSY.equals(propertyURI)) {
                        // At the moment we only handle compression schemes of images
                        if ((resultImageCompressionScheme != null) && (!"".equals(resultImageCompressionScheme))) {
                            v = scale.createValue();
                            ((BooleanValue) v).bool(
                                    !FITS_COMPRESSIONSCHEME_UNCOMPRESSED.equals(resultImageCompressionScheme));
                        }
                    } else if ((OBJECT_IMAGE_COLORENCODING_BITSPERSAMPLE + "#equal").equals(propertyURI)) {
                        String sampleValue = extractor.extractText(fitsDocSample, "//fits:bitsPerSample/text()");
                        String resultValue = extractor.extractText(fitsDocResult, "//fits:bitsPerSample/text()");
                        v = identicalValues(sampleValue, resultValue, scale);
                    } else if ((OBJECT_IMAGE_COLORENCODING_SAMPLESPERPIXEL + "#equal").equals(propertyURI)) {
                        String sampleValue = extractor.extractText(fitsDocSample, "//fits:samplesPerPixel/text()");
                        String resultValue = extractor.extractText(fitsDocResult, "//fits:samplesPerPixel/text()");
                        v = identicalValues(sampleValue, resultValue, scale);
                    } else if ((OBJECT_IMAGE_PHOTOMETRICINTERPRETATION_COLORSPACE + "#equal").equals(propertyURI)) {
                        String sampleValue = extractor.extractText(fitsDocSample, "//fits:colorSpace/text()");
                        String resultValue = extractor.extractText(fitsDocResult, "//fits:colorSpace/text()");
                        v = identicalValues(sampleValue, resultValue, scale);
                    } else if ((OBJECT_IMAGE_PHOTOMETRICINTERPRETATION_COLORPROFILE_ICCPROFILE + "#equal")
                            .equals(propertyURI)) {
                        String sampleValue = extractor.extractText(fitsDocSample, "//fits:iccProfileName/text()");
                        String resultValue = extractor.extractText(fitsDocResult, "//fits:iccProfileName/text()");
                        v = identicalValues(sampleValue, resultValue, scale);
                    } else if ((OBJECT_IMAGE_SPATIALMETRICS_SAMPLINGFREQUENCYUNIT + "#equal").equals(propertyURI)) {
                        String sampleValue = extractor.extractText(fitsDocSample,
                                "//fits:samplingFrequencyUnit/text()");
                        String resultValue = extractor.extractText(fitsDocResult,
                                "//fits:samplingFrequencyUnit/text()");
                        v = identicalValues(sampleValue, resultValue, scale);
                    } else if ((OBJECT_IMAGE_SPATIALMETRICS_XSAMPLINGFREQUENCY + "#equal").equals(propertyURI)) {
                        String sampleValue = extractor.extractText(fitsDocSample,
                                "//fits:xSamplingFrequency/text()");
                        String resultValue = extractor.extractText(fitsDocResult,
                                "//fits:xSamplingFrequency/text()");
                        v = identicalValues(sampleValue, resultValue, scale);
                    } else if ((OBJECT_IMAGE_SPATIALMETRICS_YSAMPLINGFREQUENCY + "#equal").equals(propertyURI)) {
                        String sampleValue = extractor.extractText(fitsDocSample,
                                "//fits:ySamplingFrequency/text()");
                        String resultValue = extractor.extractText(fitsDocResult,
                                "//fits:ySamplingFrequency/text()");
                        v = identicalValues(sampleValue, resultValue, scale);

                    } else if ((OBJECT_IMAGE_METADATA + "#equal").equals(propertyURI)) {
                        // we use the equal metric. reserve PRESERVED metric for later and get it right.
                        HashMap<String, String> sampleMetadata = extractor.extractValues(fitsDocSample,
                                "//fits:exiftool/*[local-name() != 'rawdata']");
                        HashMap<String, String> resultMetadata = extractor.extractValues(fitsDocResult,
                                "//fits:exiftool/*[local-name() != 'rawdata']");
                        v = preservedValues(sampleMetadata, resultMetadata, scale);
                    } else if ((OBJECT_IMAGE_METADATA_PRODUCER + "#equal").equals(propertyURI)) {
                        String sampleValue = extractor.extractText(fitsDocSample,
                                "//fits:ImageCreation/ImageProducer/text()");
                        String resultValue = extractor.extractText(fitsDocResult,
                                "//fits:ImageCreation/ImageProducer/text()");
                        v = identicalValues(sampleValue, resultValue, scale);
                    } else if ((OBJECT_IMAGE_METADATA_SOFTWARE + "#equal").equals(propertyURI)) {
                        String sampleValue = extractor.extractText(fitsDocSample,
                                "//fits:creatingApplicationName/text()");
                        String resultValue = extractor.extractText(fitsDocResult,
                                "//fits:creatingApplicationName/text()");
                        v = identicalValues(sampleValue, resultValue, scale);
                    } else if ((OBJECT_IMAGE_METADATA_CREATIONDATE + "#equal").equals(propertyURI)) {
                        String sampleValue = extractor.extractText(fitsDocSample,
                                "//fits:ImageCreation/DateTimeCreated/text()");
                        String resultValue = extractor.extractText(fitsDocResult,
                                "//fits:ImageCreation/DateTimeCreated/text()");
                        v = identicalValues(sampleValue, resultValue, scale);
                    } else if ((OBJECT_IMAGE_METADATA_LASTMODIFIED + "#equal").equals(propertyURI)) {
                        String sampleValue = extractor.extractText(fitsDocSample,
                                "//fits:fileinfo/lastmodified/text()");
                        String resultValue = extractor.extractText(fitsDocResult,
                                "//fits:fileinfo/lastmodified/text()");
                        v = identicalValues(sampleValue, resultValue, scale);
                    } else if ((OBJECT_IMAGE_METADATA_DESCRIPTION + "#equal").equals(propertyURI)) {
                        String sampleValue = extractor.extractText(fitsDocSample,
                                "//fits:exiftool/ImageDescription/text()");
                        String resultValue = extractor.extractText(fitsDocResult,
                                "//fits:exiftool/ImageDescription/text()");
                        v = identicalValues(sampleValue, resultValue, scale);
                    } else if ((OBJECT_IMAGE_METADATA_ORIENTATION + "#equal").equals(propertyURI)) {
                        String sampleValue = extractor.extractText(fitsDocSample,
                                "//fits:exiftool/Orientation/text()");
                        String resultValue = extractor.extractText(fitsDocResult,
                                "//fits:exiftool/Orientation/text()");
                        v = identicalValues(sampleValue, resultValue, scale);
                    }

                    if (v != null) {
                        v.setComment(v.getComment() + SOURCE);
                        results.put(measurementInfoUri, v);
                        listener.updateStatus(String.format("%s: evaluated measurement: %s = %s", NAME,
                                measurementInfoUri.getAsURI(), v.toString()));
                    } else {
                        listener.updateStatus(String.format("%s: no evaluator found for measurement: %s", NAME,
                                measurementInfoUri.getAsURI()));
                    }
                }
            } catch (IOException e) {
                listener.updateStatus(" - could not read FITS xml");
            } catch (SAXException e) {
                listener.updateStatus(" - invalid FITS xml found");
            } catch (ParserConfigurationException e) {
                listener.updateStatus(" - invalid FITS xml found");
            }
        } else {
            listener.updateStatus(" - no FITS xml found");
        }
        return results;
    }

    private Value preservedValues(HashMap<String, String> sampleMetadata, HashMap<String, String> resultMetadata,
            Scale scale) {
        int numMissing = 0;
        int numChanged = 0;
        BooleanValue v = (BooleanValue) scale.createValue();
        StringBuilder comment = new StringBuilder();
        for (String key : sampleMetadata.keySet()) {
            String sampleValue = sampleMetadata.get(key);
            String resultValue = resultMetadata.get(key);
            if (resultValue == null) {
                numMissing++;
                comment.append(" - " + key + "\n");
            } else if (!resultValue.equals(sampleValue)) {
                numChanged++;
                comment.append(" ~ " + key + ": sample=" + sampleValue + ", result=" + resultValue + "\n");
            }
        }
        if ((numChanged == 0) && (numMissing == 0)) {
            v.bool(true);
            v.setComment("result contains complete metadata of sample");
        } else {
            v.bool(false);
            comment.insert(0, "following differences found: (- .. missing, ~ .. altered):\n");
            v.setComment(comment.toString());
        }
        return v;
    }

    private Value identicalValues(String v1, String v2, Scale s) {
        BooleanValue bv = (BooleanValue) s.createValue();
        String s1 = (v1 == null || "".equals(v1)) ? "UNDEFINED" : v1;
        String s2 = (v2 == null || "".equals(v2)) ? "UNDEFINED" : v2;

        if (!"UNDEFINED".equals(s1) && !"UNDEFINED".equals(s2)) {
            // both values are defined:
            if (s1.equals(s2)) {
                bv.bool(true);
                bv.setComment("Both have value " + s1);
            } else {
                bv.bool(false);
                bv.setComment("Reference value: " + s1 + "\nActual value: " + s2);
            }
        } else if (s1.equals(s2)) {
            // both are undefined :
            bv.setComment("Both values are UNDEFINED");
            //bv.setValue("");
        } else {
            // one value is undefined:
            bv.setComment("Reference value: " + s1 + "\nActual value: " + s2);
        }
        return bv;
    }
}