Project

General

Profile

Download (14.5 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2017 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.ui.combo.term;
10

    
11
import java.util.ArrayList;
12
import java.util.Arrays;
13
import java.util.Collections;
14
import java.util.Comparator;
15
import java.util.List;
16

    
17
import org.apache.commons.lang3.StringUtils;
18
import org.eclipse.jface.util.PropertyChangeEvent;
19
import org.eclipse.swt.SWT;
20
import org.eclipse.swt.events.SelectionEvent;
21
import org.eclipse.swt.widgets.Listener;
22

    
23
import eu.etaxonomy.cdm.model.term.DefinedTermBase;
24
import eu.etaxonomy.cdm.model.term.TermType;
25
import eu.etaxonomy.cdm.model.term.TermVocabulary;
26
import eu.etaxonomy.cdm.persistence.dto.TermDto;
27
import eu.etaxonomy.taxeditor.model.DefaultTermComparator;
28
import eu.etaxonomy.taxeditor.model.MessagingUtils;
29
import eu.etaxonomy.taxeditor.preference.IPreferenceKeys;
30
import eu.etaxonomy.taxeditor.preference.PreferencesUtil;
31
import eu.etaxonomy.taxeditor.store.CdmStore;
32
import eu.etaxonomy.taxeditor.store.TermManager;
33
import eu.etaxonomy.taxeditor.ui.combo.AbstractComboElement;
34
import eu.etaxonomy.taxeditor.ui.element.CdmFormFactory;
35
import eu.etaxonomy.taxeditor.ui.element.CdmPropertyChangeEvent;
36
import eu.etaxonomy.taxeditor.ui.element.ICdmFormElement;
37

    
38
/**
39
 * @author n.hoffmann
40
 * @created Nov 5, 2009
41
 */
42
public class TermComboElement<T extends DefinedTermBase>
43
		extends AbstractComboElement<T> {
44

    
45
	private T emptyElement;
46
	private static String EMPTY_ELEMENT_LABEL = "";
47

    
48
	private ArrayList<T> terms;
49

    
50
	public List<T> getTerms() {
51
        return terms;
52
    }
53

    
54
    private Comparator<T> termComparator;
55

    
56
	public Comparator<T> getTermComparator() {
57
		return termComparator;
58
	}
59

    
60
	public void setTermComparator(Comparator<T> termComparator) {
61
		this.termComparator = termComparator;
62
		populateTerms();
63
	}
64

    
65
	private final TermType termType;
66
	@SuppressWarnings("rawtypes")
67
    private final TermVocabulary termVocabulary;
68
	private final Class<T> termClass;
69

    
70
	private List<T> customPreferredTerms;
71

    
72
	private boolean useAbbrevLabel = false;
73
	private boolean addEmptyElement;
74

    
75
	public TermComboElement(CdmFormFactory formFactory,
76
			ICdmFormElement parentElement, TermType termType, String labelString, T selection, boolean addEmptyElement,
77
			int style, boolean useAbbrevLabel, Comparator<T> comparator) {
78
		this(formFactory, parentElement, null, termType, null, null, labelString, selection, addEmptyElement, style, useAbbrevLabel, comparator);
79
	}
80

    
81
	public TermComboElement(CdmFormFactory formFactory,
82
            ICdmFormElement parentElement, TermType termType, String labelString, TermDto selection, boolean addEmptyElement,
83
            int style, boolean useAbbrevLabel, Comparator<T> comparator) {
84
        this(formFactory, parentElement, null, termType, null, null, labelString, selection, addEmptyElement, style, useAbbrevLabel, comparator);
85
    }
86

    
87
	public TermComboElement(CdmFormFactory formFactory,
88
	        ICdmFormElement parentElement, TermVocabulary<?> termVocabulary, String labelString, T selection, boolean addEmptyElement,
89
	        int style, boolean useAbbrevLabel, Comparator<T> comparator) {
90
	    this(formFactory, parentElement, null, null, termVocabulary, null,labelString, selection, addEmptyElement, style, useAbbrevLabel, comparator);
91
	}
92

    
93
    public TermComboElement(CdmFormFactory formFactory,
94
            ICdmFormElement parentElement, Class<T> termClass, String labelString, T selection, boolean addEmptyElement,
95
            int style) {
96
        this(formFactory, parentElement, termClass, null, null, null, labelString, selection, addEmptyElement, style, false, null);
97
    }
98

    
99
    public TermComboElement(CdmFormFactory formFactory,
100
            ICdmFormElement parentElement, Class<T> termClass, String labelString, T selection, boolean addEmptyElement,
101
            int style, boolean useAbbrevLabel) {
102
        this(formFactory, parentElement, termClass, null, null, null, labelString, selection, addEmptyElement, style, useAbbrevLabel, null);
103
    }
104

    
105
    public TermComboElement(CdmFormFactory formFactory,
106
            ICdmFormElement parentElement, List<T> terms, String labelString, T selection, boolean addEmptyElement,
107
            int style, boolean useAbbrevLabel, Comparator<T> comparator) {
108
        this(formFactory, parentElement, null, null, null, terms,labelString, selection, addEmptyElement, style, useAbbrevLabel, comparator);
109
    }
110

    
111
	private TermComboElement(CdmFormFactory formFactory,
112
	        ICdmFormElement parentElement, Class<T> termClass, TermType termType, TermVocabulary<?> termVocabulary, List<T> terms,String labelString, T selection, boolean addEmptyElement,
113
	        int style, boolean useAbbrevLabel, Comparator<T> comparator) {
114

    
115
	    super(formFactory, parentElement);
116

    
117
        this.termVocabulary = termVocabulary;
118
        this.termClass = termClass;
119
        this.addEmptyElement = addEmptyElement;
120
        this.useAbbrevLabel = useAbbrevLabel;
121
        this.termComparator = comparator;
122
        if (labelString != null) {
123
            label.setText(labelString);
124
        }
125
        this.selection = selection;
126

    
127
        if(termType!=null){
128
            //TODO try to remove generic T and avoid classes to be used
129
        	addTerms((List<T>) getTermManager().getPreferredTerms(termType));
130
        }
131
        else if(termVocabulary!=null){
132
            addTerms((List<T>) getTermManager().getPreferredTerms(termVocabulary));
133
        }
134
        else if(this.termClass!=null){
135
            addTerms(getPreferredTerms());
136
        }else if (terms != null){
137
            addTerms(terms);
138
        }
139
        if (termType == null && terms != null && !terms.isEmpty()){
140
        	this.termType = terms.get(0).getTermType();
141
        }else{
142
        	this.termType = termType;
143
        }
144

    
145
        addContentProposalAdapter();
146
        combo.addSelectionListener(this);
147
        combo.addDisposeListener(this);
148
        if (comparator == null){
149
            setTermComparator(new DefaultTermComparator<>());
150
        }else{
151
        	populateTerms();
152
        }
153

    
154
        PreferencesUtil.getPreferenceStore().addPropertyChangeListener(this);
155

    
156
        if (selection != null) {
157
            setSelection(selection);
158
        }
159
	}
160

    
161
	protected void addTerms(List<T> preferredTerms) {
162
		terms = new ArrayList<>();
163
		Collections.sort(preferredTerms, termComparator);
164
		if(addEmptyElement){
165
		    // Add an empty element for when nothing was selected yet
166
		    combo.add(EMPTY_ELEMENT_LABEL);
167
		    terms.add(emptyElement);
168
		}
169
		for (T term: preferredTerms){
170
			terms.add(term);
171
		}
172
	}
173

    
174
	private TermComboElement(CdmFormFactory formFactory,
175
            ICdmFormElement parentElement, Class<T> termClass, TermType termType, TermVocabulary<?> termVocabulary, List<T> terms,String labelString, TermDto selection, boolean addEmptyElement,
176
            int style, boolean useAbbrevLabel, Comparator<T> comparator) {
177
        super(formFactory, parentElement);
178

    
179
        this.termVocabulary = termVocabulary;
180
        this.termClass = termClass;
181
        this.addEmptyElement = addEmptyElement;
182
        this.useAbbrevLabel = useAbbrevLabel;
183
        this.termComparator = comparator;
184
        if (labelString != null) {
185
            label.setText(labelString);
186
        }
187

    
188
        if(termType!=null){
189
            //TODO try to remove generic T and avoid classes to be used
190
            addTerms((List<T>) getTermManager().getPreferredTerms(termType));
191
        }
192
        else if(termVocabulary!=null){
193
            addTerms((List<T>) getTermManager().getPreferredTerms(termVocabulary));
194
        }
195
        else if(this.termClass!=null){
196
            addTerms(getPreferredTerms());
197
        }else if (terms != null && !terms.isEmpty()){
198
            addTerms(terms);
199

    
200
        }
201
        if (termType == null){
202
        	this.termType = terms.get(0).getTermType();
203
        }else{
204
        	this.termType = termType;
205
        }
206

    
207
        addContentProposalAdapter();
208
        combo.addSelectionListener(this);
209
        combo.addDisposeListener(this);
210
        if (comparator == null){
211
            setTermComparator(new DefaultTermComparator<T>());
212
        }else{
213
        	populateTerms();
214
        }
215
        PreferencesUtil.getPreferenceStore().addPropertyChangeListener(this);
216
        if (this.terms != null && selection != null){
217
            for (T term: this.terms){
218
                if (term != null && term.getUuid().equals(selection.getUuid())){
219
                    this.selection = term;
220
                }
221
            }
222
        }
223
        if (this.selection != null) {
224
            setSelection(this.selection);
225
        }
226
    }
227

    
228
	/**
229
	 * <p>Sets the selection of the combo to the given T object.</p>
230
	 * <p>Passing <code>null</code> to this method will set the selection to
231
	 * the empty element and effectively clear the selection</p>
232
	 *
233
	 * @param selection
234
	 *            a T object or <code>null</code> to clear the selection
235
	 */
236
	@Override
237
    public void setSelection(T selection) {
238
		this.selection = selection;
239

    
240
		Listener[] listeners = combo.getListeners(SWT.Selection);
241

    
242
		for (Listener listener : listeners) {
243
			combo.removeListener(SWT.Selection, listener);
244
		}
245
		int selectedIndex;
246
		if(selection == null){
247
			// set selection to the emptyElement
248
			selectedIndex = 0;
249
		}else{
250
			selectedIndex = terms.indexOf(selection);
251
			if (selectedIndex == -1) {
252
				createTermNotInPreferredTerms(selection, this.terms);
253
				selectedIndex = terms.indexOf(selection);
254
			}
255
		}
256

    
257

    
258
		for (Listener listener : listeners) {
259
			combo.addListener(SWT.Selection, listener);
260
		}
261
		combo.select(selectedIndex);
262

    
263
	}
264

    
265
	public void setSelectionDto(TermDto selection) {
266
        int selectedIndex = 0;
267
        if(selection == null){
268
            // set selection to the emptyElement
269
            selectedIndex = 0;
270
        }else{
271
            for (T term: terms){
272
                if (term != null && term.getUuid().equals(selection.getUuid())){
273
                    selectedIndex = terms.indexOf(term);
274
                }
275
            }
276
        }
277
        if (selectedIndex > -1) {
278
            combo.select(selectedIndex);
279
        }
280
    }
281

    
282
	/**
283
	 * Fills the combo with elements and sets up the convenience functions
284
	 * for selection index
285
	 *
286
	 * @param preferredTerms
287
	 */
288
	protected void populateTerms() {
289
		combo.removeAll();
290
		int i = 1;
291
		int index = 0;
292

    
293
		if(addEmptyElement){
294
		    // Add an empty element for when nothing was selected yet
295
		    combo.add(EMPTY_ELEMENT_LABEL);
296
		}
297
		List<T> withoutNull = new ArrayList<>(terms);
298

    
299
		if (termComparator != null) {
300
			if (addEmptyElement){
301
				withoutNull = terms.subList(1, terms.size());
302
			}
303
		}
304
		for (T term : withoutNull) {
305
			String label = getLabel(term);
306
			if (label == null) {
307
				if (term.getTitleCache() != null) {
308
					label = term.getTitleCache();
309
					MessagingUtils.warn(getClass(),
310
							"Term does not have a default language representation: " + label
311
									+ ", " + term.getUuid());
312
				} else {
313
					label = "Unknown";
314
					MessagingUtils.warn(getClass(),
315
							"Representation Label and TitleCache empty for term: "
316
									+ term + ", " + term.getUuid());
317
				}
318

    
319
			}
320
			combo.add(label);
321
			combo.setData(label, term);
322
			i++;
323
			if (selection != null) {
324
				if (selection.equals(term)) {
325
					index = i;
326
				}
327
			}
328
		}
329
        if (selection != null && index == 0) {
330
			createTermNotInPreferredTerms(selection, terms);
331
		}
332

    
333
		combo.select(index);
334
	}
335

    
336
	protected List<T> getPreferredTerms(){
337
	    List<T> preferredTerms = new ArrayList<>();
338
		if (customPreferredTerms != null){
339
			return customPreferredTerms;
340
		}
341
		else if(termType!=null){
342
		    preferredTerms = getTermManager().getPreferredTerms(termType);
343
		}
344
		else if(termVocabulary!=null){
345
		    preferredTerms = getTermManager().getPreferredTerms(termVocabulary);
346
		}
347
		if(termClass!=null){
348
		    preferredTerms = getTermManager().getPreferredTerms(termClass);
349
		}
350
		return preferredTerms;
351
	}
352

    
353
	/**
354
	 * May be overridden by derived classes if the desired label string does not
355
	 * reside in term.getLabel();
356
	 *
357
	 * @param term
358
	 *            a T object.
359
	 * @return a {@link java.lang.String} object.
360
	 */
361
	protected String getLabel(T term) {
362
		if (term == null){
363
			return "";
364
		}else{
365
			String termLabel = null;
366
			if (useAbbrevLabel){
367
			    if (!StringUtils.isBlank(term.getIdInVocabulary())){
368
			        termLabel = term.getIdInVocabulary();
369
			    }
370
			}
371
			if (termLabel == null){
372
				termLabel = term.getLabel(CdmStore.getDefaultLanguage());
373
			}
374
			if (termLabel == null){
375
			    termLabel = term.getLabel();
376
			}
377
			if(PreferencesUtil.getBooleanValue(IPreferenceKeys.SHOW_VOCABULARY_ID_FOR_TERM_LABELS)
378
			    && term.getVocabulary()!=null){
379
			    String vocLabel = term.getVocabulary().getLabel(CdmStore.getDefaultLanguage());
380
			    if (vocLabel == null){
381
			        vocLabel = term.getVocabulary().getLabel();
382
			    }
383
			    termLabel += " ["+vocLabel+"]";
384
			}
385
            return termLabel;
386
		}
387
	}
388

    
389
	private void createTermNotInPreferredTerms(T term, List<T> preferredTerms) {
390
		terms.add(term);
391
		populateTerms();
392
	}
393

    
394
	@Override
395
    public void widgetSelected(SelectionEvent e) {
396
	    if (e.getSource().equals(combo) && combo.getSelectionIndex() >= 0){
397
	    	int index = combo.getSelectionIndex();
398
	        selection = terms.get(combo.getSelectionIndex());
399
	        firePropertyChangeEvent(new CdmPropertyChangeEvent(this, e));
400
	    }
401
	}
402

    
403
	@Override
404
    public void propertyChange(PropertyChangeEvent event) {
405
		super.propertyChange(event);
406
		T selection = this.selection;
407
		if (event != null
408
				&& PreferencesUtil.PREFERRED_TERMS_CHANGE.equals(event
409
						.getProperty())) {
410
			addTerms(getPreferredTerms());
411
			populateTerms();
412
		}
413
		this.setSelection(selection);
414
	}
415

    
416
	protected TermManager getTermManager() {
417
		return CdmStore.getTermManager();
418
	}
419

    
420
	public int getVisibleItemCount(){
421
		return combo.getVisibleItemCount();
422
	}
423

    
424
	/**
425
	 * <p>A {@link List} of term objects may be passed to this combo box. In this case, the default behaviour
426
	 * of displaying the preferred terms for the T type will be overridden and the combo will only display the
427
	 * given terms. Also, any previous selection will be reseted.</p>
428
	 *
429
	 * <p>To return to the default of displaying the preferred terms, simply pass <code>null</code>.</p>
430
	 *
431
	 * @param terms a {@link List} of T objects or <code>null</code> for default preferred terms
432
	 */
433
	public void setTerms(List<T> terms) {
434
		customPreferredTerms = terms;
435
		addTerms(customPreferredTerms);
436
		populateTerms();
437
	}
438

    
439
	public void removeEmptyElement(){
440
	    if(addEmptyElement){
441
	        if(terms.contains(emptyElement)){
442
	            terms.remove(emptyElement);
443
	        }
444
	        if(Arrays.asList(combo.getItems()).contains(EMPTY_ELEMENT_LABEL)){
445
	            combo.remove(EMPTY_ELEMENT_LABEL);
446
	        }
447
	    }
448
	}
449
}
(1-1/4)