Merge branch 'release/5.18.0'
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / preference / ListComponent.java
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.preference;
10
11 import java.awt.Toolkit;
12 import java.io.BufferedReader;
13 import java.io.IOException;
14 import java.io.InputStreamReader;
15 import java.net.HttpURLConnection;
16 import java.net.URL;
17 import java.util.ArrayList;
18
19 import javax.swing.event.DocumentEvent;
20
21 import org.apache.commons.lang3.StringUtils;
22 import org.eclipse.equinox.internal.p2.ui.misc.StringMatcher;
23 import org.eclipse.jface.fieldassist.ComboContentAdapter;
24 import org.eclipse.jface.fieldassist.ContentProposalAdapter;
25 import org.eclipse.jface.fieldassist.IContentProposal;
26 import org.eclipse.jface.fieldassist.IContentProposalProvider;
27 import org.eclipse.jface.resource.JFaceResources;
28 import org.eclipse.swt.SWT;
29 import org.eclipse.swt.custom.CLabel;
30 import org.eclipse.swt.events.ModifyEvent;
31 import org.eclipse.swt.events.ModifyListener;
32 import org.eclipse.swt.events.MouseEvent;
33 import org.eclipse.swt.events.MouseListener;
34 import org.eclipse.swt.graphics.Rectangle;
35 import org.eclipse.swt.layout.GridData;
36 import org.eclipse.swt.widgets.Button;
37 import org.eclipse.swt.widgets.Combo;
38 import org.eclipse.swt.widgets.Composite;
39 import org.eclipse.swt.widgets.Display;
40 import org.eclipse.swt.widgets.Label;
41 import org.eclipse.swt.widgets.List;
42 import org.eclipse.swt.widgets.Text;
43 import org.json.JSONArray;
44 import org.json.JSONException;
45 import org.json.JSONObject;
46
47 import eu.etaxonomy.cdm.model.metadata.CdmPreference;
48 import eu.etaxonomy.cdm.model.metadata.PreferencePredicate;
49 import eu.etaxonomy.taxeditor.l10n.Messages;
50 import eu.etaxonomy.taxeditor.preference.menu.CdmPreferencePage;
51
52 /**
53 * @author k.luther
54 * @date 20.04.2017
55 */
56 public class ListComponent implements ModifyListener
57 {
58 private List list;
59
60 private static final String addString = Messages.ListComponent_ADD_PROVIDER;
61 private static final String removeString = Messages.ListComponent_REMOVE_PROVIDER;
62 private static final String noProvider = Messages.ListComponent_NO_PROVIDER_AVAILABLE;
63 private static final String serverSidePreference = "Server Side Preference:";
64 private Button removeButton;
65 private Combo providerURI;
66 protected Label labelException;
67 boolean isAdmin = false;
68 CdmPreferencePage preferencePage;
69 CdmPreference providerListPreference;
70 String providerList;
71 String[] items;
72
73 public CdmPreference getProviderListPreference() {
74 return providerListPreference;
75 }
76
77 public void setProviderListPreference(CdmPreference providerListPreference) {
78 this.providerListPreference = providerListPreference;
79 }
80
81 public ListComponent(Composite parent, int style, boolean isAdmin, CdmPreferencePage parentPage) {
82 this.isAdmin= isAdmin;
83 this.preferencePage = parentPage;
84
85 providerListPreference = PreferencesUtil.getPreferenceFromDB(PreferencePredicate.BioCaseProvider);
86 if (!isAdmin && providerListPreference != null && !providerListPreference.isAllowOverride()){
87 Label editingNotAllowed = new Label(parent, style);
88 editingNotAllowed.setText(Messages.AbcdImportProvider_description_not_available);
89 return ;
90 }
91 final CLabel description = new CLabel(parent, SWT.NULL);
92 description.setText(Messages.AbcdImportProvider_description);
93 list = new List(parent, SWT.BORDER | SWT.V_SCROLL);
94 GridData gridData = new GridData(SWT.FILL, SWT.CENTER, true, true, 2, 3);
95 gridData.grabExcessHorizontalSpace = true;
96 list.setLayoutData(gridData);
97
98 Rectangle clientArea = parent.getShell().getClientArea ();
99 list.setBounds (clientArea.x, clientArea.y, 50, 500);
100
101
102 providerList = null; //$NON-NLS-1$
103 String allProviderStringDB = "";
104
105 if (!isAdmin && ((providerListPreference != null && providerListPreference.isAllowOverride()) || providerListPreference == null)){
106 providerList = PreferencesUtil.getStringValue(PreferencePredicate.BioCaseProvider.getKey(), true);
107
108 }else{
109 if (providerListPreference != null){
110 providerList = providerListPreference.getValue();
111 }
112 }
113
114 //the string is structured like this: http://ww3.bgbm.org/biocase/pywrapper.cgi?dsa=DNA_Bank;http:...;
115 if (providerList != null){
116 String[] providerArray = providerList.split(";"); //$NON-NLS-1$
117 for (String providerString : providerArray){
118 if (!StringUtils.isBlank(providerString)){
119 list.add(providerString);
120 }
121 }
122 }
123
124 if (list.getItemCount() == 0){
125 list.add(noProvider);
126 }
127 list.add(""); //$NON-NLS-1$
128
129 // list.setSelection(0);
130 GridData dataList = new GridData();
131 dataList.horizontalAlignment = GridData.FILL;
132 dataList.horizontalSpan = 3;
133
134 // dataList.grabExcessVerticalSpace = true;
135
136 list.setLayoutData(dataList);
137
138 providerURI = new Combo(parent, SWT.BORDER);
139
140 URL url;
141 String response = null;
142 try {
143 url = new URL("https://www.biocase.org/whats_biocase/gbif_biocase.cgi");
144
145 HttpURLConnection conn = (HttpURLConnection) url.openConnection();
146 conn.setRequestProperty("Accept", "application/json");
147 // conn.setConnectTimeout(TIMEOUT*9);
148 // conn.setReadTimeout(TIMEOUT*9);
149
150 if (conn.getResponseCode() != 200) {
151 throw new RuntimeException("Failed : HTTP error code : " + conn.getResponseCode());
152 }
153 BufferedReader br = new BufferedReader(new InputStreamReader((conn.getInputStream())));
154
155 StringBuilder builder = new StringBuilder();
156 String line;
157 while ((line = br.readLine()) != null) {
158 builder.append(line);
159 }
160 conn.disconnect();
161 response = builder.toString();
162 } catch (IOException e) {
163 // TODO Auto-generated catch block
164 e.printStackTrace();
165 }
166
167 JSONArray jsonResponseArray;
168 try {
169 jsonResponseArray =new JSONArray(response);
170
171 int i = 0;
172 String service_url = null;
173 JSONArray dataSets = null;
174 items = new String[jsonResponseArray.length()];
175 while (i<jsonResponseArray.length()){
176 JSONObject object = jsonResponseArray.getJSONObject(i);
177 service_url = (String) object.get("service_url");
178 dataSets = (JSONArray) object.get("datasets");
179 if (service_url != null){
180 providerURI.add(service_url);
181 items[i] = service_url;
182 }
183 i++;
184 }
185
186 } catch (JSONException e) {
187 // TODO Auto-generated catch block
188 e.printStackTrace();
189 }
190
191 GridData dataProviderUri = new GridData();
192 dataProviderUri.horizontalAlignment = GridData.FILL;
193 dataProviderUri.horizontalSpan = 3;
194 providerURI.setLayoutData(dataProviderUri);
195 // providerURI.setVisible(false);
196
197 ContentProposalAdapter adapter = new ContentProposalAdapter(providerURI, new ComboContentAdapter(), getProposalProvider(), null, null);
198 adapter.setPropagateKeys(true);
199 adapter.setProposalAcceptanceStyle(ContentProposalAdapter.PROPOSAL_REPLACE);
200 // String[] proposals = new String[providerURI.getItems().length];
201 //
202 // for (int i = 0; i < providerURI.getItems().length; i++) {
203 // proposals[i] = providerURI.getItem(i);
204 // }
205 //
206 // ComboViewer comboViewer = new ComboViewer(parent, SWT.NONE);
207 // comboViewer.setContentProvider(new ArrayContentProvider());
208 // comboViewer.setLabelProvider(new LabelProvider(){
209 // @Override
210 // public String getText(final Object element){
211 // if(element instanceof String){
212 // return (String) element;
213 // }
214 // return element.toString();
215 // }
216 // });
217 // comboViewer.setInput(proposals);
218 // // additionally, configure the comboViewer arbitrary
219 // AutoCompleteField field = new AutoCompleteField(comboViewer.getCombo(), new ComboContentAdapter(), proposals);
220
221 //providerURI.addModifyListener(this);
222 labelException = new Label(parent, SWT.NULL);
223 labelException.setText("");
224
225 labelException.setLayoutData(dataProviderUri);
226
227 Button addButton = new Button(parent, SWT.NULL);
228 AddListener addListener = new AddListener(addButton);
229 addButton.setText(addString);
230 addButton.addMouseListener(addListener);
231
232 removeButton = new Button(parent, SWT.NULL);
233 removeButton.setText(removeString);
234 removeButton.addMouseListener(new RemoveListener());
235 }
236
237 IContentProposalProvider getProposalProvider() {
238 return new IContentProposalProvider() {
239 @Override
240 public IContentProposal[] getProposals(String contents, int position) {
241 //String[] items = getStringItems();
242 if (contents.length() == 0 || items.length == 0) {
243 return new IContentProposal[0];
244 }
245 StringMatcher matcher = new StringMatcher("*" + contents + "*", true, false); //$NON-NLS-1$ //$NON-NLS-2$
246 ArrayList<String> matches = new ArrayList<String>();
247 for (int i = 0; i < items.length; i++) {
248 if (matcher.match(items[i])) {
249 matches.add(items[i]);
250 }
251 }
252
253 // We don't want to autoactivate if the only proposal exactly matches
254 // what is in the combo. This prevents the popup from
255 // opening when the user is merely scrolling through the combo values or
256 // has accepted a combo value.
257 if (matches.size() == 1 && matches.get(0).equals(providerURI.getText())) {
258 return new IContentProposal[0];
259 }
260
261 if (matches.isEmpty()) {
262 return new IContentProposal[0];
263 }
264
265 // Make the proposals
266 IContentProposal[] proposals = new IContentProposal[matches.size()];
267 for (int i = 0; i < matches.size(); i++) {
268 final String proposal = matches.get(i);
269 proposals[i] = new IContentProposal() {
270
271 @Override
272 public String getContent() {
273 return proposal;
274 }
275
276 @Override
277 public int getCursorPosition() {
278 return proposal.length();
279 }
280
281 @Override
282 public String getDescription() {
283 return null;
284 }
285
286 @Override
287 public String getLabel() {
288 return null;
289 }
290 };
291 }
292 return proposals;
293 }
294 };
295 }
296
297 public boolean isAdmin() {
298 return isAdmin;
299 }
300
301 public void setAdmin(boolean isAdmin) {
302 this.isAdmin = isAdmin;
303 }
304
305 class RemoveListener implements MouseListener {
306 @Override
307 public void mouseUp(MouseEvent e) {
308 //This method can be called only if
309 //there's a valid selection
310 //so go ahead and remove whatever's selected.
311 int index = list.getSelectionIndex();
312 try{
313 String item = list.getItem(index);
314 if (item.equals(serverSidePreference)) {
315 return;
316 }
317 list.remove(index);
318
319
320 int size = list.getItemCount();
321
322 if (size == 0) { //Nothing's left, disable removing.
323 removeButton.setEnabled(false);
324
325 } else { //Select an index.
326 if (index == size) {
327 //removed item in last position
328 index--;
329 }
330
331 list.setSelection(index-1);
332 preferencePage.setApply(true);
333
334 }
335 }catch(IllegalArgumentException iae){
336 //nothing was selected
337 return;
338 }
339
340 }
341 /**
342 * {@inheritDoc}
343 */
344 @Override
345 public void mouseDoubleClick(MouseEvent e) {
346 // TODO Auto-generated method stub
347
348 }
349
350
351 /**
352 * {@inheritDoc}
353 */
354 @Override
355 public void mouseDown(MouseEvent e) {
356 // TODO Auto-generated method stub
357
358 }
359 }
360
361 //This listener is shared by the text field and the add button.
362 class AddListener implements MouseListener {
363 private boolean alreadyEnabled = false;
364 private Button button;
365
366 public AddListener(Button button) {
367 this.button = button;
368 }
369
370
371 protected boolean alreadyInList(String name) {
372 return list.getData(name) != null;
373 }
374
375
376 private void enableButton() {
377 if (!alreadyEnabled) {
378 button.setEnabled(true);
379 }
380 }
381
382 private boolean handleEmptyTextField(DocumentEvent e) {
383 if (e.getDocument().getLength() <= 0) {
384 button.setEnabled(false);
385 alreadyEnabled = false;
386 return true;
387 }
388 return false;
389 }
390
391
392
393 /**
394 * {@inheritDoc}
395 */
396 @Override
397 public void mouseDoubleClick(MouseEvent e) {
398 // TODO Auto-generated method stub
399
400 }
401
402 /**
403 * {@inheritDoc}
404 */
405 @Override
406 public void mouseDown(MouseEvent e) {
407 // TODO Auto-generated method stub
408
409 }
410
411 /**
412 * {@inheritDoc}
413 */
414 @Override
415 public void mouseUp(MouseEvent event) {
416 String name = providerURI.getText();
417
418 //User didn't type in a unique name...
419 if (name.equals("") || alreadyInList(name) || !StringUtils.isBlank(labelException.getText())) { //$NON-NLS-1$
420 Toolkit.getDefaultToolkit().beep();
421 //providerURI.selectAll();
422 return;
423 }
424
425 int index = list.getSelectionIndex(); //get selected index
426 if (index == -1) { //no selection, so insert at beginning
427 index = 0;
428 } else { //add after the selected item
429 index++;
430 }
431 if(list.getItemCount() == 0){
432 index = 0;
433 }else if (list.getItem(0).equals(noProvider)){
434 list.remove(noProvider);
435 }
436 int itemCount = list.getItemCount();
437
438
439 list.add(providerURI.getText(), index);
440 list.setSelection(index);
441 list.update();
442 list.redraw();
443
444 //Select the new item
445
446 providerURI.setText(""); //$NON-NLS-1$
447 preferencePage.setApply(true);
448 }
449 }
450
451 public String createAllProviderString(){
452 String allProviderString = null;
453 boolean first = true;
454 for (String item: list.getItems()){
455 if (item.equals(noProvider) || item.equals(serverSidePreference)){
456 //do nothing
457 }else if (first || StringUtils.isBlank(allProviderString)){ //$NON-NLS-1$
458 allProviderString = item.trim();
459 first = false;
460 }else {
461 allProviderString +=";"+ item.trim(); //$NON-NLS-1$
462 }
463 }
464
465 return allProviderString;
466
467 }
468
469
470 @Override
471 public void modifyText(ModifyEvent e) {
472 if(e.widget==providerURI){
473 Text text = (Text) e.widget;
474 boolean hasControlCharacters = false;
475 String textString = text.getText();
476 int stringLength = textString.length();
477 for (int i = 0; i < stringLength; i++) {
478 if (Character.isISOControl(textString.charAt(i))) {
479 hasControlCharacters = true;
480 break;
481 }
482 }
483
484 //remove control character such as line breaks etc.
485 try {
486 getParsedText();
487 labelException.setFont(JFaceResources.getFontRegistry().getBold(JFaceResources.DEFAULT_FONT));
488 labelException.setForeground(Display.getCurrent().getSystemColor(SWT.NULL));
489 labelException.setText("");
490 } catch (Exception exception) {
491 labelException.setFont(JFaceResources.getFontRegistry().getBold(JFaceResources.DEFAULT_FONT));
492 labelException.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_RED));
493 labelException.setText(Messages.UriWithLabelElement_URL_NOT_SAVED+exception.getLocalizedMessage());
494 }
495 }
496
497
498 }
499
500
501 protected URL getParsedText() throws Exception {
502 String uriText = providerURI.getText();
503 if(!StringUtils.isBlank(uriText)){
504 return new URL(providerURI.getText());
505 }
506 return null;
507 }
508
509
510
511 }
512