2 * Copyright (C) 2018 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
9 package eu
.etaxonomy
.taxeditor
.editor
.descriptiveDataSet
.matrix
;
11 import java
.util
.ArrayList
;
12 import java
.util
.Collection
;
13 import java
.util
.List
;
15 import java
.util
.UUID
;
16 import java
.util
.stream
.Collectors
;
18 import org
.eclipse
.core
.runtime
.ICoreRunnable
;
19 import org
.eclipse
.core
.runtime
.IProgressMonitor
;
20 import org
.eclipse
.core
.runtime
.SubMonitor
;
21 import org
.eclipse
.core
.runtime
.jobs
.IJobChangeEvent
;
22 import org
.eclipse
.core
.runtime
.jobs
.Job
;
23 import org
.eclipse
.core
.runtime
.jobs
.JobChangeAdapter
;
24 import org
.eclipse
.jface
.layout
.GridDataFactory
;
25 import org
.eclipse
.jface
.window
.Window
;
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
.layout
.RowLayout
;
30 import org
.eclipse
.swt
.widgets
.Button
;
31 import org
.eclipse
.swt
.widgets
.Composite
;
33 import eu
.etaxonomy
.cdm
.api
.application
.CdmApplicationState
;
34 import eu
.etaxonomy
.cdm
.api
.service
.IDescriptiveDataSetService
;
35 import eu
.etaxonomy
.cdm
.api
.service
.ITaxonNodeService
;
36 import eu
.etaxonomy
.cdm
.api
.service
.UpdateResult
;
37 import eu
.etaxonomy
.cdm
.api
.service
.description
.AggregationMode
;
38 import eu
.etaxonomy
.cdm
.api
.service
.description
.StructuredDescriptionAggregationConfiguration
;
39 import eu
.etaxonomy
.cdm
.api
.service
.dto
.RowWrapperDTO
;
40 import eu
.etaxonomy
.cdm
.common
.monitor
.IRemotingProgressMonitor
;
41 import eu
.etaxonomy
.cdm
.filter
.TaxonNodeFilter
;
42 import eu
.etaxonomy
.cdm
.model
.description
.DescriptiveDataSet
;
43 import eu
.etaxonomy
.cdm
.model
.location
.NamedArea
;
44 import eu
.etaxonomy
.cdm
.model
.taxon
.Taxon
;
45 import eu
.etaxonomy
.cdm
.model
.taxon
.TaxonNode
;
46 import eu
.etaxonomy
.cdm
.persistence
.dto
.SpecimenNodeWrapper
;
47 import eu
.etaxonomy
.cdm
.persistence
.dto
.TaxonNodeDto
;
48 import eu
.etaxonomy
.taxeditor
.editor
.internal
.TaxeditorEditorPlugin
;
49 import eu
.etaxonomy
.taxeditor
.editor
.l10n
.Messages
;
50 import eu
.etaxonomy
.taxeditor
.model
.ImageResources
;
51 import eu
.etaxonomy
.taxeditor
.model
.MessagingUtils
;
52 import eu
.etaxonomy
.taxeditor
.store
.CdmStore
;
53 import eu
.etaxonomy
.taxeditor
.store
.StoreUtil
;
54 import eu
.etaxonomy
.taxeditor
.ui
.dialog
.selection
.TaxonSelectionDialog
;
60 public class CharacterMatrixBottomToolbar
extends Composite
{
62 private CharacterMatrix matrix
;
64 public CharacterMatrixBottomToolbar(CharacterMatrix matrix
, int style
) {
73 setLayout(new RowLayout());
74 GridDataFactory
.fillDefaults().grab(true, false).applyTo(this);
77 * Add description button
79 Button btnAddDescription
= new Button(this, SWT
.PUSH
);
80 btnAddDescription
.setImage(ImageResources
.getImage(ImageResources
.ADD_ICON_GREEN
));
81 btnAddDescription
.addSelectionListener(new SelectionAdapter() {
83 public void widgetSelected(SelectionEvent e
) {
84 if(StoreUtil
.promptCheckIsDirty(matrix
.getPart())){
87 SpecimenSelectionDialog dialog
= new SpecimenSelectionDialog(matrix
.getShell(), matrix
);
88 if(dialog
.open()==Window
.OK
){
89 Collection
<SpecimenNodeWrapper
> wrappers
= dialog
.getSpecimen();
90 if(wrappers
.stream().anyMatch(wrapper
->wrapper
.getTaxonDescriptionUuid()==null)
91 && !MessagingUtils
.confirmDialog(
92 "Create Taxon Association",
93 "Some specimens are not linked with taxon via IndividualsAssociation yet.\n"
94 + "Do you want to create this association?")){
97 addRowsToMatrix(wrappers
, matrix
.getDescriptiveDataSet().getUuid());
98 wrappers
.forEach(wrapper
->matrix
.getSpecimenCache().remove(wrapper
));
103 * Remove description button
105 Button btnRemoveDescription
= new Button(this, SWT
.PUSH
);
106 btnRemoveDescription
.setImage(ImageResources
.getImage(ImageResources
.ACTIVE_DELETE_ICON
));
107 btnRemoveDescription
.addSelectionListener(new SelectionAdapter() {
109 public void widgetSelected(SelectionEvent e
) {
110 if(StoreUtil
.promptCheckIsDirty(matrix
.getPart())){
113 if(!MessagingUtils
.confirmDialog(Messages
.CharacterMatrixBottomToolbar_CONFIRM_DELETE_TITLE
, Messages
.CharacterMatrixBottomToolbar_CONFIRM_DELETE_MESSAGE
)){
116 int[] fullySelectedRowPositions
= matrix
.getBodyLayer().getSelectionLayer().getFullySelectedRowPositions();
117 List
<RowWrapperDTO
> toRemove
= new ArrayList
<>();
118 for (int i
: fullySelectedRowPositions
) {
119 Object rowObject
= matrix
.getBodyDataProvider().getRowObject(i
);
120 if(rowObject
instanceof RowWrapperDTO
){
121 toRemove
.add((RowWrapperDTO
) rowObject
);
124 toRemove
.forEach(rowToRemove
-> {
125 matrix
.getDescriptions().remove(rowToRemove
);
126 CdmStore
.getService(IDescriptiveDataSetService
.class).removeDescription(
127 rowToRemove
.getDescription().getUuid(), matrix
.getDescriptiveDataSet().getUuid());
134 Button btnAggregate
= new Button(this, SWT
.PUSH
);
135 btnAggregate
.setText(Messages
.CharacterMatrixBottomToolbar_AGGREGATE
);
136 btnAggregate
.addSelectionListener(new SelectionAdapter() {
138 public void widgetSelected(SelectionEvent e
) {
139 if(StoreUtil
.promptCheckIsDirty(matrix
.getPart())){
142 aggregatDescriptiveDataSet(matrix
.getDescriptiveDataSet().getUuid());
146 * Key generation button
148 Button btnGenerateKey
= new Button(this, SWT
.PUSH
);
149 btnGenerateKey
.setText("Generate Polytomous Key");
150 btnGenerateKey
.addSelectionListener(new SelectionAdapter() {
152 public void widgetSelected(SelectionEvent e
) {
153 if(StoreUtil
.promptCheckIsDirty(matrix
.getPart())){
156 Set
<TaxonNodeDto
> nodeDtos
= matrix
.getDescriptiveDataSet().getTaxonSubtreeFilter().stream()
157 .map(node
->new TaxonNodeDto(node
))
158 .collect(Collectors
.toSet());
159 TaxonNodeDto parentDto
= CdmStore
.getService(ITaxonNodeService
.class).findCommonParentDto(nodeDtos
);
160 UUID taxonUuid
= parentDto
.getTaxonUuid();
161 int response
= MessagingUtils
.confirmDialog(
162 "Choose taxonomic scope",
163 String
.format("The common parent taxon of this data set is :\n%s\n\n"
164 + "Do you want to use this as the taxonomic scope for the polytomous key?"
165 , parentDto
.getTaxonTitleCache()), "Yes", "Choose different taxon", "Cancel");
169 else if(response
==1){
170 Taxon taxon
= TaxonSelectionDialog
.selectTaxon(getShell(), null);
174 taxonUuid
= taxon
.getUuid();
176 generateKey(matrix
.getDescriptiveDataSet().getUuid(), taxonUuid
);
182 private void aggregatDescriptiveDataSet(UUID descriptiveDataSetUuid
){
183 // FIXME: set taxon node filter for config (this is still not used in the aggregation)
184 StructuredDescriptionAggregationConfiguration config
= StructuredDescriptionAggregationConfiguration
.NewInstance(
186 config
.setDatasetUuid(matrix
.getDescriptiveDataSet().getUuid());
187 config
.setAggregateToHigherRanks(true);
188 config
.setAggregationMode(AggregationMode
.byAreasAndRanks());
189 config
.setAdaptBatchSize(false);
191 TaxonNodeFilter filter
= TaxonNodeFilter
.NewRankInstance(matrix
.getDescriptiveDataSet().getMinRank(),
192 matrix
.getDescriptiveDataSet().getMaxRank());
193 for (NamedArea namedArea
: matrix
.getDescriptiveDataSet().getGeoFilter()) {
194 filter
= filter
.orArea(namedArea
.getUuid());
196 for (TaxonNode taxonNode
: matrix
.getDescriptiveDataSet().getTaxonSubtreeFilter()) {
197 filter
= filter
.orSubtree(taxonNode
);
199 config
.setTaxonNodeFilter(filter
);
201 UUID monitorUuid
= CdmApplicationState
.getLongRunningTasksService().invoke(config
);
203 String jobLabel
= "Aggregate Descriptive Data Set";
204 Job job
= Job
.create(jobLabel
, (ICoreRunnable
) monitor
-> {
205 SubMonitor subMonitor
= SubMonitor
.convert(monitor
);
206 subMonitor
.beginTask(jobLabel
, IProgressMonitor
.UNKNOWN
);
207 IRemotingProgressMonitor remotingMonitor
;
209 remotingMonitor
= CdmStore
.getProgressMonitorClientManager()
210 .pollMonitor(jobLabel
,
216 Object resultObject
= remotingMonitor
.getResult();
217 if(resultObject
instanceof Exception
){
218 MessagingUtils
.errorDialog("Aggregation failed", this, "Aggregation was not successfull", TaxeditorEditorPlugin
.PLUGIN_ID
, (Exception
)resultObject
, true, true);
220 else if(resultObject
instanceof UpdateResult
){
221 DescriptiveDataSet dataSet
= (DescriptiveDataSet
) ((UpdateResult
) resultObject
).getCdmEntity();
222 dataSet
= matrix
.getCdmEntitiySession().load(dataSet
, true);
223 // update local dataset
224 matrix
.setDescriptiveDataSet(dataSet
);
225 matrix
.loadDescriptions(descriptiveDataSetUuid
, false);
227 } catch (InterruptedException e
) {
232 job
.addJobChangeListener(new JobChangeAdapter(){
234 public void done(IJobChangeEvent event
) {
235 CharacterMatrixBottomToolbar
.this.getDisplay().asyncExec(()->{
243 private void addRowsToMatrix(Collection
<SpecimenNodeWrapper
> wrappers
, UUID descriptiveDataSetUuid
){
244 UUID monitorUuid
= CdmApplicationState
.getLongRunningTasksService().addRowWrapperToDataset(wrappers
, descriptiveDataSetUuid
);
246 String jobLabel
= "Add specimens to matrix";
247 Job job
= Job
.create(jobLabel
, (ICoreRunnable
) monitor
-> {
248 SubMonitor subMonitor
= SubMonitor
.convert(monitor
);
249 subMonitor
.beginTask(jobLabel
, IProgressMonitor
.UNKNOWN
);
250 IRemotingProgressMonitor remotingMonitor
;
252 remotingMonitor
= CdmStore
.getProgressMonitorClientManager()
253 .pollMonitor(jobLabel
,
259 Object resultObject
= remotingMonitor
.getResult();
260 if(resultObject
instanceof Exception
){
261 MessagingUtils
.errorDialog("Adding specimens failed", this, "Adding specimens was not successfull", TaxeditorEditorPlugin
.PLUGIN_ID
, (Exception
)resultObject
, true, true);
263 else if(resultObject
instanceof UpdateResult
){
264 UpdateResult result
= (UpdateResult
)resultObject
;
265 if(!result
.getExceptions().isEmpty()){
266 MessagingUtils
.warningDialog(Messages
.CharacterMatrixBottomToolbar_ERROR_ROW_CREATION_TITLE
, this,
267 String
.format(Messages
.CharacterMatrixBottomToolbar_ERROR_ROW_CREATION_MESSAGE
, result
.getExceptions()
268 .stream().map(ex
->ex
.toString())
269 .collect(Collectors
.joining("\n"))));
271 DescriptiveDataSet dataSet
= (DescriptiveDataSet
) result
.getCdmEntity();
272 dataSet
= matrix
.getCdmEntitiySession().load(dataSet
, true);
273 // update local dataset
274 matrix
.setDescriptiveDataSet(dataSet
);
275 matrix
.loadDescriptions(descriptiveDataSetUuid
, false);
277 } catch (InterruptedException e
) {
282 job
.addJobChangeListener(new JobChangeAdapter(){
284 public void done(IJobChangeEvent event
) {
285 CharacterMatrixBottomToolbar
.this.getDisplay().asyncExec(()->{
293 private void generateKey(UUID datasetUuid
, UUID taxonUuid
) {
295 UUID monitorUuid
= CdmApplicationState
.getLongRunningTasksService().generatePolytomousKey(datasetUuid
, taxonUuid
);
297 String jobLabel
= "Generate polytomous key";
298 Job job
= Job
.create(jobLabel
, (ICoreRunnable
) monitor
-> {
299 SubMonitor subMonitor
= SubMonitor
.convert(monitor
);
300 subMonitor
.beginTask(jobLabel
, IProgressMonitor
.UNKNOWN
);
301 IRemotingProgressMonitor remotingMonitor
;
303 remotingMonitor
= CdmStore
.getProgressMonitorClientManager()
304 .pollMonitor(jobLabel
,
310 Object resultObject
= remotingMonitor
.getResult();
311 if(resultObject
instanceof Exception
){
312 MessagingUtils
.errorDialog("Key generation failed", this, "Generating the polytomous key was not successfull", TaxeditorEditorPlugin
.PLUGIN_ID
, (Exception
)resultObject
, true, true);
314 } catch (InterruptedException e
) {