<commit_before>package com.biomatters.plugins.barcoding.validator.research.report;

import com.biomatters.geneious.publicapi.components.GLabel;
import com.biomatters.geneious.publicapi.components.GPanel;
import com.biomatters.geneious.publicapi.components.GTable;
import com.biomatters.geneious.publicapi.components.GTextPane;
import com.biomatters.geneious.publicapi.documents.AnnotatedPluginDocument;
import com.biomatters.geneious.publicapi.documents.URN;
import com.biomatters.geneious.publicapi.plugin.DocumentViewer;
import com.biomatters.geneious.publicapi.plugin.Options;
import com.biomatters.plugins.barcoding.validator.output.ValidationOutputRecord;
import com.biomatters.plugins.barcoding.validator.output.ValidationReportDocument;
import com.biomatters.plugins.barcoding.validator.research.BarcodeValidatorOptions;

import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import java.awt.*;
import java.util.*;
import java.util.List;

/**
 * @author <NAME>
 *         Created on 4/11/14 11:36 AM
 */
public class BatchValidationReportViewer extends DocumentViewer {
    private Map<URN, ValidationReportDocument> reports = new HashMap<URN, ValidationReportDocument>();

    public BatchValidationReportViewer(AnnotatedPluginDocument[] reportApds) {
        for (AnnotatedPluginDocument reportApd : reportApds) {
            if(ValidationReportDocument.class.isAssignableFrom(reportApd.getDocumentClass())) {
                ValidationReportDocument report = (ValidationReportDocument) reportApd.getDocumentOrCrash();
                reports.put(reportApd.getURN(), report);
            }
        }
    }


    @Override
    public JComponent getComponent() {
        if(reports.isEmpty()) {
            return null;
        }

        boolean barcodesNotTheSame = false;
        Set<URN> barcodeUrns = null;
        List<Row> rows = new ArrayList<Row>();
        int numPassedEverything = 0;

        for (Map.Entry<URN, ValidationReportDocument> entry : reports.entrySet()) {
            HashSet<URN> barcodesInThisReport = new HashSet<URN>();
            ValidationReportDocument report = entry.getValue();
            BarcodeValidatorOptions optionsUsed = report.getOptionsUsed();
            Map<OptionIdentifier, String> valuesFromOptions = getValuesFromOptions(optionsUsed);
            int count = 0;
            boolean passedEverything = true;
            for (ValidationOutputRecord validationOutputRecord : report.getRecords()) {
                barcodesInThisReport.add(validationOutputRecord.getBarcodeSequenceUrn());
                if(validationOutputRecord.isAllPassed()) {
                    count++;
                } else {
                    passedEverything = false;
                }
            }
            rows.add(new Row(entry.getKey(), count, report.getRecords().size() - count, valuesFromOptions));
            if(passedEverything) {
                numPassedEverything++;
            }
            if(barcodeUrns == null) {
                barcodeUrns = barcodesInThisReport;
            } else {
                if(!barcodeUrns.equals(barcodesInThisReport)) {
                    barcodesNotTheSame = true;
                }
            }
        }
        if(rows.isEmpty()) {
            return null;
        }

        Collections.sort(rows, Collections.reverseOrder(new Comparator<Row>() {
            @Override
            public int compare(Row o1, Row o2) {
                return o1.numAllPassed - o2.numAllPassed;
            }
        }));

        GPanel rootPanel = new GPanel(new BorderLayout());

        JTextPane textPane = new GTextPane();
        textPane.setContentType("text/html");
        textPane.setEditable(false);
        textPane.setText(getHeaderText(reports.size(), barcodesNotTheSame, numPassedEverything));
        rootPanel.add(textPane, BorderLayout.NORTH);

        boolean missing = false;
        Set<OptionIdentifier> optionIds = new HashSet<OptionIdentifier>();
        for (Row row : rows) {
            if(row.valuesFromOptions == null) {
                missing = true;
            } else {
                optionIds.addAll(row.valuesFromOptions.keySet());
            }
        }
        if(!missing) {
            List<OptionIdentifier> idsOfDifferent = new ArrayList<OptionIdentifier>();
            for (OptionIdentifier optionId : optionIds) {
                Set<String> values = new HashSet<String>();
                for (Row row : rows) {
                    values.add(row.valuesFromOptions.get(optionId));
                }
                if(values.size() > 1) {
                    idsOfDifferent.add(optionId);
                }
            }

            rootPanel.add(new JScrollPane(new GTable(new RowTableModel(idsOfDifferent, rows))));
        } else {
            rootPanel.add(new GLabel("No table shown because one of the selected reports was created prior to v0.2"));
        }

        return rootPanel;
    }

