au.org.ala.delta.intkey.directives.invocation.DifferencesDirectiveInvocation.java Source code

Java tutorial

Introduction

Here is the source code for au.org.ala.delta.intkey.directives.invocation.DifferencesDirectiveInvocation.java

Source

/*******************************************************************************
 * Copyright (C) 2011 Atlas of Living Australia
 * All Rights Reserved.
 * 
 * The contents of this file are subject to the Mozilla Public
 * License Version 1.1 (the "License"); you may not use this file
 * except in compliance with the License. You may obtain a copy of
 * the License at http://www.mozilla.org/MPL/
 * 
 * Software distributed under the License is distributed on an "AS
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * rights and limitations under the License.
 ******************************************************************************/
package au.org.ala.delta.intkey.directives.invocation;

import java.awt.Color;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;

import org.apache.commons.io.FileUtils;

import au.org.ala.delta.intkey.model.IntkeyContext;
import au.org.ala.delta.intkey.ui.UIUtils;
import au.org.ala.delta.model.Attribute;
import au.org.ala.delta.model.Character;
import au.org.ala.delta.model.DiffUtils;
import au.org.ala.delta.model.IntegerCharacter;
import au.org.ala.delta.model.Item;
import au.org.ala.delta.model.MatchType;
import au.org.ala.delta.model.MultiStateCharacter;
import au.org.ala.delta.model.RealCharacter;
import au.org.ala.delta.model.Specimen;
import au.org.ala.delta.model.TextCharacter;
import au.org.ala.delta.model.format.AttributeFormatter;
import au.org.ala.delta.model.format.CharacterFormatter;
import au.org.ala.delta.model.format.Formatter.AngleBracketHandlingMode;
import au.org.ala.delta.model.format.Formatter.CommentStrippingMode;
import au.org.ala.delta.model.format.ItemFormatter;
import au.org.ala.delta.rtf.RTFBuilder;
import au.org.ala.delta.rtf.RTFUtils;
import au.org.ala.delta.rtf.RTFWriter;
import au.org.ala.delta.util.Pair;

public class DifferencesDirectiveInvocation extends LongRunningIntkeyDirectiveInvocation<File> {

    private MatchType _matchType;
    private boolean _matchUnknowns = false;
    private boolean _matchInapplicables = false;
    private boolean _omitTextCharacters = false;

    private boolean _useGlobalMatchValues = true;

    private List<Character> _characters;
    private List<Item> _taxa;
    private boolean _includeSpecimen = false;

    private CharacterFormatter _characterFormatter;
    private ItemFormatter _taxonFormatter;
    private AttributeFormatter _attributeFormatter;

    public void setCharacters(List<Character> characters) {
        this._characters = characters;
    }

    public void setSelectedTaxaSpecimen(Pair<List<Item>, Boolean> pair) {
        this._taxa = pair.getFirst();
        this._includeSpecimen = pair.getSecond();
    }

    public void setMatchOverlap(boolean matchOverlap) {
        if (matchOverlap) {
            _matchType = MatchType.OVERLAP;
            _useGlobalMatchValues = false;
        }
    }

    public void setMatchSubset(boolean matchSubset) {
        if (matchSubset) {
            _matchType = MatchType.SUBSET;
            _useGlobalMatchValues = false;
        }
    }

    public void setMatchExact(boolean matchExact) {
        if (matchExact) {
            _matchType = MatchType.EXACT;
            _useGlobalMatchValues = false;
        }
    }

    public void setMatchUnknowns(boolean matchUnknowns) {
        this._matchUnknowns = matchUnknowns;
        _useGlobalMatchValues = false;
    }

    public void setMatchInapplicables(boolean matchInapplicables) {
        this._matchInapplicables = matchInapplicables;
        _useGlobalMatchValues = false;
    }

    public void setOmitTextCharacters(boolean omitTextCharacters) {
        this._omitTextCharacters = omitTextCharacters;
    }

