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
 * @param <T>
42
 */
43
public class TermComboElement<T extends DefinedTermBase>
44
		extends AbstractComboElement<T> {
45

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

    
49
	private ArrayList<T> terms;
50

    
51
	public ArrayList<T> getTerms() {
52
        return terms;
53
    }
54

    
55
    private Comparator<T> termComparator;
56

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

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

    
66
	private final TermType termType;
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
        super(formFactory, parentElement);
115

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
256

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

    
262
	}
263

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

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

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

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

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

    
332
		combo.select(index);
333
	}
334

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

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

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

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

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

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

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

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

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