annis.gui.frequency.FrequencyResultPanel.java Source code

Java tutorial

Introduction

Here is the source code for annis.gui.frequency.FrequencyResultPanel.java

Source

/*
 * Copyright 2012 Corpuslinguistic working group Humboldt University Berlin.
 *
 * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package annis.gui.frequency;

import annis.gui.components.FrequencyChart;
import annis.gui.objects.FrequencyQuery;
import annis.libgui.Helper;
import annis.service.objects.FrequencyTable;
import annis.service.objects.FrequencyTableEntry;
import annis.service.objects.FrequencyTableEntryType;
import au.com.bytecode.opencsv.CSVWriter;
import com.google.common.base.Charsets;
import com.google.common.base.Joiner;
import com.google.common.collect.Ordering;
import com.vaadin.data.Container;
import com.vaadin.data.util.AbstractBeanContainer;
import com.vaadin.data.util.DefaultItemSorter;
import com.vaadin.data.util.IndexedContainer;
import com.vaadin.data.util.ItemSorter;
import com.vaadin.server.FileDownloader;
import com.vaadin.server.FontAwesome;
import com.vaadin.server.StreamResource;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Table;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.ValoTheme;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.Serializable;
import java.io.Writer;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
import org.slf4j.LoggerFactory;

/**
 *
 * @author Thomas Krause <krauseto@hu-berlin.de>
 */
public class FrequencyResultPanel extends VerticalLayout {
    private static final org.slf4j.Logger log = LoggerFactory.getLogger(FrequencyResultPanel.class);

    public static final int MAX_NUMBER_OF_CHART_ITEMS = 100;

    private Table tblResult;
    private final Button btDownloadCSV;
    private final FrequencyChart chart;
    private final FrequencyQueryPanel queryPanel;
    private final FrequencyQuery query;

    public FrequencyResultPanel(FrequencyTable table, FrequencyQuery query, FrequencyQueryPanel queryPanel) {
        this.query = query;
        this.queryPanel = queryPanel;

        setSizeFull();

        chart = new FrequencyChart(this);
        chart.setHeight("350px");
        chart.setVisible(false);
        addComponent(chart);

        btDownloadCSV = new Button("Download as CSV");
        btDownloadCSV.setDescription("Download as CSV");
        btDownloadCSV.setSizeUndefined();
        addComponent(btDownloadCSV);
        setComponentAlignment(btDownloadCSV, Alignment.TOP_RIGHT);

        btDownloadCSV.setVisible(false);
        btDownloadCSV.setIcon(FontAwesome.DOWNLOAD);
        btDownloadCSV.addStyleName(ValoTheme.BUTTON_SMALL);

        showResult(table);
    }

    private void showResult(FrequencyTable table) {
        if (queryPanel != null) {
            queryPanel.notifiyQueryFinished();
        }
        recreateTable(table);

        btDownloadCSV.setVisible(true);
        FileDownloader downloader = new FileDownloader(
                new StreamResource(new CSVResource(table, query.getFrequencyDefinition()), "frequency.txt"));
        downloader.extend(btDownloadCSV);

        chart.setVisible(true);
        FrequencyTable clippedTable = table;
        if (clippedTable.getEntries().size() > MAX_NUMBER_OF_CHART_ITEMS) {
            List<FrequencyTable.Entry> entries = new ArrayList<>(clippedTable.getEntries());

            clippedTable = new FrequencyTable();
            clippedTable.setEntries(entries.subList(0, MAX_NUMBER_OF_CHART_ITEMS));
            clippedTable.setSum(table.getSum());
            chart.setCaption("Showing historgram of top " + MAX_NUMBER_OF_CHART_ITEMS
                    + " results, see table below for complete dataset.");
        }
        chart.setFrequencyData(clippedTable);

    }

    private String createFieldsString() {
        StringBuilder sb = new StringBuilder();

        ListIterator<FrequencyTableEntry> it = query.getFrequencyDefinition().listIterator();
        while (it.hasNext()) {
            FrequencyTableEntry e = it.next();

            sb.append(e.getReferencedNode()).append(":");
            if (e.getType() == FrequencyTableEntryType.span) {
                sb.append("tok");
            } else {
                sb.append(e.getKey());
            }

            if (it.hasNext()) {
                sb.append(",");
            }
        }

        return sb.toString();
    }

