Merge branch 'hotfix/3.12.3' into develop
[taxeditor.git] / eu.etaxonomy.taxeditor.navigation / src / main / java / eu / etaxonomy / taxeditor / navigation / search / SearchResultView.java
1 /**
2 * Copyright (C) 2007 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
10 package eu.etaxonomy.taxeditor.navigation.search;
11
12 import java.util.ArrayList;
13 import java.util.List;
14
15 import org.eclipse.core.runtime.IProgressMonitor;
16 import org.eclipse.core.runtime.IStatus;
17 import org.eclipse.core.runtime.Status;
18 import org.eclipse.core.runtime.jobs.Job;
19 import org.eclipse.jface.action.GroupMarker;
20 import org.eclipse.jface.action.MenuManager;
21 import org.eclipse.jface.viewers.ArrayContentProvider;
22 import org.eclipse.jface.viewers.DoubleClickEvent;
23 import org.eclipse.jface.viewers.IDoubleClickListener;
24 import org.eclipse.jface.viewers.IStructuredSelection;
25 import org.eclipse.jface.viewers.TableViewer;
26 import org.eclipse.swt.SWT;
27 import org.eclipse.swt.layout.GridData;
28 import org.eclipse.swt.layout.GridLayout;
29 import org.eclipse.swt.widgets.Composite;
30 import org.eclipse.swt.widgets.Control;
31 import org.eclipse.swt.widgets.Display;
32 import org.eclipse.swt.widgets.Label;
33 import org.eclipse.swt.widgets.Menu;
34 import org.eclipse.swt.widgets.Text;
35 import org.eclipse.ui.IMemento;
36 import org.eclipse.ui.IWorkbenchActionConstants;
37 import org.eclipse.ui.part.ViewPart;
38
39 import eu.etaxonomy.cdm.api.conversation.ConversationHolder;
40 import eu.etaxonomy.cdm.api.conversation.IConversationEnabled;
41 import eu.etaxonomy.cdm.api.service.ITaxonService;
42 import eu.etaxonomy.cdm.api.service.config.IFindTaxaAndNamesConfigurator;
43 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
44 import eu.etaxonomy.cdm.model.taxon.Synonym;
45 import eu.etaxonomy.cdm.model.taxon.Taxon;
46 import eu.etaxonomy.cdm.model.taxon.TaxonBase;
47 import eu.etaxonomy.cdm.persistence.dto.UuidAndTitleCache;
48 import eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap;
49 import eu.etaxonomy.cdm.persistence.query.MatchMode;
50 import eu.etaxonomy.taxeditor.model.AbstractUtility;
51 import eu.etaxonomy.taxeditor.model.ContextListenerAdapter;
52 import eu.etaxonomy.taxeditor.model.IContextListener;
53 import eu.etaxonomy.taxeditor.navigation.search.SearchBar.SearchOption;
54 import eu.etaxonomy.taxeditor.store.CdmStore;
55 import eu.etaxonomy.taxeditor.view.CdmViewerChooser;
56
57 /**
58 * <p>SearchResultView class.</p>
59 *
60 * @author p.ciardelli
61 * @author n.hoffmann
62 * @created 19.01.2009
63 * @version 1.0
64 */
65 public class SearchResultView extends ViewPart implements IConversationEnabled{
66
67 private static Object[] EMPTY = new Object[0];
68
69 private class ContextListener extends ContextListenerAdapter{
70 /* (non-Javadoc)
71 * @see eu.etaxonomy.taxeditor.model.IContextListener#contextStop(org.eclipse.ui.IMemento, org.eclipse.core.runtime.IProgressMonitor)
72 */
73 @Override
74 public void contextStop(IMemento memento, IProgressMonitor monitor) {
75 monitor.subTask("Getting rid of search results");
76 AbstractUtility.hideView(SearchResultView.this);
77 }
78 }
79
80 /** Constant <code>ID="eu.etaxonomy.taxeditor.navigation.searc"{trunked}</code> */
81 public static final String ID =
82 "eu.etaxonomy.taxeditor.navigation.search.searchResultView"; //$NON-NLS-1$
83
84 private TableViewer resultViewer;
85
86 private ConversationHolder conversation;
87
88 private Text searchString;
89
90 private Text configurationLabel;
91
92 private Text status;
93
94 private SearchJob searchJob;
95
96 private IContextListener contextListener;
97
98 /* (non-Javadoc)
99 * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
100 */
101 /** {@inheritDoc} */
102 @Override
103 public void createPartControl(Composite parent) {
104
105 conversation = CdmStore.createConversation();
106 contextListener = new ContextListener();
107 CdmStore.getContextManager().addContextListener(contextListener);
108
109 GridLayout layout = new GridLayout();
110 layout.marginWidth = 0;
111 layout.marginHeight = 0;
112
113 parent.setLayout(layout);
114
115 Composite infoComposite = createInfoComposite(parent);
116 infoComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
117
118 resultViewer = new TableViewer(parent, SWT.NONE);
119 resultViewer.setContentProvider(new ArrayContentProvider());
120 resultViewer.setLabelProvider(new SearchResultLabelProvider());
121 resultViewer.addDoubleClickListener(new IDoubleClickListener() {
122 @Override
123 public void doubleClick(DoubleClickEvent event) {
124 if(event.getSelection() instanceof IStructuredSelection){
125 Object selectedObject = ((IStructuredSelection) event.getSelection()).getFirstElement();
126 if (selectedObject instanceof UuidAndTitleCache){
127 Class type = ((UuidAndTitleCache) selectedObject).getType();
128 if(type == Taxon.class || type == Synonym.class){
129 TaxonBase taxonBase = CdmStore.getService(ITaxonService.class).load(((UuidAndTitleCache) selectedObject).getUuid());
130 CdmViewerChooser chooser = new CdmViewerChooser(getSite().getShell());
131 chooser.chooseViewer(taxonBase);
132 }
133 }
134 }
135 }
136 });
137
138 resultViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
139
140 getSite().setSelectionProvider(resultViewer);
141
142 // register context menu
143 MenuManager menuMgr = new MenuManager();
144 menuMgr.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
145 getSite().registerContextMenu(menuMgr, resultViewer);
146
147 Control control = resultViewer.getControl();
148 Menu menu = menuMgr.createContextMenu(control);
149 control.setMenu(menu);
150 }
151
152 private Composite createInfoComposite(Composite parent){
153 Composite composite = new Composite(parent, SWT.NULL);
154
155 composite.setLayout(new GridLayout(2, false));
156
157 Label searchStringLabel = new Label(composite, SWT.NULL);
158 searchStringLabel.setText("Search String:");
159
160 searchString = new Text(composite, SWT.NULL);
161 searchString.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
162 searchString.setEditable(false);
163 // searchString.setText(" ");
164
165 Label configurationDescriptionLabel = new Label(composite, SWT.NULL);
166 configurationDescriptionLabel.setText("Search for:");
167
168 configurationLabel = new Text(composite, SWT.WRAP);
169 configurationLabel.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
170 configurationLabel.setEditable(false);
171
172 Label statusLabel = new Label(composite, SWT.NULL);
173 statusLabel.setText("Status:");
174
175 status = new Text(composite, SWT.NULL);
176 status.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
177 status.setEditable(false);
178
179 return composite;
180 }
181
182 /**
183 * <p>performSearch</p>
184 *
185 * @param configurator a {@link eu.etaxonomy.cdm.api.service.config.ITaxonServiceConfigurator} object.
186 */
187 public void performSearch(IFindTaxaAndNamesConfigurator configurator){
188 setPartName("Search: '" + configurator.getTitleSearchString() + "'");
189
190 searchString.setText(configurator.getTitleSearchString());
191
192 List<String> includedEntities = new ArrayList<String>();
193 if(configurator.isDoTaxa()) {
194 includedEntities.add(SearchOption.TAXON.getLabel());
195 }
196 if(configurator.isDoSynonyms()) {
197 includedEntities.add(SearchOption.SYNONYM.getLabel());
198 }
199 if(configurator.isDoNamesWithoutTaxa()) {
200 includedEntities.add(SearchOption.NAME.getLabel());
201 }
202 if(configurator.isDoTaxaByCommonNames()){
203 includedEntities.add(SearchOption.COMMON_NAME.getLabel());
204 }
205 configurator.setMatchMode(MatchMode.LIKE);
206
207 String includedEntitiesString = "";
208 for (int i = 0; i < includedEntities.size(); i++){
209 includedEntitiesString += includedEntities.get(i);
210 if(i < includedEntities.size() -1){
211 includedEntitiesString += ", ";
212 }
213 }
214
215 configurationLabel.setText(includedEntitiesString);
216
217 status.setText("Searching...");
218
219 searchJob = new SearchJob(Display.getCurrent(), configurator);
220 searchJob.schedule();
221
222 }
223
224 /**
225 * <p>displaySearchResult</p>
226 *
227 * @param result a {@link java.util.List} object.
228 */
229 protected void displaySearchResult(List<UuidAndTitleCache<IdentifiableEntity>> result) {
230 if(result.size() > 0){
231 resultViewer.setInput(result);
232 status.setText(result.size() + " entities found");
233 }else{
234 resultViewer.setInput(EMPTY);
235 status.setText("Search returned no results");
236 }
237 }
238
239 /* (non-Javadoc)
240 * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
241 */
242 /** {@inheritDoc} */
243 @Override
244 public void setFocus() {
245 //logger.warn("Setting focus to search result viewer");
246 conversation.bind();
247 // pass focus to resultViewer
248 resultViewer.getControl().setFocus();
249 }
250
251 /* (non-Javadoc)
252 * @see eu.etaxonomy.cdm.api.conversation.IConversationEnabled#getConversationHolder()
253 */
254 /**
255 * <p>getConversationHolder</p>
256 *
257 * @return a {@link eu.etaxonomy.cdm.api.conversation.ConversationHolder} object.
258 */
259 @Override
260 public ConversationHolder getConversationHolder() {
261 return this.conversation;
262 }
263
264 /* (non-Javadoc)
265 * @see eu.etaxonomy.cdm.persistence.hibernate.ICdmPostDataChangeObserver#update(eu.etaxonomy.cdm.persistence.hibernate.CdmDataChangeMap)
266 */
267 /** {@inheritDoc} */
268 @Override
269 public void update(CdmDataChangeMap changeEvents) {
270 // TODO Auto-generated method stub
271
272 }
273
274 /* (non-Javadoc)
275 * @see org.eclipse.ui.part.WorkbenchPart#dispose()
276 */
277 /** {@inheritDoc} */
278 @Override
279 public void dispose() {
280 super.dispose();
281 conversation.close();
282 if(searchJob != null) {
283 searchJob.cancel();
284 }
285 CdmStore.getContextManager().removeContextListener(contextListener);
286 }
287
288 /**
289 *
290 * @author n.hoffmann
291 * @created Feb 2, 2010
292 * @version 1.0
293 */
294 class SearchJob extends Job{
295
296 private final IFindTaxaAndNamesConfigurator configurator;
297
298 private final Display display;
299
300 /**
301 * @param name
302 */
303 public SearchJob(Display display, IFindTaxaAndNamesConfigurator configurator) {
304 super("Performing Search");
305 this.display = display;
306 this.configurator = configurator;
307 }
308
309 /* (non-Javadoc)
310 * @see org.eclipse.core.runtime.jobs.Job#run(org.eclipse.core.runtime.IProgressMonitor)
311 */
312 @Override
313 protected IStatus run(IProgressMonitor monitor) {
314 monitor.beginTask("", 100);
315 monitor.worked(20);
316
317 final List<UuidAndTitleCache<IdentifiableEntity>> searchResult = CdmStore.getSearchManager().findTaxaAndNames(configurator);
318 monitor.worked(40);
319
320 if(! monitor.isCanceled()){
321 display.asyncExec(new Runnable() {
322 @Override
323 public void run() {
324 displaySearchResult(searchResult);
325 }
326 });
327 }else{
328 display.asyncExec(new Runnable() {
329 @Override
330 public void run() {
331 status.setText("Cancelled");
332 }
333 });
334 }
335 monitor.done();
336 return Status.OK_STATUS;
337 }
338
339 }
340 }