Merge branch 'hotfix/5.45.1'
[taxeditor.git] / eu.etaxonomy.taxeditor.editor / src / main / java / eu / etaxonomy / taxeditor / editor / view / checklist / e4 / DistributionEditor.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.view.checklist.e4;
10
11 import java.util.ArrayList;
12 import java.util.Arrays;
13 import java.util.HashMap;
14 import java.util.HashSet;
15 import java.util.Iterator;
16 import java.util.List;
17 import java.util.Map;
18 import java.util.Set;
19 import java.util.SortedSet;
20 import java.util.TreeSet;
21 import java.util.UUID;
22 import java.util.stream.Collectors;
23
24 import org.apache.commons.collections4.map.LinkedMap;
25 import org.apache.logging.log4j.LogManager;
26 import org.apache.logging.log4j.Logger;
27 import org.eclipse.jface.layout.GridDataFactory;
28 import org.eclipse.jface.layout.GridLayoutFactory;
29 import org.eclipse.jface.wizard.WizardDialog;
30 import org.eclipse.nebula.widgets.nattable.NatTable;
31 import org.eclipse.nebula.widgets.nattable.config.ConfigRegistry;
32 import org.eclipse.nebula.widgets.nattable.config.DefaultNatTableStyleConfiguration;
33 import org.eclipse.nebula.widgets.nattable.coordinate.PositionCoordinate;
34 import org.eclipse.nebula.widgets.nattable.data.IDataProvider;
35 import org.eclipse.nebula.widgets.nattable.data.IRowDataProvider;
36 import org.eclipse.nebula.widgets.nattable.data.ListDataProvider;
37 import org.eclipse.nebula.widgets.nattable.extension.e4.selection.E4SelectionListener;
38 import org.eclipse.nebula.widgets.nattable.extension.glazedlists.filterrow.DefaultGlazedListsFilterStrategy;
39 import org.eclipse.nebula.widgets.nattable.filterrow.FilterRowHeaderComposite;
40 import org.eclipse.nebula.widgets.nattable.freeze.CompositeFreezeLayer;
41 import org.eclipse.nebula.widgets.nattable.freeze.FreezeHelper;
42 import org.eclipse.nebula.widgets.nattable.freeze.FreezeLayer;
43 import org.eclipse.nebula.widgets.nattable.grid.GridRegion;
44 import org.eclipse.nebula.widgets.nattable.grid.command.ClientAreaResizeCommand;
45 import org.eclipse.nebula.widgets.nattable.grid.data.DefaultColumnHeaderDataProvider;
46 import org.eclipse.nebula.widgets.nattable.grid.data.DefaultCornerDataProvider;
47 import org.eclipse.nebula.widgets.nattable.grid.data.DefaultRowHeaderDataProvider;
48 import org.eclipse.nebula.widgets.nattable.grid.layer.ColumnHeaderLayer;
49 import org.eclipse.nebula.widgets.nattable.grid.layer.CornerLayer;
50 import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultColumnHeaderDataLayer;
51 import org.eclipse.nebula.widgets.nattable.grid.layer.DefaultRowHeaderDataLayer;
52 import org.eclipse.nebula.widgets.nattable.grid.layer.GridLayer;
53 import org.eclipse.nebula.widgets.nattable.grid.layer.RowHeaderLayer;
54 import org.eclipse.nebula.widgets.nattable.layer.AbstractLayer;
55 import org.eclipse.nebula.widgets.nattable.layer.DataLayer;
56 import org.eclipse.nebula.widgets.nattable.layer.ILayer;
57 import org.eclipse.nebula.widgets.nattable.layer.config.DefaultColumnHeaderStyleConfiguration;
58 import org.eclipse.nebula.widgets.nattable.painter.cell.TextPainter;
59 import org.eclipse.nebula.widgets.nattable.painter.cell.decorator.BeveledBorderDecorator;
60 import org.eclipse.nebula.widgets.nattable.selection.SelectionLayer;
61 import org.eclipse.nebula.widgets.nattable.sort.config.SingleClickSortConfiguration;
62 import org.eclipse.nebula.widgets.nattable.util.GUIHelper;
63 import org.eclipse.swt.SWT;
64 import org.eclipse.swt.events.SelectionAdapter;
65 import org.eclipse.swt.events.SelectionEvent;
66 import org.eclipse.swt.layout.GridData;
67 import org.eclipse.swt.layout.GridLayout;
68 import org.eclipse.swt.widgets.Button;
69 import org.eclipse.swt.widgets.Composite;
70 import org.eclipse.swt.widgets.Label;
71 import org.eclipse.swt.widgets.Text;
72
73 import ca.odell.glazedlists.BasicEventList;
74 import ca.odell.glazedlists.EventList;
75 import eu.etaxonomy.cdm.api.service.ITermCollectionService;
76 import eu.etaxonomy.cdm.api.service.ITermService;
77 import eu.etaxonomy.cdm.api.service.dto.TaxonDescriptionDTO;
78 import eu.etaxonomy.cdm.api.service.dto.TaxonDistributionDTO;
79 import eu.etaxonomy.cdm.compare.term.OrderedTermComparator;
80 import eu.etaxonomy.cdm.compare.term.TermIdInVocabularyComparator;
81 import eu.etaxonomy.cdm.compare.term.TermLanguageComparator;
82 import eu.etaxonomy.cdm.compare.term.TermSymbol1Comparator;
83 import eu.etaxonomy.cdm.compare.term.TermSymbol2Comparator;
84 import eu.etaxonomy.cdm.model.common.Language;
85 import eu.etaxonomy.cdm.model.description.DescriptionElementBase;
86 import eu.etaxonomy.cdm.model.description.Distribution;
87 import eu.etaxonomy.cdm.model.description.TaxonDescription;
88 import eu.etaxonomy.cdm.model.location.NamedArea;
89 import eu.etaxonomy.cdm.model.metadata.PreferencePredicate;
90 import eu.etaxonomy.cdm.model.metadata.TermOrder;
91 import eu.etaxonomy.cdm.model.reference.Reference;
92 import eu.etaxonomy.cdm.model.term.DefinedTermBase;
93 import eu.etaxonomy.cdm.model.term.Representation;
94 import eu.etaxonomy.cdm.model.term.TermType;
95 import eu.etaxonomy.cdm.model.term.TermVocabulary;
96 import eu.etaxonomy.cdm.persistence.dto.TermCollectionDto;
97 import eu.etaxonomy.cdm.persistence.dto.TermDto;
98 import eu.etaxonomy.taxeditor.editor.IDistributionEditor;
99 import eu.etaxonomy.taxeditor.editor.l10n.Messages;
100 import eu.etaxonomy.taxeditor.model.AbstractUtility;
101 import eu.etaxonomy.taxeditor.model.ImageResources;
102 import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
103 import eu.etaxonomy.taxeditor.preference.Resources;
104 import eu.etaxonomy.taxeditor.preference.wizard.AvailableDistributionWizard;
105 import eu.etaxonomy.taxeditor.store.CdmStore;
106 import eu.etaxonomy.taxeditor.ui.dialog.selection.ReferenceSelectionDialog;
107
108 /**
109 * @author k.luther
110 * @since 27.11.2018
111 */
112 public class DistributionEditor extends Composite implements IDistributionEditor {
113
114 @SuppressWarnings("unused")
115 private static final Logger logger = LogManager.getLogger();
116
117 private static final String DISTRIBUTION_EDITOR = "Distribution Editor"; //$NON-NLS-1$
118 private static final String LOADING_TAXA = Messages.ChecklistEditor_LOAD_TAXA;
119 private static final String UNKNOWN = Messages.ChecklistEditor_UNKNOWN;
120 private static final String ELEMENT_COUNT = Messages.ChecklistEditor_ELEMENT_COUNT;
121 public static final String TYPE_FILTER_TEXT = "type filter text"; //$NON-NLS-1$
122
123 static final String TAXON_COLUMN = "taxon_column"; //$NON-NLS-1$
124 static final String RANK_COLUMN = "collector_column";//$NON-NLS-1$
125 static final String SYNONYM_COLUMN = "synonym_column";//$NON-NLS-1$
126
127 private NatTable natTable;
128 private Label statusLabel;
129 private Label statusLabelSourceReference;
130 private Reference defaultSource;
131
132 private Map<Integer, NamedArea> areaToColumnIndexMap = new HashMap<>();
133 private int firstDataColumnIndex;
134
135 private ListDataProvider<TaxonDistributionDTO> bodyDataProvider;
136 private LinkedMap<String, String> propertyToLabelMap = new LinkedMap<>();
137
138 private boolean isShowRank = false;
139 private Text searchText;
140
141 private Button button3;
142 private Button button2;
143
144 protected EventList<TaxonDistributionDTO> taxonList;
145 private String actualNameCache;
146 protected Map<UUID, Map<NamedArea, Set<DescriptionElementBase>>> taxonDistributionMap = new HashMap<>();
147
148 protected List<TaxonDistributionDTO> descriptionsToSave = new ArrayList<>();
149
150 protected SortedSet<NamedArea> areas;
151 protected DistributionEditorPart part;
152 private BodyLayerStack<TaxonDistributionDTO> bodyLayerStack;
153 private FreezeLayer freezeLayer;
154 private ConfigRegistry configRegistry;
155 private AbstractLayer topMostLayer;
156
157 private SelectionLayer selectionLayer;
158
159 public DistributionEditor(Composite parent, DistributionEditorPart part) {
160 super(parent, SWT.NULL);
161 isShowRank = PreferencesUtil.getBooleanValue(PreferencePredicate.ShowRankInDistributionEditor.getKey());
162 this.part = part;
163 this.setLayout(new GridLayout());
164 GridLayoutFactory.fillDefaults().applyTo(parent);
165
166 Composite topComposite = new Composite(parent, SWT.NONE);
167 createTopComposite(topComposite);
168
169 natTable = new NatTable(parent, false);
170 parent.pack();
171
172 Composite bottomComposite = new Composite(parent, SWT.NONE);
173 GridLayoutFactory.fillDefaults().applyTo(bottomComposite);
174 createStatusBar(bottomComposite);
175 }
176
177 public boolean isShowRank() {
178 return isShowRank;
179 }
180
181 public void setShowRank(boolean isShowRank) {
182 this.isShowRank = isShowRank;
183 }
184
185 public int getFirstDataColumnIndex() {
186 return firstDataColumnIndex;
187 }
188
189 public void setFirstDataColumnIndex(int firstDataColumnIndex) {
190 this.firstDataColumnIndex = firstDataColumnIndex;
191 }
192
193 @Override
194 public String getActualNameCache() {
195 return actualNameCache;
196 }
197
198 public void setActualNameCache(String actualNameCache) {
199 this.actualNameCache = actualNameCache;
200 }
201
202 public LinkedMap<String, String> getPropertyToLabelMap() {
203 return propertyToLabelMap;
204 }
205
206 public void setPropertyToLabelMap(LinkedMap<String, String> propertyToLabelMap) {
207 this.propertyToLabelMap = propertyToLabelMap;
208 }
209
210 public Map<Integer, NamedArea> getAreaToColumnIndexMap() {
211 return areaToColumnIndexMap;
212 }
213
214 public void setAreaToColumnIndexMap(Map<Integer, NamedArea> areaToColumnIndexMap) {
215 this.areaToColumnIndexMap = areaToColumnIndexMap;
216 }
217
218 public List<TaxonDistributionDTO> getDescriptionsToSave() {
219 return descriptionsToSave;
220 }
221
222 public void setDescriptionsToSave(List<TaxonDistributionDTO> descriptionsToSave) {
223 this.descriptionsToSave = descriptionsToSave;
224 }
225
226 private void createStatusBar(Composite composite) {
227 GridData gridData = new GridData();
228 gridData.horizontalSpan = 2;
229 gridData.grabExcessHorizontalSpace = true;
230 gridData.horizontalAlignment = GridData.FILL;
231 GridLayout gridLayout = new GridLayout();
232 gridLayout.numColumns = 3;
233 composite.setLayoutData(gridData);
234 composite.setLayout(gridLayout);
235
236 gridData = new GridData();
237 gridData.horizontalSpan = 1;
238 gridData.grabExcessHorizontalSpace = true;
239 gridData.horizontalAlignment = GridData.FILL;
240
241 statusLabel = new Label(composite, SWT.LEFT);
242 statusLabel.setText(ELEMENT_COUNT + (taxonList != null ? taxonList.size() : UNKNOWN));
243 statusLabel.setLayoutData(gridData);
244
245 statusLabelSourceReference = new Label(composite, SWT.RIGHT);
246
247 statusLabelSourceReference.setLayoutData(gridData);
248
249 if (defaultSource != null) {
250 statusLabelSourceReference.setText(Messages.DistributionEditor_defaultSource
251 + (defaultSource.getAbbrevTitle() != null ? defaultSource.getAbbrevTitle()
252 : defaultSource.getAbbrevTitleCache()));
253 }
254
255 button3 = new Button(composite, SWT.PUSH);
256 button3.setEnabled(false);
257 GridData gridData3 = new GridData();
258 gridData3.horizontalAlignment = SWT.RIGHT;
259 button3.setLayoutData(gridData3);
260 // button3.setText(Messages.ChecklistEditor_REMOVE_DEFAULT_SOURCE);
261 button3.setImage(ImageResources.getImage(ImageResources.TRASH_ICON));
262 button3.setToolTipText(Messages.ChecklistEditor_REMOVE_DEFAULT_SOURCE_TOOLTIP);
263 button3.addSelectionListener(new SelectionAdapter() {
264
265 @Override
266 public void widgetSelected(SelectionEvent event) {
267 defaultSource = null;
268
269 String defaultSourceStr = (defaultSource == null) ? "" //$NON-NLS-1$
270 : Messages.DistributionEditor_defaultSource + defaultSource.getTitleCache();
271 if (defaultSourceStr.length() > 100) {
272 defaultSourceStr = defaultSourceStr.substring(0, 98) + "..."; //$NON-NLS-1$
273 }
274 statusLabelSourceReference.setText(defaultSourceStr);
275
276 button3.setBackground(AbstractUtility.getColor(Resources.COLOR_CONTROL_SELECTED));
277 button3.setEnabled(false);
278 button2.setText(Messages.ChecklistEditor_DEFAULT_SOURCE);
279 }
280
281 });
282 }
283
284 private void applyStyles() {
285 CdmModernNatTableThemeConfiguration configuration = new CdmModernNatTableThemeConfiguration();
286
287 // configuration.summaryRowHAlign = HorizontalAlignmentEnum.CENTER;
288 // NOTE: Getting the colors and fonts from the GUIHelper ensures that
289 // they are disposed properly (required by SWT)
290 configuration.cHeaderBgColor = GUIHelper.getColor(211, 211, 211);
291 configuration.rHeaderBgColor = GUIHelper.getColor(211, 211, 211);
292 natTable.addConfiguration(configuration);
293 }
294
295 private void configureNatTable(ConfigRegistry configRegistry, AbstractLayer topMostLayer) {
296 /**
297 * CONFIGURATION
298 */
299 natTable.setConfigRegistry(configRegistry);
300
301 // add default configuration because autoconfigure is set to false in
302 // constructor
303 natTable.addConfiguration(new DefaultNatTableStyleConfiguration());
304
305 natTable.addConfiguration(new DefaultColumnHeaderStyleConfiguration() {
306 {
307 TextPainter painter = new TextPainter();
308 painter.setCalculateByTextLength(true);
309 painter.setWrapText(false);
310
311 cellPainter = new BeveledBorderDecorator(painter);
312
313 }
314 });
315 // applyStyles();
316 // override the default sort configuration and change the mouse bindings
317 // to sort on a single click
318
319 natTable.addConfiguration(new SingleClickSortConfiguration());
320 natTable.addConfiguration(new FilterRowConfiguration(this));
321
322 // add the header menu configuration for adding the column header menu
323 // with hide/show actions
324 natTable.addConfiguration(new DistributionEditorHeaderMenuConfiguration(natTable));
325
326 // add custom configuration for data conversion and add column labels to
327 // viewport layer
328 topMostLayer.addConfiguration(new DistributionCellEditorDataConversionConfiguration(this));
329
330 applyStyles();
331 natTable.configure();
332 }
333
334 public void createTable() {
335 /**
336 * layers
337 */
338 createLayers();
339
340 /**
341 * configuration
342 */
343 configureNatTable(configRegistry, topMostLayer);
344
345 /**
346 * handlers and listeners
347 */
348 registerHandlersAndListeners(topMostLayer);
349 FreezeHelper.freeze(freezeLayer, bodyLayerStack.getViewPortLayer(),
350 new PositionCoordinate(bodyLayerStack.getViewPortLayer(), 0, 0),
351 new PositionCoordinate(bodyLayerStack.getViewPortLayer(), 0, -1));
352 // grab all space
353 GridDataFactory.fillDefaults().grab(true, true).applyTo(natTable);
354
355 this.layout();
356 natTable.doCommand(new ClientAreaResizeCommand(natTable));
357 // boolean ok = natTable.doCommand(new
358 // ClientAreaResizeCommand(natTable));
359 }
360
361 private void createLayers() {
362
363 DistributionColumnAccessor columnPropertyAccessor = new DistributionColumnAccessor(this);
364 DistributionEditorConfigLabelAccumulator labelAccumulator = new DistributionEditorConfigLabelAccumulator(this);
365
366 // bodyLayerStack = new BodyLayerStack<>(taxonList,
367 // columnPropertyAccessor, new TaxonDistributionDtoComparator(),
368 // labelAccumulator);
369 bodyLayerStack = new BodyLayerStack<>(taxonList, columnPropertyAccessor, null, labelAccumulator);
370 bodyDataProvider = bodyLayerStack.getBodyDataProvider();
371
372 propertyToLabelMap.put(TAXON_COLUMN, Messages.ChecklistEditor_TAXON);
373 if (isShowRank) {
374 propertyToLabelMap.put(RANK_COLUMN, Messages.ChecklistEditor_RANK);
375 propertyToLabelMap.put(SYNONYM_COLUMN, Messages.ChecklistEditor_SYNONYMS);
376 } else {
377 propertyToLabelMap.put(SYNONYM_COLUMN, Messages.ChecklistEditor_SYNONYMS);
378 }
379 configRegistry = new ConfigRegistry();
380
381 initLabels();
382 this.selectionLayer = bodyLayerStack.getSelectionLayer();
383
384 freezeLayer = new FreezeLayer(selectionLayer);
385 final CompositeFreezeLayer compositeFreezeLayer = new CompositeFreezeLayer(freezeLayer,
386 bodyLayerStack.getViewPortLayer(), selectionLayer);
387
388 // as the selection mouse bindings are registered for the region label
389 // GridRegion.BODY
390 // we need to set that region label to the viewport so the selection via
391 // mouse
392 // is working correctly
393 compositeFreezeLayer.setRegionName(GridRegion.BODY);
394
395 IDataProvider columnHeaderDataProvider = new DefaultColumnHeaderDataProvider(
396 propertyToLabelMap.values().toArray(new String[] {}), propertyToLabelMap);
397 DataLayer columnHeaderDataLayer = new DefaultColumnHeaderDataLayer(columnHeaderDataProvider);
398 ILayer columnHeaderLayer = new ColumnHeaderLayer(columnHeaderDataLayer, compositeFreezeLayer, selectionLayer);
399
400 FilterRowHeaderComposite<TaxonDistributionDTO> filterRowHeaderLayer = new FilterRowHeaderComposite<>(
401 new DefaultGlazedListsFilterStrategy<>(bodyLayerStack.getFilterList(), columnPropertyAccessor,
402 configRegistry),
403 columnHeaderLayer, columnHeaderDataLayer.getDataProvider(), configRegistry);
404
405 // build the row header layer stack
406 IDataProvider rowHeaderDataProvider = new DefaultRowHeaderDataProvider(bodyDataProvider);
407 DataLayer rowHeaderDataLayer = new DefaultRowHeaderDataLayer(rowHeaderDataProvider);
408 ILayer rowHeaderLayer = new RowHeaderLayer(rowHeaderDataLayer, compositeFreezeLayer, selectionLayer);
409
410 IDataProvider cornerDataProvider = new DefaultCornerDataProvider(columnHeaderDataProvider,
411 rowHeaderDataProvider);
412 DataLayer cornerDataLayer = new DataLayer(cornerDataProvider);
413 ILayer cornerLayer = new CornerLayer(cornerDataLayer, rowHeaderLayer, filterRowHeaderLayer);
414
415 GridLayer gridLayer = new GridLayer(compositeFreezeLayer, filterRowHeaderLayer, rowHeaderLayer, cornerLayer);
416
417 natTable.setLayer(gridLayer);
418 topMostLayer = compositeFreezeLayer;
419 }
420
421 private Text createSearchBar(Composite parent) {
422
423 Button button1 = new Button(parent, SWT.PUSH);
424 GridData gridData2 = new GridData();
425 gridData2.horizontalSpan = 1;
426 gridData2.horizontalAlignment = SWT.RIGHT;
427
428 button1.setLayoutData(gridData2);
429
430 button1.setText(Messages.ChecklistEditor_DIST_STATUS);
431 button1.setToolTipText(Messages.ChecklistEditor_DIST_STATUS_TOOLTIP);
432 button1.addSelectionListener(new SelectionAdapter() {
433 @Override
434 public void widgetSelected(SelectionEvent event) {
435 AvailableDistributionWizard availableDistributionWizard = new AvailableDistributionWizard();
436 WizardDialog dialog = new WizardDialog(AbstractUtility.getShell(), availableDistributionWizard);
437
438 int open = dialog.open();
439 if (open == 0) {
440 reload();
441 }
442 }
443 });
444
445 button2 = new Button(parent, SWT.PUSH);
446 GridData gridData3 = new GridData();
447 gridData3.horizontalAlignment = SWT.RIGHT;
448
449 button2.setLayoutData(gridData3);
450
451 button2.setText(Messages.ChecklistEditor_DEFAULT_SOURCE);
452 button2.setToolTipText(Messages.ChecklistEditor_DEFAULT_SOURCE_TOOLTIP);
453 button2.addSelectionListener(new SelectionAdapter() {
454
455 @Override
456 public void widgetSelected(SelectionEvent event) {
457 defaultSource = ReferenceSelectionDialog.select(AbstractUtility.getShell(), null);
458
459 String defaultSourceStr = (defaultSource == null) ? "" //$NON-NLS-1$
460 : Messages.DistributionEditor_defaultSource + defaultSource.getTitleCache();
461 if (defaultSourceStr.length() > 100) {
462 defaultSourceStr = defaultSourceStr.substring(0, 98) + "..."; //$NON-NLS-1$
463 }
464 statusLabelSourceReference.setText(defaultSourceStr);
465
466 button2.setBackground(AbstractUtility.getColor(Resources.COLOR_CONTROL_SELECTED));
467 // EventUtility.postEvent(WorkbenchEventConstants.REFRESH_DETAILS,
468 // true);
469 button3.setEnabled(true);
470 button2.setText(Messages.ChecklistEditor_SWITCH_DEFAULT_SOURCE);
471 }
472 });
473
474 parent.pack();
475 return searchText;
476 }
477
478 /**
479 * This method should only be called for adding new Distribution columns and
480 * reloading the table.<br>
481 * It will hide the old distribution column and load the newly added
482 * columns.<br>
483 * <p>
484 * <b>Notice:</b> for data update please use <b>refresh()</b>
485 *
486 */
487 public void reload() {
488 this.areaToColumnIndexMap.clear();
489 this.areas.clear();
490 this.propertyToLabelMap.clear();
491 createTable();
492 natTable.redraw();
493 }
494
495 private void createTopComposite(Composite parent) {
496 GridLayout gridLayout = new GridLayout(3, false);
497 gridLayout.marginWidth = 0;
498 gridLayout.marginHeight = 0;
499 GridData gridData2 = new GridData();
500 gridData2.horizontalSpan = 1;
501 gridData2.horizontalAlignment = SWT.RIGHT;
502 gridData2.horizontalIndent = 3;
503 parent.setLayoutData(gridData2);
504 parent.setLayout(gridLayout);
505 searchText = createSearchBar(parent);
506
507 }
508
509 public void loadDistributions(List<TaxonDistributionDTO> taxonList) {
510 if (this.taxonList == null) {
511 this.taxonList = new BasicEventList<>();
512 }
513 taxonList.stream().forEach(wrapper -> DistributionEditor.this.taxonList.add(wrapper));
514 statusLabel.setText(ELEMENT_COUNT + taxonList.size());
515 createTaxonDistributionMap();
516 }
517
518 protected void createTaxonDistributionMap() {
519 Iterator<TaxonDistributionDTO> iterator = this.taxonList.iterator();
520 while (iterator.hasNext()) {
521 TaxonDistributionDTO dto = iterator.next();
522 TaxonDescriptionDTO descriptionDto = dto.getDescriptionsWrapper();
523 for (TaxonDescription desc : descriptionDto.getDescriptions()) {
524 if (this.part.getCdmEntitySession() != null) {
525 this.part.getCdmEntitySession().load(desc, true);
526 }
527 for (DescriptionElementBase descElement : desc.getElements()) {
528 if (descElement instanceof Distribution) {
529 Map<NamedArea, Set<DescriptionElementBase>> distributionsMap = taxonDistributionMap
530 .get(dto.getTaxonUuid());
531
532 if (distributionsMap == null) {
533 distributionsMap = new HashMap<>();
534 taxonDistributionMap.put(dto.getTaxonUuid(), distributionsMap);
535 }
536 Set<DescriptionElementBase> distributions = distributionsMap
537 .get(((Distribution) descElement).getArea());
538 if (distributions == null) {
539 distributions = new HashSet<>();
540 distributionsMap.put(((Distribution) descElement).getArea(), distributions);
541 }
542 distributions.add(descElement);
543 }
544 }
545 }
546 }
547 }
548
549 private void initLabels() {
550
551 int index = 2;
552 if (isShowRank) {
553 index++;
554 }
555
556 loadNamedAreas();
557 if (areas == null) {
558 areas = new TreeSet<>();
559 }
560 for (DefinedTermBase<?> area : areas) {
561 this.areaToColumnIndexMap.put(index++, (NamedArea) area);
562 String areaLabel;
563 // TODO: adapt to preference
564 Representation rep = area.getPreferredRepresentation(CdmStore.getDefaultLanguage());
565 String label = rep.getLabel();
566 if (label == null) {
567 label = area.getTitleCache();
568 }
569 if (PreferencesUtil.isShowIdInVocabularyInChecklistEditor()) {
570 if (area.getIdInVocabulary() != null) {
571 areaLabel = area.getIdInVocabulary();
572 } else {
573 areaLabel = label;
574 }
575 } else if (PreferencesUtil.isShowSymbol1InChecklistEditor()) {
576 if (area.getSymbol() != null) {
577 areaLabel = area.getSymbol();
578 } else {
579 areaLabel = label;
580 }
581 } else if (PreferencesUtil.isShowSymbol2InChecklistEditor()) {
582 if (area.getSymbol2() != null) {
583 areaLabel = area.getSymbol2();
584 } else {
585 areaLabel = label;
586 }
587 } else {
588 areaLabel = label;
589 }
590
591 // String areaLabel = area.getLabel();
592 String property = area.getUuid().toString();
593 propertyToLabelMap.put(property, areaLabel);
594 }
595 }
596
597 private SortedSet<NamedArea> loadNamedAreas() {
598 // IPreferenceStore preferenceStore =
599 // PreferencesUtil.getPreferenceStore();
600
601 String valuesAreas = PreferencesUtil.getStringValue(PreferencePredicate.AvailableDistributionAreaTerms.getKey(),
602 true);
603 String values = PreferencesUtil
604 .getStringValue(PreferencePredicate.AvailableDistributionAreaVocabularies.getKey());
605 List<UUID> uuidList = new ArrayList<UUID>();
606 String[] split;
607 List<String> listValue;
608 List<NamedArea> termlist = new ArrayList<>();
609 if (values != null && values != "") { //$NON-NLS-1$
610 split = values.split(";"); //$NON-NLS-1$
611 listValue = Arrays.asList(split);
612
613 UUID uuid;
614 for (String s : listValue) {
615 uuid = UUID.fromString(s);
616 uuidList.add(uuid);
617 }
618 }
619
620 List<TermCollectionDto> vocs = new ArrayList<>();
621 ITermCollectionService service = CdmStore.getService(ITermCollectionService.class);
622 if (uuidList.isEmpty()) {
623 List<TermCollectionDto> vocList = service.findCollectionDtoByTermType(TermType.NamedArea);
624 vocs.addAll(vocList);
625 } else {
626 vocs = service.findTermCollectionDtoByUuids(uuidList);
627 }
628 Set<UUID> termUuids = new HashSet<UUID>();
629
630 ITermService termService = CdmStore.getService(ITermService.class);
631 for (TermCollectionDto voc : vocs) {
632 termUuids.addAll(voc.getTerms().stream().map(TermDto::getUuid).collect(Collectors.toList()));
633 }
634 termlist.addAll((List) termService.find(termUuids));
635 List<NamedArea> filteredList = new ArrayList<>();
636 if (valuesAreas != null && valuesAreas != "") {
637 split = valuesAreas.split(";"); //$NON-NLS-1$
638 listValue = Arrays.asList(split);
639
640 for (NamedArea area : termlist) {
641 if (listValue.contains(area.getUuid().toString())) {
642 filteredList.add(area);
643 }
644 }
645 } else {
646 filteredList.addAll(termlist);
647 }
648
649 TermOrder sortOrder = PreferencesUtil.getSortNamedAreasInDistributionEditor();
650 if (sortOrder.equals(TermOrder.Natural)) {
651 areas = getTermsOrderedByVocabularyOrder(filteredList);
652 } else if (sortOrder.equals(TermOrder.IdInVoc)) {
653 areas = getTermsOrderedByIdInVocabulary(filteredList);
654 } else {
655 areas = getTermsOrderedByLabels(filteredList, CdmStore.getDefaultLanguage());
656 }
657
658 return null;
659 }
660
661 public <T extends DefinedTermBase<T>> SortedSet<T> getTermsOrderedByLabels(List<T> listTerm, Language language) {
662 TermLanguageComparator<T> comp = new TermLanguageComparator<>(Language.DEFAULT(), language);
663 SortedSet<T> result = new TreeSet<>(comp);
664 if (listTerm != null) {
665 result.addAll(listTerm);
666 }
667
668 return result;
669 }
670
671 public <T extends DefinedTermBase<T>> SortedSet<T> getTermsOrderedByIdInVocabulary(List<T> namedAreas) {
672 TermIdInVocabularyComparator<T> comp = new TermIdInVocabularyComparator<>();
673
674 SortedSet<T> result = new TreeSet<>(comp);
675 if (namedAreas != null) {
676 result.addAll(namedAreas);
677 }
678 return result;
679 }
680
681 public <T extends DefinedTermBase<T>> SortedSet<T> getTermsOrderedBySymbol(List<T> namedAreas) {
682 TermSymbol1Comparator<T> comp = new TermSymbol1Comparator<>();
683
684 SortedSet<T> result = new TreeSet<>(comp);
685 if (namedAreas != null) {
686 result.addAll(namedAreas);
687 }
688 return result;
689 }
690
691 public <T extends DefinedTermBase<T>> SortedSet<T> getTermsOrderedBySymbol2(List<T> namedAreas) {
692 TermSymbol2Comparator<T> comp = new TermSymbol2Comparator<>();
693
694 SortedSet<T> result = new TreeSet<>(comp);
695 if (namedAreas != null) {
696 result.addAll(namedAreas);
697 }
698 return result;
699 }
700
701 public <T extends DefinedTermBase<T>> SortedSet<T> getTermsOrderedByVocabularyOrder(List<T> listAreas) {
702 OrderedTermComparator<T> comp = new OrderedTermComparator<>();
703 boolean allOrderedTerms = true;
704 List<TermVocabulary<T>> alreadyOrderIndexNull = new ArrayList<>();
705 for (T term : listAreas) {
706 if (!(term.isOrderRelevant())) {
707 allOrderedTerms = false;
708 break;
709 } else if (term.getOrderIndex() == 0) {
710 // Note by AM: when does orderIndex == 0 happen?
711 if (alreadyOrderIndexNull.contains(term.getVocabulary())) {
712 allOrderedTerms = false;
713 break;
714 } else {
715 alreadyOrderIndexNull.add(term.getVocabulary());
716 }
717 }
718 }
719 if (allOrderedTerms) {
720 SortedSet<T> result = new TreeSet<>(comp);
721 result.addAll(listAreas);
722 return result;
723 } else {
724 return getTermsOrderedByLabels(listAreas, PreferencesUtil.getGlobalLanguage());
725 }
726 }
727
728 private void registerHandlersAndListeners(AbstractLayer topMostLayer) {
729 // selection listener
730 E4SelectionListener<?> selectionListener = new DistributionCellSelectionListener(part.getSelectionService(),
731 selectionLayer, bodyDataProvider, part);
732 selectionLayer.addLayerListener(selectionListener);
733 selectionListener.setFullySelectedRowsOnly(false);
734
735 // register handler for view configuration menu
736 // natTable.registerCommandHandler(toolbar.getDisplayPersistenceDialogCommandHandler());
737 }
738
739 public IRowDataProvider<TaxonDistributionDTO> getBodyDataProvider() {
740 return bodyDataProvider;
741 }
742
743 public void setDirty() {
744 part.setDirty();
745 }
746
747 @Override
748 public Reference getDefaultSource() {
749 return defaultSource;
750 }
751
752 // /**
753 // * @param result
754 // */
755 // public void reloadDistributions() {
756 // loadDistributions(taxonList);
757 //
758 // }
759 }