    @Override
    public File doRunInBackground(IntkeyContext context) throws IntkeyDirectiveInvocationException {
        int numberOfTaxa = _taxa.size();
        if (_includeSpecimen) {
            numberOfTaxa++;
        }

        if (numberOfTaxa < 2) {
            throw new IntkeyDirectiveInvocationException("TwoTaxaRequiredForComparison.error");
        }

        if (_useGlobalMatchValues) {
            _matchType = context.getMatchType();
            _matchUnknowns = context.getMatchUnknowns();
            _matchInapplicables = context.getMatchInapplicables();
        }

        _characterFormatter = new CharacterFormatter(context.displayNumbering(),
                CommentStrippingMode.RETAIN_SURROUNDING_STRIP_INNER, AngleBracketHandlingMode.REMOVE, false, true);
        _taxonFormatter = new ItemFormatter(context.displayNumbering(), CommentStrippingMode.STRIP_ALL,
                AngleBracketHandlingMode.RETAIN, false, false, false);
        _attributeFormatter = new AttributeFormatter(context.displayNumbering(), false,
                CommentStrippingMode.RETAIN_SURROUNDING_STRIP_INNER, AngleBracketHandlingMode.RETAIN, false,
                context.getDataset().getOrWord());

        Specimen specimen = null;
        if (_includeSpecimen) {
            specimen = context.getSpecimen();
        }

        progress(UIUtils.getResourceString("DifferencesDirective.Progress.Calculating"));

        List<au.org.ala.delta.model.Character> differences = DiffUtils.determineDifferingCharactersForTaxa(
                context.getDataset(), _characters, _taxa, specimen, _matchUnknowns, _matchInapplicables, _matchType,
                _omitTextCharacters);

        // Differences output can be very large so write it to a temporary file.
        try {
            File tempFile = File.createTempFile("IntkeyDifferences", null);
            tempFile.deleteOnExit();
            FileWriter fw = new FileWriter(tempFile);
            RTFWriter rtfWriter = new RTFWriter(fw);
            rtfWriter.startDocument();

            for (int i = 0; i < differences.size(); i++) {
                au.org.ala.delta.model.Character ch = differences.get(i);

                List<Attribute> attrs = context.getDataset().getAllAttributesForCharacter(ch.getCharacterId());

                // Display difference in bold if differing values do not overlap
                boolean differencesOverlap = DiffUtils.compareForTaxa(context.getDataset(), ch, _taxa, specimen,
                        true, true, MatchType.OVERLAP);

                String charDescription = _characterFormatter.formatCharacterDescription(ch);
                if (!differencesOverlap) {
                    charDescription = RTFUtils.formatTextBold(charDescription);
                }

                rtfWriter.writeText(charDescription);

                rtfWriter.increaseIndent();

                if (_includeSpecimen) {
                    rtfWriter.writeText(UIUtils.getResourceString("DifferencesDirective.Specimen"));
                    Attribute attr = specimen.getAttributeForCharacter(ch);

                    rtfWriter.increaseIndent();

                    String formattedAttributeDescription = _attributeFormatter.formatAttribute(attr);
                    if (!differencesOverlap) {
                        formattedAttributeDescription = RTFUtils.formatTextBold(formattedAttributeDescription);
                    }

                    rtfWriter.writeText(formattedAttributeDescription);

                    rtfWriter.decreaseIndent();
                }

                for (Item taxon : _taxa) {
                    Attribute taxonAttr = attrs.get(taxon.getItemNumber() - 1);

                    String taxonDescription = _taxonFormatter.formatItemDescription(taxon);
                    rtfWriter.writeText(taxonDescription);

                    rtfWriter.increaseIndent();

                    String formattedAttributeDescription = _attributeFormatter.formatAttribute(taxonAttr);
                    if (!differencesOverlap) {
                        formattedAttributeDescription = RTFUtils.formatTextBold(formattedAttributeDescription);
                    }

                    rtfWriter.writeText(formattedAttributeDescription);

                    rtfWriter.decreaseIndent();

                }

                rtfWriter.decreaseIndent();
                rtfWriter.writeText("");

                int progressPercent = (int) Math.floor((((double) i + 1) / differences.size()) * 100);
                progress(UIUtils.getResourceString("DifferencesDirective.Progress.Generating", progressPercent));
            }

            rtfWriter.setTextColor(Color.RED);
            rtfWriter.setFont(1);

            if (differences.size() == 0) {
                rtfWriter.writeText(UIUtils.getResourceString("DifferencesDirective.NoDifferences"));
            } else if (differences.size() == 1) {
                rtfWriter.writeText(UIUtils.getResourceString("DifferencesDirective.OneDifference"));
            } else {
                rtfWriter.writeText(
                        UIUtils.getResourceString("DifferencesDirective.ManyDifferences", differences.size()));
            }

            rtfWriter.endDocument();
            return tempFile;
        } catch (IOException ex) {
            throw new IntkeyDirectiveInvocationException(ex, "DifferencesDirectives.ReportGeneration.error",
                    ex.getMessage());
        }
    }

    @Override
    protected void handleProcessingDone(IntkeyContext context, File result) {
        context.getUI().displayRTFReportFromFile(result,
                UIUtils.getResourceString("DifferencesDirective.ReportTitle"));
    }
}