Java tutorial
/* * Copyright 2011 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; import annis.libgui.Helper; import annis.model.Annotation; import com.google.common.collect.ComparisonChain; import com.google.common.escape.Escaper; import com.google.common.net.UrlEscapers; import com.sun.jersey.api.client.ClientHandlerException; import com.sun.jersey.api.client.UniformInterfaceException; import com.sun.jersey.api.client.WebResource; import com.vaadin.data.Property; import com.vaadin.data.util.BeanItemContainer; import com.vaadin.shared.ui.label.ContentMode; import com.vaadin.ui.Accordion; import com.vaadin.ui.Alignment; import com.vaadin.ui.ComboBox; import com.vaadin.ui.Component; import com.vaadin.ui.HorizontalLayout; import com.vaadin.ui.Label; import com.vaadin.ui.Notification; import com.vaadin.ui.Panel; import com.vaadin.ui.Table; import com.vaadin.ui.Table.ColumnGenerator; import com.vaadin.ui.VerticalLayout; import com.vaadin.ui.themes.ChameleonTheme; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.TreeMap; import org.slf4j.LoggerFactory; /** * Provides all corpus annotations for a corpus or for a specific search result. * * // TODO cleanup the toplevelCorpus side effects. * * @author thomas * @author Benjamin Weienfels <b.pixeldrama@gmail.com> */ public class MetaDataPanel extends Panel implements Property.ValueChangeListener { private static final org.slf4j.Logger log = LoggerFactory.getLogger(MetaDataPanel.class); private final static Escaper urlPathEscape = UrlEscapers.urlPathSegmentEscaper(); private VerticalLayout layout; private String toplevelCorpusName; // this is only set if the metadata panel is called from a specific result. private String documentName; private ComboBox corpusSelection; // last selected corpus or document of the combobox private String lastSelectedItem; // holds all corpus and documents for the combox in the corpus browser panel private List<Annotation> docs; // holds the current corpus annotation table, when called from corpus browser private Table corpusAnnotationTable = null; /** * this empty label is currently use for empty metadata list on the left side * of the corpusbrowser */ private Label emptyLabel = new Label("(no metadata)"); public MetaDataPanel(String toplevelCorpusName) { this(toplevelCorpusName, null); } public MetaDataPanel(String toplevelCorpusName, String documentName) { super("Metadata"); this.toplevelCorpusName = toplevelCorpusName; this.documentName = documentName; setSizeFull(); layout = new VerticalLayout(); setContent(layout); layout.setSizeFull(); if (documentName == null) { docs = getAllSubcorpora(toplevelCorpusName); HorizontalLayout selectionLayout = new HorizontalLayout(); Label selectLabel = new Label("Select corpus/document: "); corpusSelection = new ComboBox(); selectionLayout.addComponents(selectLabel, corpusSelection); layout.addComponent(selectionLayout); selectLabel.setSizeUndefined(); corpusSelection.setWidth(100, Unit.PERCENTAGE); corpusSelection.setHeight("-1px"); corpusSelection.addValueChangeListener(MetaDataPanel.this); selectionLayout.setWidth(100, Unit.PERCENTAGE); selectionLayout.setHeight("-1px"); selectionLayout.setSpacing(true); selectionLayout.setComponentAlignment(selectLabel, Alignment.MIDDLE_LEFT); selectionLayout.setComponentAlignment(corpusSelection, Alignment.MIDDLE_LEFT); selectionLayout.setExpandRatio(selectLabel, 0.4f); selectionLayout.setExpandRatio(corpusSelection, 0.6f); corpusSelection.addItem(toplevelCorpusName); corpusSelection.select(toplevelCorpusName); corpusSelection.setNullSelectionAllowed(false); corpusSelection.setImmediate(true); for (Annotation c : docs) { corpusSelection.addItem(c.getName()); } } else { Map<Integer, List<Annotation>> hashMData = splitListAnnotations(); List<BeanItemContainer<Annotation>> l = putInBeanContainer(hashMData); Accordion accordion = new Accordion(); accordion.setSizeFull(); // set output to none if no metadata are available if (l.isEmpty()) { addEmptyLabel(); } else { for (BeanItemContainer<Annotation> item : l) { String corpusName = item.getIdByIndex(0).getCorpusName(); String path = toplevelCorpusName.equals(corpusName) ? "corpus: " + corpusName : "document: " + corpusName; if (item.getItemIds().isEmpty()) { accordion.addTab(new Label("none"), path); } else { accordion.addTab(setupTable(item), path); } } layout.addComponent(accordion); } } } private Table setupTable(BeanItemContainer<Annotation> metaData) { final BeanItemContainer<Annotation> mData = metaData; mData.sort(new Object[] { "namespace", "name" }, new boolean[] { true, true }); Table tblMeta = new Table(); tblMeta.setContainerDataSource(mData); tblMeta.addGeneratedColumn("genname", new MetaTableNameGenerator(mData)); tblMeta.addGeneratedColumn("genvalue", new MetaTableValueGenerator(mData)); tblMeta.setVisibleColumns("genname", "genvalue"); tblMeta.setColumnHeaders("Name", "Value"); tblMeta.setSizeFull(); tblMeta.setColumnWidth("genname", -1); tblMeta.setColumnExpandRatio("genvalue", 1.0f); tblMeta.addStyleName(ChameleonTheme.TABLE_STRIPED); return tblMeta; } /** * Returns empty map if no metadata are available. */ private Map<Integer, List<Annotation>> splitListAnnotations() { List<Annotation> metadata = Helper.getMetaData(toplevelCorpusName, documentName); Map<Integer, List<Annotation>> hashMetaData = new HashMap<>(); if (metadata != null && !metadata.isEmpty()) { // if called from corpus browser sort the other way around. if (documentName != null) { hashMetaData = new TreeMap<>(Collections.reverseOrder()); } else { hashMetaData = new TreeMap<>(); } for (Annotation metaDatum : metadata) { int pre = metaDatum.getPre(); if (!hashMetaData.containsKey(pre)) { hashMetaData.put(pre, new ArrayList<Annotation>()); hashMetaData.get(pre).add(metaDatum); } else { hashMetaData.get(pre).add(metaDatum); } } } return hashMetaData; } private List<BeanItemContainer<Annotation>> putInBeanContainer( Map<Integer, List<Annotation>> splittedAnnotationsList) { List<BeanItemContainer<Annotation>> listOfBeanItemCon = new ArrayList<>(); for (List<Annotation> list : splittedAnnotationsList.values()) { BeanItemContainer<Annotation> metaContainer = new BeanItemContainer<>(Annotation.class); metaContainer.addAll(list); listOfBeanItemCon.add(metaContainer); } return listOfBeanItemCon; } private List<Annotation> getAllSubcorpora(String toplevelCorpusName) { List<Annotation> result = new LinkedList<>(); WebResource res = Helper.getAnnisWebResource(); try { res = res.path("meta").path("docnames").path(urlPathEscape.escape(toplevelCorpusName)); result = res.get(new Helper.AnnotationListType()); Collections.sort(result, new Comparator<Annotation>() { @Override public int compare(Annotation arg0, Annotation arg1) { return ComparisonChain.start().compare(arg0.getName(), arg1.getName()).result(); } }); } catch (UniformInterfaceException ex) { log.error(null, ex); Notification.show("Remote exception: " + ex.getLocalizedMessage(), Notification.Type.WARNING_MESSAGE); } catch (ClientHandlerException ex) { log.error(null, ex); Notification.show("Remote exception: " + ex.getLocalizedMessage(), Notification.Type.WARNING_MESSAGE); } return result; } @Override public void valueChange(Property.ValueChangeEvent event) { if (lastSelectedItem == null || !lastSelectedItem.equals(event.getProperty().getValue())) { lastSelectedItem = event.getProperty().getValue().toString(); List<Annotation> metaData = Helper.getMetaDataDoc(toplevelCorpusName, lastSelectedItem); if (metaData == null || metaData.isEmpty()) { super.setCaption("No metadata available"); addEmptyLabel(); if (corpusAnnotationTable != null) { corpusAnnotationTable.removeAllItems(); } } else { super.setCaption("Metadata"); removeEmptyLabel(); loadTable(toplevelCorpusName, metaData); } } } private void loadTable(String item, List<Annotation> metaData) { BeanItemContainer<Annotation> metaContainer = new BeanItemContainer<>(Annotation.class); metaContainer.addAll(metaData); if (corpusAnnotationTable != null) { layout.removeComponent(corpusAnnotationTable); } layout.removeComponent(emptyLabel); corpusAnnotationTable = setupTable(metaContainer); corpusAnnotationTable.setHeight(100, Unit.PERCENTAGE); corpusAnnotationTable.setWidth(100, Unit.PERCENTAGE); layout.addComponent(corpusAnnotationTable); layout.setExpandRatio(corpusAnnotationTable, 1.0f); } /** * Places a label in the middle center of the corpus browser panel. */ private void addEmptyLabel() { if (emptyLabel == null) { emptyLabel = new Label("none"); } if (corpusAnnotationTable != null) { layout.removeComponent(corpusAnnotationTable); } layout.addComponent(emptyLabel); // this has only an effect after adding the component to a parent. Bug by vaadin? emptyLabel.setSizeUndefined(); layout.setComponentAlignment(emptyLabel, Alignment.MIDDLE_CENTER); layout.setExpandRatio(emptyLabel, 1.0f); } private void removeEmptyLabel() { if (emptyLabel != null) { layout.removeComponent(emptyLabel); } } public static class MetaTableNameGenerator implements ColumnGenerator { private final BeanItemContainer<Annotation> mData; public MetaTableNameGenerator(BeanItemContainer<Annotation> mData) { this.mData = mData; } @Override public Component generateCell(Table source, Object itemId, Object columnId) { Annotation anno = mData.getItem(itemId).getBean(); String qName = anno.getName(); if (anno.getNamespace() != null) { qName = anno.getNamespace() + ":" + qName; } Label l = new Label(qName); l.setSizeUndefined(); return l; } } public static class MetaTableValueGenerator implements ColumnGenerator { private final BeanItemContainer<Annotation> mData; public MetaTableValueGenerator(BeanItemContainer<Annotation> mData) { this.mData = mData; } @Override public Component generateCell(Table source, Object itemId, Object columnId) { Annotation anno = mData.getItem(itemId).getBean(); Label l = new Label(anno.getValue(), ContentMode.HTML); return l; } } }