ref #7095 Add text filter to specimen selection dialog
[taxeditor.git] / eu.etaxonomy.taxeditor.editor / src / main / java / eu / etaxonomy / taxeditor / editor / workingSet / matrix / SpecimenSelectionDialog.java
1 /**
2 * Copyright (C) 2018 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9 package eu.etaxonomy.taxeditor.editor.workingSet.matrix;
10
11 import java.util.ArrayList;
12 import java.util.Collection;
13 import java.util.List;
14 import java.util.UUID;
15 import java.util.stream.Collectors;
16 import java.util.stream.Stream;
17
18 import org.eclipse.jface.dialogs.Dialog;
19 import org.eclipse.jface.layout.GridDataFactory;
20 import org.eclipse.jface.viewers.IStructuredContentProvider;
21 import org.eclipse.jface.viewers.IStructuredSelection;
22 import org.eclipse.jface.viewers.ITableLabelProvider;
23 import org.eclipse.jface.viewers.LabelProvider;
24 import org.eclipse.jface.viewers.TableViewer;
25 import org.eclipse.jface.viewers.TableViewerColumn;
26 import org.eclipse.swt.SWT;
27 import org.eclipse.swt.events.SelectionAdapter;
28 import org.eclipse.swt.events.SelectionEvent;
29 import org.eclipse.swt.graphics.Image;
30 import org.eclipse.swt.layout.GridData;
31 import org.eclipse.swt.layout.GridLayout;
32 import org.eclipse.swt.widgets.Button;
33 import org.eclipse.swt.widgets.Composite;
34 import org.eclipse.swt.widgets.Control;
35 import org.eclipse.swt.widgets.Shell;
36 import org.eclipse.swt.widgets.Table;
37 import org.eclipse.swt.widgets.Text;
38
39 import eu.etaxonomy.cdm.api.service.IOccurrenceService;
40 import eu.etaxonomy.cdm.api.service.ITaxonNodeService;
41 import eu.etaxonomy.cdm.api.service.config.FindOccurrencesConfigurator;
42 import eu.etaxonomy.cdm.common.CdmUtils;
43 import eu.etaxonomy.cdm.filter.TaxonNodeFilter;
44 import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
45 import eu.etaxonomy.cdm.model.taxon.Taxon;
46 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
47 import eu.etaxonomy.taxeditor.editor.l10n.Messages;
48 import eu.etaxonomy.taxeditor.model.ImageResources;
49 import eu.etaxonomy.taxeditor.store.CdmStore;
50 import eu.etaxonomy.taxeditor.ui.combo.taxon.TaxonNodeCombo;
51
52 /**
53 * Dialog to choose specimens for the character matrix.<br>
54 * Filters specimens that have already been added.
55 * @author pplitzner
56 * @since Jan 3, 2018
57 *
58 */
59 public class SpecimenSelectionDialog extends Dialog {
60
61 private TableViewer list;
62
63 private Collection<SpecimenOrObservationBase> selectedSpecimens = new ArrayList<>();
64 private CharacterMatrix matrix;
65 private Text txtTextFilter;
66
67 private TaxonNodeCombo comboTaxon;
68
69 protected SpecimenSelectionDialog(Shell parentShell, CharacterMatrix matrix) {
70 super(parentShell);
71 this.matrix = matrix;
72 }
73
74 @Override
75 protected Control createDialogArea(Composite parent) {
76 Composite composite = (Composite) super.createDialogArea(parent);
77 GridLayout gl_composite = new GridLayout();
78 composite.setLayout(gl_composite);
79
80 Composite composite_1 = new Composite(composite, SWT.NONE);
81 composite_1.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1));
82 composite_1.setLayout(new GridLayout(3, false));
83
84 txtTextFilter = new Text(composite_1, SWT.BORDER);
85 txtTextFilter.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
86 txtTextFilter.addModifyListener(e->applyFilter());
87
88 comboTaxon = new TaxonNodeCombo(composite_1, SWT.NONE);
89 comboTaxon.setInput(matrix.getWorkingSet().getTaxonSubtreeFilter());
90 comboTaxon.addSelectionChangedListener(e->applyFilter());
91
92 Button btnRefreshButton = new Button(composite_1, SWT.NONE);
93 btnRefreshButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
94 btnRefreshButton.setToolTipText(Messages.SpecimenSelectionDialog_REFRESH);
95 btnRefreshButton.setImage(ImageResources.getImage(ImageResources.REFRESH));
96 btnRefreshButton.addSelectionListener(new SelectionAdapter() {
97 @Override
98 public void widgetSelected(SelectionEvent e) {
99 loadSpecimens();
100 list.setInput(matrix.getSpecimenCache());
101 }
102 });
103 //table
104 list = new TableViewer(composite, SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
105 Table table = list.getTable();
106 GridData gd_table = GridDataFactory.fillDefaults().create();
107 gd_table.grabExcessHorizontalSpace = true;
108 gd_table.grabExcessVerticalSpace = true;
109 table.setLayoutData(gd_table);
110 //table columns
111 TableViewerColumn columnTaxon = new TableViewerColumn(list, SWT.NONE);
112 columnTaxon.getColumn().setText("Taxon");
113 columnTaxon.getColumn().setWidth(200);
114 columnTaxon.getColumn().setResizable(true);
115 columnTaxon.getColumn().setMoveable(true);
116 TableViewerColumn columnSpecimen = new TableViewerColumn(list, SWT.NONE);
117 columnSpecimen.getColumn().setText("Specimen");
118 columnSpecimen.getColumn().setWidth(200);
119 columnSpecimen.getColumn().setResizable(true);
120 columnSpecimen.getColumn().setMoveable(true);
121 table.setHeaderVisible(true);
122 table.setLinesVisible(true);
123 list.setContentProvider(new SpecimenListContentProvider());
124 list.setLabelProvider(new SpecimenListLabelProvider());
125
126 //gather specimens
127 if(matrix.getSpecimenCache()==null){
128 loadSpecimens();
129 }
130 list.setInput(matrix.getSpecimenCache());
131 return composite;
132 }
133
134 private void applyFilter(){
135 Stream<SpecimenWrapper> filteredWrappers =matrix.getSpecimenCache().stream();
136 if(comboTaxon.getSelection()!=null){
137 filteredWrappers =
138 filteredWrappers
139 .filter(wrapper->wrapper.getTaxonNode().equals(comboTaxon.getSelection()));
140 }
141 if(!CdmUtils.isBlank(txtTextFilter.getText())){
142 filteredWrappers =
143 filteredWrappers
144 .filter(wrapper->wrapper.getLabel().toLowerCase().contains(txtTextFilter.getText().toLowerCase()));
145 }
146 list.setInput(filteredWrappers.collect(Collectors.toList()));
147 }
148
149 private void loadSpecimens(){
150 List<SpecimenWrapper> specimenCache = new ArrayList<>();
151 //set filter parameters
152 TaxonNodeFilter filter = TaxonNodeFilter.NewRankInstance(matrix.getWorkingSet().getMinRank(), matrix.getWorkingSet().getMaxRank());
153 matrix.getWorkingSet().getGeoFilter().forEach(area -> filter.orArea(area.getUuid()));
154 matrix.getWorkingSet().getTaxonSubtreeFilter().forEach(node -> filter.orSubtree(node));
155 filter.setIncludeUnpublished(true);
156
157 ITaxonNodeService taxonNodeService = CdmStore.getService(ITaxonNodeService.class);
158 List<UUID> filteredNodes = taxonNodeService.uuidList(filter);
159 for (UUID uuid : filteredNodes) {
160 //TODO implement occurrence service for taxon nodes
161 // let it return UuidAndTitleCache
162 TaxonNode taxonNode = taxonNodeService.load(uuid);
163 Taxon taxon = taxonNode.getTaxon();
164 if(taxon!=null){
165 FindOccurrencesConfigurator config = new FindOccurrencesConfigurator();
166 config.setAssociatedTaxonUuid(taxon.getUuid());
167 List<SpecimenOrObservationBase> specimensForTaxon = CdmStore.getService(IOccurrenceService.class).findByTitle(config).getRecords();
168 specimensForTaxon.forEach(specimen->specimenCache.add(new SpecimenWrapper(specimen, taxonNode, specimen.getTitleCache())));
169 }
170 }
171 matrix.setSpecimenCache(specimenCache);
172 }
173
174 @Override
175 protected void configureShell(Shell newShell) {
176 super.configureShell(newShell);
177 newShell.setText(Messages.SpecimenSelectionDialog_SELECT_SPECIMENS);
178 newShell.setMinimumSize(500, 400);
179 }
180
181 @Override
182 protected void okPressed() {
183 selectedSpecimens.clear();
184 List<SpecimenWrapper> wrappers = ((IStructuredSelection)list.getSelection()).toList();
185 wrappers.forEach(element->selectedSpecimens.add(element.getSpecimen()));
186 super.okPressed();
187 }
188
189 @Override
190 protected boolean isResizable() {
191 return true;
192 }
193
194 public Collection<SpecimenOrObservationBase> getSpecimen(){
195 return selectedSpecimens;
196 }
197
198 private class SpecimenListContentProvider implements IStructuredContentProvider{
199 @Override
200 public Object[] getElements(Object inputElement) {
201 return ((List<SpecimenWrapper>) inputElement).stream().filter(wrapper ->
202 wrapper.getSpecimen().getDescriptions().stream().noneMatch(description ->
203 matrix.getWorkingSet().getDescriptions().contains(description))).toArray();
204 }
205 }
206
207 private class SpecimenListLabelProvider extends LabelProvider implements ITableLabelProvider{
208
209 @Override
210 public Image getColumnImage(Object element, int columnIndex) {
211 return null;
212 }
213
214 @Override
215 public String getColumnText(Object element, int columnIndex) {
216 if(element instanceof SpecimenWrapper){
217 SpecimenWrapper wrapper = (SpecimenWrapper)element;
218 switch (columnIndex) {
219 case 0:
220 return wrapper.getTaxonNode().getTaxon().getName().getTitleCache();
221 case 1:
222 return wrapper.getSpecimen().getTitleCache();
223 default:
224 break;
225 }
226 }
227 return "";
228 }
229 }
230 }