Project

General

Profile

Download (13 KB) Statistics
| Branch: | Tag: | Revision:
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.view.webimport.termimport;
10

    
11
import java.util.ArrayList;
12
import java.util.Collection;
13
import java.util.Collections;
14
import java.util.Comparator;
15
import java.util.HashSet;
16
import java.util.Iterator;
17
import java.util.List;
18
import java.util.stream.Collectors;
19

    
20
import org.eclipse.core.runtime.IProgressMonitor;
21
import org.eclipse.core.runtime.IStatus;
22
import org.eclipse.core.runtime.Status;
23
import org.eclipse.core.runtime.jobs.Job;
24
import org.eclipse.e4.ui.di.UISynchronize;
25
import org.eclipse.jface.util.LocalSelectionTransfer;
26
import org.eclipse.jface.viewers.ISelection;
27
import org.eclipse.jface.viewers.IStructuredSelection;
28
import org.eclipse.jface.viewers.StructuredSelection;
29
import org.eclipse.jface.window.Window;
30
import org.eclipse.swt.SWT;
31
import org.eclipse.swt.dnd.DND;
32
import org.eclipse.swt.dnd.DragSourceAdapter;
33
import org.eclipse.swt.dnd.DragSourceEvent;
34
import org.eclipse.swt.dnd.Transfer;
35
import org.eclipse.swt.events.FocusEvent;
36
import org.eclipse.swt.events.FocusListener;
37
import org.eclipse.swt.events.KeyAdapter;
38
import org.eclipse.swt.events.KeyEvent;
39
import org.eclipse.swt.events.SelectionAdapter;
40
import org.eclipse.swt.events.SelectionEvent;
41

    
42
import eu.etaxonomy.cdm.common.CdmUtils;
43
import eu.etaxonomy.taxeditor.l10n.Messages;
44
import eu.etaxonomy.taxeditor.model.ColorResources;
45
import eu.etaxonomy.taxeditor.model.MessagingUtils;
46
import eu.etaxonomy.taxeditor.preference.Resources;
47
import eu.etaxonomy.taxeditor.view.webimport.termimport.parser.TermParser;
48
import eu.etaxonomy.taxeditor.view.webimport.termimport.parser.TerminologyParser;
49
import eu.etaxonomy.taxeditor.view.webimport.termimport.requests.RequestSearch;
50
import eu.etaxonomy.taxeditor.view.webimport.termimport.requests.RequestTerminologies;
51
import eu.etaxonomy.taxeditor.view.webimport.termimport.wrapper.OntologyTermWrapper;
52
import eu.etaxonomy.taxeditor.view.webimport.termimport.wrapper.TerminologyWrapper;
53

    
54
/**
55
 * @author pplitzner
56
 * @since Apr 23, 2018
57
 *
58
 */
