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.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; } }