    private static Map<OptionIdentifier, String> getValuesFromOptions(Options optionsUsed) {
        if(optionsUsed == null) {
            return null;
        }
        return getValuesFromOptions("", optionsUsed);
    }

    private static Map<OptionIdentifier, String> getValuesFromOptions(String prefix, Options options) {
        Map<OptionIdentifier, String> result = new HashMap<OptionIdentifier, String>();
        for (Options.Option option : options.getOptions()) {
            if(!(option instanceof Options.LabelOption)) {
                result.put(new OptionIdentifier(prefix + option.getName(), option.getLabel()), option.getValueAsString());
            }
        }

        for (Map.Entry<String, Options> entry : options.getChildOptions().entrySet()) {
            result.putAll(getValuesFromOptions(prefix + entry.getKey() + ".", entry.getValue()));
        }
<commit_msg>BV-32 - Report document for overview of multiple parameter sets Add some basic sorting for now<commit_after>package com.biomatters.plugins.barcoding.validator.research.report;

import com.biomatters.geneious.publicapi.components.GLabel;
import com.biomatters.geneious.publicapi.components.GPanel;
import com.biomatters.geneious.publicapi.components.GTable;
import com.biomatters.geneious.publicapi.components.GTextPane;
import com.biomatters.geneious.publicapi.documents.AnnotatedPluginDocument;
import com.biomatters.geneious.publicapi.documents.URN;
import com.biomatters.geneious.publicapi.plugin.DocumentViewer;
import com.biomatters.geneious.publicapi.plugin.Options;
import com.biomatters.plugins.barcoding.validator.output.ValidationOutputRecord;
import com.biomatters.plugins.barcoding.validator.output.ValidationReportDocument;
import com.biomatters.plugins.barcoding.validator.research.BarcodeValidatorOptions;

import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
import javax.swing.table.TableRowSorter;
import java.awt.*;
import java.util.*;
import java.util.List;

/**
 * @author <NAME>
 *         Created on 4/11/14 11:36 AM
 */
public class BatchValidationReportViewer extends DocumentViewer {
    private Map<URN, ValidationReportDocument> reports = new HashMap<URN, ValidationReportDocument>();

    public BatchValidationReportViewer(AnnotatedPluginDocument[] reportApds) {
        for (AnnotatedPluginDocument reportApd : reportApds) {
            if(ValidationReportDocument.class.isAssignableFrom(reportApd.getDocumentClass())) {
                ValidationReportDocument report = (ValidationReportDocument) reportApd.getDocumentOrCrash();
                reports.put(reportApd.getURN(), report);
            }
        }
    }


    @Override
    public JComponent getComponent() {
        if(reports.isEmpty()) {
            return null;
        }

        boolean barcodesNotTheSame = false;
        Set<URN> barcodeUrns = null;
        List<Row> rows = new ArrayList<Row>();
        int numPassedEverything = 0;

        for (Map.Entry<URN, ValidationReportDocument> entry : reports.entrySet()) {
            HashSet<URN> barcodesInThisReport = new HashSet<URN>();
            ValidationReportDocument report = entry.getValue();
            BarcodeValidatorOptions optionsUsed = report.getOptionsUsed();
            Map<OptionIdentifier, String> valuesFromOptions = getValuesFromOptions(optionsUsed);
            int count = 0;
            boolean passedEverything = true;
            for (ValidationOutputRecord validationOutputRecord : report.getRecords()) {
                barcodesInThisReport.add(validationOutputRecord.getBarcodeSequenceUrn());
                if(validationOutputRecord.isAllPassed()) {
                    count++;
                } else {
                    passedEverything = false;
                }
            }
            rows.add(new Row(entry.getKey(), count, report.getRecords().size() - count, valuesFromOptions));
            if(passedEverything) {
                numPassedEverything++;
            }
            if(barcodeUrns == null) {
                barcodeUrns = barcodesInThisReport;
            } else {
                if(!barcodeUrns.equals(barcodesInThisReport)) {
                    barcodesNotTheSame = true;
                }
            }
        }
        if(rows.isEmpty()) {
            return null;
        }

        Collections.sort(rows, Collections.reverseOrder(new Comparator<Row>() {
            @Override
            public int compare(Row o1, Row o2) {
                return o1.numAllPassed - o2.numAllPassed;
            }
        }));

        GPanel rootPanel = new GPanel(new BorderLayout());

        JTextPane textPane = new GTextPane();
        textPane.setContentType("text/html");
        textPane.setEditable(false);
        textPane.setText(getHeaderText(reports.size(), barcodesNotTheSame, numPassedEverything));
        rootPanel.add(textPane, BorderLayout.NORTH);

        boolean missing = false;
        Set<OptionIdentifier> optionIds = new HashSet<OptionIdentifier>();
        for (Row row : rows) {
            if(row.valuesFromOptions == null) {
                missing = true;
            } else {
                optionIds.addAll(row.valuesFromOptions.keySet());
            }
        }
        if(!missing) {
            List<OptionIdentifier> idsOfDifferent = new ArrayList<OptionIdentifier>();
            for (OptionIdentifier optionId : optionIds) {
                Set<String> values = new HashSet<String>();
                for (Row row : rows) {
                    values.add(row.valuesFromOptions.get(optionId));
                }
                if(values.size() > 1) {
                    idsOfDifferent.add(optionId);
                }
            }

            RowTableModel model = new RowTableModel(idsOfDifferent, rows);
            GTable table = new GTable(model);
            table.setRowSorter(new TableRowSorter<TableModel>(model));
            rootPanel.add(new JScrollPane(table));
        } else {
            rootPanel.add(new GLabel("No table shown because one of the selected reports was created prior to v0.2"));
        }

        return rootPanel;
    }

    private static Map<OptionIdentifier, String> getValuesFromOptions(Options optionsUsed) {
        if(optionsUsed == null) {
            return null;
        }
        return getValuesFromOptions("", optionsUsed);
    }

    private static Map<OptionIdentifier, String> getValuesFromOptions(String prefix, Options options) {
        Map<OptionIdentifier, String> result = new HashMap<OptionIdentifier, String>();
        for (Options.Option option : options.getOptions()) {
            if(!(option instanceof Options.LabelOption)) {
                result.put(new OptionIdentifier(prefix + option.getName(), option.getLabel()), option.getValueAsString());
            }
        }

        for (Map.Entry<String, Options> entry : options.getChildOptions().entrySet()) {
            result.putAll(getValuesFromOptions(prefix + entry.getKey() + ".", entry.getValue()));
        }

{'fraction_non_alphanumeric': 0.10004182350480971, 'fraction_numerical': 0.003178586365537432, 'mean_word_length': 2.492842535787321, 'pattern_counts': {'":': 0, '<': 48, '<?xml version=': 0, '>': 50, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4640588', 'n_tokens_mistral': 3227, 'n_tokens_neox': 3049, 'n_words': 582}