59
public class GfBioTerminologyImportPresenter {
60

    
61
    public static final String NO_CONNECTION_TITLE = Messages.GfBioTerminologyImportPresenter_NO_CONNECTION_TITLE;
62
    public static final String NO_CONNECTION_MESSAGE = Messages.GfBioTerminologyImportPresenter_NO_CONNECTION_MESSAGE;
63
    private static final String TXT_SEARCH_DEFAULT = Messages.GfBioTerminologyImportPresenter_TEXT_SEARCH_DEFAULT;
64

    
65
    private GfBioTerminologyImportComposite composite;
66
    private Collection<TerminologyWrapper> selectedOntologies = new ArrayList<>();
67
    private UISynchronize sync;
68
    private volatile Collection<TerminologyWrapper> availableOntologies = new HashSet<>();
69

    
70
    public GfBioTerminologyImportPresenter(GfBioTerminologyImportComposite composite, UISynchronize sync) {
71
        super();
72
        this.composite = composite;
73
        this.sync = sync;
74

    
75
        requestAvailableOntologies();
76

    
77
        composite.getBtnSearch().addSelectionListener(new SelectionAdapter() {
78
            @Override
79
            public void widgetSelected(SelectionEvent e) {
80
                if(e.widget==composite.getBtnSearch()){
81
                    search();
82
                }
83
            }
84
        });
85

    
86
        //text search
87
        composite.getTxtSearch().addKeyListener(new KeyAdapter() {
88
            @Override
89
            public void keyPressed(KeyEvent e) {
90
                if(e.keyCode==SWT.CR){
91
                    search();
92
                }
93
            }
94
        });
95
        composite.getTxtSearch().setText(TXT_SEARCH_DEFAULT);
96
        composite.getTxtSearch().setForeground(ColorResources.getColor(Resources.SEARCH_VIEW_FOREGROUND));
97
        composite.getTxtSearch().addFocusListener(new FocusListener() {
98

    
99
            @Override
100
            public void focusGained(FocusEvent e) {
101
                composite.getTxtSearch().setForeground(ColorResources.getColor(Resources.SEARCH_VIEW_FOCUS));
102
                if (TXT_SEARCH_DEFAULT.equals(composite.getTxtSearch().getText())) {
103
                    composite.getTxtSearch().setText(""); //$NON-NLS-1$
104
                }
105
            }
106

    
107
            @Override
108
            public void focusLost(FocusEvent e) {
109
                if (CdmUtils.isBlank(composite.getTxtSearch().getText())) {
110
                    composite.getTxtSearch().setForeground(ColorResources.getColor(Resources.SEARCH_VIEW_FOREGROUND));
111
                    composite.getTxtSearch().setText(TXT_SEARCH_DEFAULT);
112
                }
113
            }
114
        });
115

    
116

    
117
        composite.getBtnChooseOntology().addSelectionListener(new SelectionAdapter() {
118
            @Override
119
            public void widgetSelected(SelectionEvent e) {
120
                if(availableOntologies.isEmpty()
121
                        && MessagingUtils.confirmDialog("No Ontologies available", "There are no ontologies available. They have either not been loaded yet or the terminology service can not be reached.\nDo you want to retry loading the ontologies?")){
122
                    //re-check if ontologies have been loaded in the meantime
123
                    if(availableOntologies.isEmpty()){
124
                        requestAvailableOntologies();
125
                    }
126
                    else{
127
                        openOntologySelectionDialog(composite);
128
                    }
129
                }
130
                else{
131
                    openOntologySelectionDialog(composite);
132
                }
133
            }
134

    
135
            private void openOntologySelectionDialog(GfBioTerminologyImportComposite composite) {
136
                OntologySelectionDialog dialog = new OntologySelectionDialog(composite.getShell(), selectedOntologies, availableOntologies);
137
                if(dialog.open()==Window.OK){
138
                    selectedOntologies = dialog.getSelectedOntologies();
139
                    composite.getTextOntologies().setText(selectedOntologies.stream()
140
                            .map(wrapper->wrapper.getAcronym())
141
                            .collect(Collectors.joining(", ")));
142
                }
143
            }
144
        });
145

    
146
        //vocabulary combo
147
        composite.getBtnRemoveVocabulary().addSelectionListener(new SelectionAdapter() {
148
            @Override
149
            public void widgetSelected(SelectionEvent e) {
150
                composite.getTermVocabularyComboViewer().setElement(null);
151
            }
152
        });
153

    
154
        composite.getTreeTermHierarchy().setContentProvider(new OntologyTermContentProvider());
155
        composite.getTreeTermHierarchy().setLabelProvider(new OntologyTermLabelProvider());
156

    
157
        //tree results
158
        composite.getTreeTermHierarchy().addSelectionChangedListener(e->updateDetails(e.getSelection()));
159
        composite.getTreeTermHierarchy().setContentProvider(new OntologyTermContentProvider());
160
        composite.getTreeTermHierarchy().setLabelProvider(new OntologyTermLabelProvider());
161
        Transfer[] transfers = new Transfer[] {LocalSelectionTransfer.getTransfer(),};
162
        composite.getTreeTermHierarchy().addDragSupport(DND.DROP_MOVE,
163
                transfers, new DragSourceAdapter() {
164

    
165
            @Override
166
            public void dragSetData(DragSourceEvent event) {
167
                if (LocalSelectionTransfer.getTransfer().isSupportedType(event.dataType)) {
168
                    IStructuredSelection selection = (IStructuredSelection) composite.getTreeTermHierarchy().getSelection();
169
                    selection.toList().stream()
170
                    .filter(item->item instanceof OntologyTermWrapper)
171
                    .forEach(wrapper->((OntologyTermWrapper)wrapper).setTermVocabulary(composite.getTermVocabularyComboViewer().getSelection()));
172
                    LocalSelectionTransfer.getTransfer().setSelection(selection);
173
                }
174
            }
175
            @Override
176
            public void dragStart(DragSourceEvent event) {
177
                event.doit = !composite.getTreeTermHierarchy().getSelection().isEmpty();
178
            }
179
        });
180
    }
181

    
182
    private void requestAvailableOntologies() {
183
        Job requestOntologiesJob = new Job("Request available ontologies") {
184

    
185
            @Override
186
            protected IStatus run(IProgressMonitor monitor) {
187
                String response = new RequestTerminologies().request();
188
                availableOntologies = TerminologyParser.parse(response);
189
                return Status.OK_STATUS;
190
            }
191
        };
192
        requestOntologiesJob.schedule();
193
    }
194

    
195
    private OntologyTermWrapper getSelectedTerm(IStructuredSelection selection){
196
        Iterator iterator = selection.iterator();
197
        if(iterator.hasNext()){
198
            Object next = iterator.next();
199
            if(next instanceof OntologyTermWrapper){
200
                return (OntologyTermWrapper) next;
201
            }
202
        }
203
        return null;
204
    }
205

    
206
    private void clearDetails(){
207
        composite.getLblLabel().setText(""); //$NON-NLS-1$
208
        composite.getLblUri().setText(""); //$NON-NLS-1$
209
        composite.getLblDescription().setText(""); //$NON-NLS-1$
210
        composite.getListSynonyms().getList().removeAll();
211
    }
212

    
213
    private void updateDetails(ISelection s) {
214
        StructuredSelection selection = (StructuredSelection)s;
215
        if(selection.isEmpty()){
216
            clearDetails();
217
        }
218
        OntologyTermWrapper wrapper = getSelectedTerm(selection);
219
        if(wrapper!=null){
220
            String label = wrapper.getLabel();
221
            String uri = wrapper.getUri();
222
            String description = wrapper.getDescription();
223
            composite.getLblLabel().setText(label!=null?label:""); //$NON-NLS-1$
224
            composite.getLblUri().setText(uri!=null?uri:""); //$NON-NLS-1$
225
            composite.getLblDescription().setText(description!=null?description:""); //$NON-NLS-1$
226
            composite.getListSynonyms().getList().removeAll();
227
            if(wrapper.getSynonyms()!=null){
228
                wrapper.getSynonyms().forEach(syn->composite.getListSynonyms().add(syn));
229
            }
230
        }
231
    }
232

    
233
    private void search(){
234
        //clear result count
235
        composite.getLblResultCount().setText("Searching...");
236

    
237
        String searchString = composite.getTxtSearch().getText();
238
        if(searchString.equals(TXT_SEARCH_DEFAULT)){
239
            return;
240
        }
241
        if(selectedOntologies.isEmpty() && !MessagingUtils.confirmDialog("Long running operation", "You have not selected any specific ontology. This search may take a long time.\n\nDo you want to continue?")){
242
            return;
243
        }
244
        Job searchJob = new Job("Search Ontologies") {
245

    
246
            @Override
247
            protected IStatus run(IProgressMonitor monitor) {
248
                String response = new RequestSearch(searchString, selectedOntologies).request();
249
                if(response==null){
250
                    MessagingUtils.informationDialog(NO_CONNECTION_TITLE, NO_CONNECTION_MESSAGE);
251
                    return Status.CANCEL_STATUS;
252
                }
253
                final List<OntologyTermWrapper> wrapperList = new ArrayList<>();
254
                wrapperList.addAll(TermParser.parse(response));
255
                if(wrapperList.isEmpty()){
256
                    MessagingUtils.informationDialog(Messages.GfBioTerminologyImportPresenter_NO_RESULTS_TITLE, Messages.GfBioTerminologyImportPresenter_NO_RESULTS_MESSAGE);
257
                }
258
                //sort list
259
                Collections.sort(wrapperList, new TermWrapperComparator(searchString));
260
                sync.syncExec(() -> {
261
                    composite.getTreeTermHierarchy().setInput(wrapperList);
262
                    composite.getLblResultCount().setText(Integer.toString(wrapperList.size()));
263
                });
264
                return Status.OK_STATUS;
265
            }
266
        };
267
       searchJob.schedule();
268
    }
269

    
270
    private final class TermWrapperComparator implements Comparator<OntologyTermWrapper> {
271
        private final String searchString;
272

    
273
        public TermWrapperComparator(String searchString) {
274
            super();
275
            this.searchString = searchString;
276
        }
277

    
278
        @Override
279
        public int compare(OntologyTermWrapper o1, OntologyTermWrapper o2) {
280
            //remove wildcards from search string
281
            String trimmedSearch = searchString.replace("*", "");
282
            String label1 = o1.getLabel();
283
            String label2 = o2.getLabel();
284
            //1. search string at the beginning
285
            if(label1.startsWith(trimmedSearch)){
286
                if(!label2.startsWith(trimmedSearch)){
287
                    return -1;
288
                }
289
                else{
290
                    return label1.compareTo(label2);
291
                }
292
            }
293
            else if(label2.startsWith(trimmedSearch)){
294
                return 1;
295
            }
296
            //2. label that contains search string
297
            if(label1.contains(trimmedSearch)){
298
                if(!label2.contains(trimmedSearch)){
299
                    return -1;
300
                }
301
            }
302
            else if(label2.contains(trimmedSearch)){
303
                return 1;
304
            }
305
            return label1.compareTo(label2);
306
        }
307
    }
308

    
309
}
(3-3/7)