    private void recreateTable(FrequencyTable table) {

        if (tblResult != null) {
            removeComponent(tblResult);
        }

        tblResult = new Table();
        tblResult.setSizeFull();

        tblResult.setCaption(table.getEntries().size() + " items with a total sum of " + table.getSum()
                + " (query on " + Joiner.on(", ").join(query.getCorpora()) + ")");

        tblResult.setSelectable(true);
        tblResult.setMultiSelect(false);
        tblResult.addStyleName(Helper.CORPUS_FONT_FORCE);

        if (!table.getEntries().isEmpty()) {
            FrequencyTable.Entry firstEntry = table.getEntries().iterator().next();
            int tupelCount = firstEntry.getTupel().length;

            tblResult.addContainerProperty("rank", Integer.class, -1);
            for (int i = 1; i <= tupelCount; i++) {
                tblResult.addContainerProperty("tupel-" + i, String.class, "");
                FrequencyTableEntry e = query.getFrequencyDefinition().get(i - 1);

                tblResult.setColumnHeader("tupel-" + i, getCaption(e));
            }

            tblResult.addContainerProperty("count", Long.class, -1l);

            int line = 0;
            for (FrequencyTable.Entry e : table.getEntries()) {
                Object[] cells = new Object[tupelCount + 2];

                System.arraycopy(e.getTupel(), 0, cells, 1, tupelCount);

                cells[0] = line + 1;
                cells[cells.length - 1] = e.getCount();

                tblResult.addItem(cells, "entry-" + line++);
            }
        }
        addLexicalSort(tblResult.getContainerDataSource());

        addComponent(tblResult);
        setExpandRatio(tblResult, 1.0f);

    }

    private void addLexicalSort(Container container) {
        ItemSorter sorter = new DefaultItemSorter(new IgnoreCaseComparator());

        if (container instanceof IndexedContainer) {
            ((IndexedContainer) container).setItemSorter(sorter);
        } else if (container instanceof AbstractBeanContainer) {
            ((AbstractBeanContainer) container).setItemSorter(sorter);
        }
    }

    public static class IgnoreCaseComparator implements Comparator<Object>, Serializable {

        @Override
        @SuppressWarnings("unchecked")
        public int compare(Object o1, Object o2) {
            if (o1 instanceof String && o2 instanceof String) {
                String s1 = (String) o1;
                String s2 = (String) o2;

                Collator collator = Collator.getInstance(Locale.ENGLISH);
                collator.setStrength(Collator.PRIMARY);
                return collator.compare(s1, s2);
            } else {
                return Ordering.natural().compare((Comparable) o1, (Comparable) o2);
            }
        }
    }

    public static String getCaption(FrequencyTableEntry e) {
        String caption;
        switch (e.getType()) {
        case annotation:
            caption = "#" + e.getReferencedNode() + "|" + e.getKey();
            break;
        case span:
            caption = "#" + e.getReferencedNode() + "|spanned text";
            break;
        case meta:
            caption = "meta|" + e.getKey();
            break;
        default:
            caption = "<unknown>";
        }
        return caption;
    }

    public static class CSVResource implements StreamResource.StreamSource {
        private final FrequencyTable data;
        private final List<FrequencyTableEntry> freqDefinition;

        public CSVResource(FrequencyTable data, List<FrequencyTableEntry> freqDefinition) {
            this.data = data;
            this.freqDefinition = freqDefinition;
        }

        @Override
        public InputStream getStream() {
            try {
                File tmpFile = File.createTempFile("annis-frequency", ".txt");
                tmpFile.deleteOnExit();
                try (Writer writer = new OutputStreamWriter(new FileOutputStream(tmpFile), Charsets.UTF_8)) {
                    CSVWriter csv = new CSVWriter(writer, '\t', CSVWriter.NO_QUOTE_CHARACTER, '\\');

                    // write headers
                    ArrayList<String> header = new ArrayList<>();
                    if (data.getEntries().size() > 0) {
                        for (int i = 0; i < data.getEntries().iterator().next().getTupel().length; i++) {
                            FrequencyTableEntry e = freqDefinition.get(i);
                            header.add(getCaption(e));
                        }
                    }
                    // add count
                    header.add("count");
                    csv.writeNext(header.toArray(new String[0]));

                    // write entries
                    for (FrequencyTable.Entry e : data.getEntries()) {
                        ArrayList<String> d = new ArrayList<>();
                        d.addAll(Arrays.asList(e.getTupel()));
                        d.add("" + e.getCount());
                        csv.writeNext(d.toArray(new String[0]));
                    }
                }

                return new FileInputStream(tmpFile);

            } catch (IOException ex) {
                log.error(null, ex);
            }
            return new ByteArrayInputStream(new byte[0]);
        }
    }

    public void selectRow(int i) {
        tblResult.setValue("entry-" + i);
        tblResult.setCurrentPageFirstItemId("entry-" + i);
    }

}