ref #9359 upgrade TaxEditor to log4j2
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / model / AbstractUtility.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 package eu.etaxonomy.taxeditor.model;
10
11 import java.io.BufferedWriter;
12 import java.io.File;
13 import java.io.FileOutputStream;
14 import java.io.OutputStreamWriter;
15 import java.io.Writer;
16 import java.text.SimpleDateFormat;
17 import java.util.ArrayList;
18 import java.util.Calendar;
19 import java.util.Collection;
20 import java.util.HashSet;
21 import java.util.LinkedHashMap;
22 import java.util.List;
23 import java.util.Map;
24 import java.util.Set;
25 import java.util.TreeSet;
26 import java.util.UUID;
27 import java.util.zip.ZipEntry;
28 import java.util.zip.ZipOutputStream;
29
30 import org.apache.commons.lang3.StringUtils;
31 import org.apache.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;
32 import org.eclipse.core.commands.ExecutionException;
33 import org.eclipse.core.commands.operations.AbstractOperation;
34 import org.eclipse.core.commands.operations.IOperationHistory;
35 import org.eclipse.core.runtime.IAdaptable;
36 import org.eclipse.core.runtime.ICoreRunnable;
37 import org.eclipse.core.runtime.IProgressMonitor;
38 import org.eclipse.core.runtime.IStatus;
39 import org.eclipse.core.runtime.NullProgressMonitor;
40 import org.eclipse.core.runtime.OperationCanceledException;
41 import org.eclipse.core.runtime.Status;
42 import org.eclipse.core.runtime.SubMonitor;
43 import org.eclipse.core.runtime.SubProgressMonitor;
44 import org.eclipse.core.runtime.jobs.Job;
45 import org.eclipse.e4.ui.di.UISynchronize;
46 import org.eclipse.e4.ui.model.application.ui.basic.MPart;
47 import org.eclipse.e4.ui.workbench.modeling.EPartService;
48 import org.eclipse.jface.action.IStatusLineManager;
49 import org.eclipse.jface.viewers.IStructuredSelection;
50 import org.eclipse.jface.viewers.SelectionChangedEvent;
51 import org.eclipse.swt.graphics.Color;
52 import org.eclipse.swt.graphics.Font;
53 import org.eclipse.swt.widgets.Display;
54 import org.eclipse.swt.widgets.Shell;
55 import org.eclipse.ui.IWorkbench;
56 import org.eclipse.ui.PlatformUI;
57 import org.eclipse.ui.ide.undo.WorkspaceUndoUtil;
58 import org.eclipse.ui.progress.IProgressConstants;
59
60 import eu.etaxonomy.cdm.api.application.CdmApplicationState;
61 import eu.etaxonomy.cdm.api.service.IProgressMonitorService;
62 import eu.etaxonomy.cdm.api.service.UpdateResult;
63 import eu.etaxonomy.cdm.api.service.dto.CdmEntityIdentifier;
64 import eu.etaxonomy.cdm.common.CdmUtils;
65 import eu.etaxonomy.cdm.common.SetMap;
66 import eu.etaxonomy.cdm.common.monitor.IRemotingProgressMonitor;
67 import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
68 import eu.etaxonomy.cdm.io.common.ExportDataWrapper;
69 import eu.etaxonomy.cdm.io.common.ExportResult;
70 import eu.etaxonomy.cdm.io.common.ExportResultType;
71 import eu.etaxonomy.cdm.io.common.ExportType;
72 import eu.etaxonomy.cdm.model.common.CdmBase;
73 import eu.etaxonomy.cdm.model.taxon.Synonym;
74 import eu.etaxonomy.cdm.model.taxon.Taxon;
75 import eu.etaxonomy.cdm.model.taxon.TaxonNode;
76 import eu.etaxonomy.cdm.model.term.IEnumTerm;
77 import eu.etaxonomy.taxeditor.event.EventUtility;
78 import eu.etaxonomy.taxeditor.event.WorkbenchEventConstants;
79 import eu.etaxonomy.taxeditor.operation.AbstractPostOperation;
80 import eu.etaxonomy.taxeditor.operation.IFeedbackGenerator;
81 import eu.etaxonomy.taxeditor.operation.IPostMoniteredOperationEnabled;
82 import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
83 import eu.etaxonomy.taxeditor.operation.e4.CdmHandlerE4;
84 import eu.etaxonomy.taxeditor.store.CdmStore;
85 import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
86 import eu.etaxonomy.taxeditor.ui.dialog.ReportTextDialog;
87 import eu.etaxonomy.taxeditor.view.e4.AbstractCdmDataViewer;
88 import eu.etaxonomy.taxeditor.view.e4.details.DetailsPartE4;
89 import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
90
91 /**
92 * @author n.hoffmann
93 * @created 11.05.2009
94 */
95 public abstract class AbstractUtility {
96
97 protected static final Logger logger = LogManager.getLogger(AbstractUtility.class);
98
99 /** Constant <code>statusLineManager</code> */
100 protected static IStatusLineManager statusLineManager;
101 /** Constant <code>DATE_FORMAT_NOW="yyyyMMddHHmm"</code> */
102 public static final String DATE_FORMAT_NOW = "yyyyMMddHHmm";
103
104 public static Object getActivePart() {
105 MPart activePart = EventUtility.getActivePart();
106 if(activePart!=null){
107 return activePart.getObject();
108 }
109 return null;
110 }
111
112 public static Shell getShell() {
113 return EventUtility.getShell();
114 }
115
116 public static IWorkbench getWorkbench() {
117 return TaxeditorStorePlugin.getDefault().getWorkbench();
118 }
119
120 @SuppressWarnings("unchecked")
121 public static Object getService(Class api) {
122 return TaxeditorStorePlugin.getDefault().getWorkbench().getService(api);
123 }
124
125 public static Font getFont(String symbolicName) {
126 return FontResources.getFont(symbolicName);
127 }
128
129 public static Color getColor(String symbolicName) {
130 return ColorResources.getColor(symbolicName);
131 }
132
133 public static IStatus executeOperation(final AbstractPostOperation operation, UISynchronize sync) {
134 if (getOperationHistory() == null) {
135 throw new IllegalArgumentException(
136 "There is no operation history for this context");
137 }
138
139 final IAdaptable uiInfoAdapter = WorkspaceUndoUtil.getUIInfoAdapter(getShell());
140
141 Job job = Job.create(operation.getLabel(), (ICoreRunnable) monitor -> {
142 sync.syncExec(() -> {
143 String operationlabel = operation.getLabel();
144 monitor.beginTask(operationlabel, 100);
145 IStatus status = Status.CANCEL_STATUS;
146 try {
147 operation.addContext(IOperationHistory.GLOBAL_UNDO_CONTEXT);
148 status = operation.execute(monitor, uiInfoAdapter);
149 } catch (ExecutionException e) {
150
151 MessagingUtils.operationDialog(AbstractUtility.class, e, TaxeditorStorePlugin.PLUGIN_ID, operationlabel, null);
152
153 } finally {
154 monitor.done();
155 }
156
157 String statusString = status.equals(Status.OK_STATUS) ? "completed"
158 : "cancelled";
159 setStatusLine(operationlabel + " " + statusString + ".");
160 IPostOperationEnabled postOperationEnabled = operation
161 .getPostOperationEnabled();
162 if (postOperationEnabled != null) {
163 postOperationEnabled.onComplete();
164 }
165 });
166 });
167
168 try {
169 job.setUser(true);
170 job.schedule();
171 } catch (Exception e) {
172 MessagingUtils.messageDialog("Error executing operation", AbstractUtility.class, "An error occurred while executing " + operation.getLabel(), e);
173 }
174
175 return Status.OK_STATUS;
176 }
177
178 public static IStatus executeOperation(final AbstractOperation operation, final CdmHandlerE4 handler, UISynchronize sync) {
179 return executeOperation_internal(operation, handler, sync);
180 }
181
182 private static IStatus executeOperation_internal(final AbstractOperation operation, final CdmHandlerE4 handler,
183 UISynchronize sync) {
184 if (getOperationHistory() == null) {
185 throw new IllegalArgumentException(
186 "There is no operation history for this context");
187 }
188
189 final IAdaptable uiInfoAdapter = WorkspaceUndoUtil
190 .getUIInfoAdapter(getShell());
191
192
193 Job job = Job.create(operation.getLabel(), (ICoreRunnable) monitor -> {
194 sync.syncExec(() -> {
195 String operationlabel = operation.getLabel();
196 monitor.beginTask(operationlabel, 100);
197 IStatus status = Status.CANCEL_STATUS;
198 try {
199 operation.addContext(IOperationHistory.GLOBAL_UNDO_CONTEXT);
200 status = operation.execute(monitor,
201 uiInfoAdapter);
202 handler.postOperation(status);
203 } catch (ExecutionException e) {
204 MessagingUtils.operationDialog(AbstractUtility.class, e, TaxeditorStorePlugin.PLUGIN_ID, operationlabel, null);
205 } finally {
206 monitor.done();
207 }
208
209 String statusString = status.equals(Status.OK_STATUS) ? "completed"
210 : "cancelled";
211 setStatusLine(operationlabel + " " + statusString + ".");
212 });
213 });
214
215 try {
216 job.setUser(true);
217 sync.syncExec(()->job.schedule());
218 } catch (Exception e) {
219 MessagingUtils.messageDialog("Error executing operation", AbstractUtility.class, "An error occurred while executing " + operation.getLabel(), e);
220 }
221
222 return Status.OK_STATUS;
223 }
224
225 /**
226 * Executes a remoting monitored operation
227 *
228 * @param label for the operation
229 * @param uuid of the remoting monitor already started on the server
230 * @param pollInterval in milliseconds
231 * @param cancelable flag which determines whether the operation can be cancelled
232 * @param postOp callback for running post operation logic
233 * @return
234 */
235 public static IStatus executeMoniteredExport(final String label,
236 final UUID uuid,
237 final int pollInterval,
238 final boolean cancelable,
239 final IPostMoniteredOperationEnabled postOp,
240 final IFeedbackGenerator feedbackGenerator,
241 String urlString,
242 boolean createZip) {
243
244 try {
245 // get the remoting monitor the first time to make sure that the
246 // operation is valid
247 final IProgressMonitorService progressMonitorService = CdmApplicationState.getCurrentAppConfig().getProgressMonitorService();
248 final IRemotingProgressMonitor firstRemotingMonitor = progressMonitorService.getRemotingMonitor(uuid);
249 if(firstRemotingMonitor == null) {
250 throw new IllegalStateException("Remoting progress monitor is null");
251 }
252 if (firstRemotingMonitor.isDone()){
253 createExportResult(label, urlString, createZip, firstRemotingMonitor);
254 }
255
256 Job job = new Job(label) {
257
258
259 @Override
260 public IStatus run(IProgressMonitor monitor) {
261 // run the monitor until the operation is finished
262 SubMonitor subMonitor = SubMonitor.convert(monitor, 100);
263 //subMonitor.beginTask("Start", 100);
264 IRemotingProgressMonitor remotingMonitor;
265 try {
266 remotingMonitor = CdmStore.getProgressMonitorClientManager().pollMonitor(label,
267 uuid,
268 pollInterval,
269 postOp,
270 feedbackGenerator,
271 subMonitor);
272 } catch (Exception ex) {
273 return new Status(IStatus.ERROR, TaxeditorStorePlugin.PLUGIN_ID, "Operation Interrupted", ex);
274 }
275
276 createExportResult(label, urlString, createZip, remotingMonitor);
277 return Status.OK_STATUS;
278 }
279
280
281
282 @Override
283 protected void canceling() {
284 CdmStore.getCurrentApplicationConfiguration().getProgressMonitorService().cancel(uuid);
285 }
286 };
287
288 // configure the job
289 job.setProperty(IProgressConstants.KEEP_PROPERTY, true);
290 job.setUser(true);
291 job.setName(label);
292 // schedule job
293 job.schedule();
294
295 } catch (Exception e) {
296 MessagingUtils.errorDialog("Error executing operation",
297 AbstractUtility.class,
298 "An error occurred while executing " + label,
299 TaxeditorStorePlugin.PLUGIN_ID,
300 e,
301 true);
302 }
303
304 return Status.OK_STATUS;
305 }
306
307 public static IOperationHistory getOperationHistory() {
308 return getWorkbench().getOperationSupport().getOperationHistory();
309 }
310
311 public static void setStatusLine(final String message) {
312 Display.getDefault().asyncExec(new Runnable() {
313
314 @Override
315 public void run() {
316 statusLineManager.setMessage(message);
317 }
318
319 });
320
321 }
322
323 public static IProgressMonitor getMonitor() {
324 statusLineManager.setCancelEnabled(false);
325 return statusLineManager.getProgressMonitor();
326 }
327
328 /**
329 * Starts either the given {@link IProgressMonitor} if it's not
330 * <code>null</code> or a new {@link NullProgressMonitor}.
331 *
332 * @param progressMonitor
333 * The {@link IProgressMonitor} or <code>null</code> if no
334 * progress should be reported.
335 * @param taskName
336 * The name of the main task.
337 * @param steps
338 * The number of steps this task is subdivided into.
339 * @return The {@link IProgressMonitor}.
340 */
341 public static IProgressMonitor startMainMonitor(
342 IProgressMonitor progressMonitor, String taskName, int steps) {
343 IProgressMonitor newMonitor = progressMonitor;
344 if (newMonitor == null) {
345 newMonitor = new NullProgressMonitor();
346 }
347 newMonitor.beginTask(taskName == null ? "" : taskName, steps);
348 newMonitor.subTask(" ");
349 return newMonitor;
350 }
351
352 /**
353 * Creates a {@link SubProgressMonitor} if the given
354 * {@link IProgressMonitor} is not <code>null</code> and not a
355 * {@link NullProgressMonitor}.
356 *
357 * @param progressMonitor
358 * The parent {@link IProgressMonitor} of the
359 * {@link SubProgressMonitor} to be created.
360 * @param ticks
361 * The number of steps this subtask is subdivided into. Must be a
362 * positive number and must not be
363 * {@link IProgressMonitor#UNKNOWN}.
364 * @return The {@link IProgressMonitor}.
365 */
366 public static IProgressMonitor getSubProgressMonitor(
367 IProgressMonitor progressMonitor, int ticks) {
368 if (progressMonitor == null) {
369 return new NullProgressMonitor();
370 }
371 if (progressMonitor instanceof NullProgressMonitor) {
372 return progressMonitor;
373 }
374
375 return new SubProgressMonitor(progressMonitor, ticks);
376 }
377
378 /**
379 * Checks whether the user canceled this operation. If not canceled, the
380 * given number of steps are declared as done.
381 *
382 * @param newMonitor
383 * a {@link org.eclipse.core.runtime.IProgressMonitor} object.
384 * @param steps
385 * a int.
386 */
387 public static void workedChecked(IProgressMonitor newMonitor, int steps) {
388 // In case the progress monitor was canceled throw an exception.
389 if (newMonitor.isCanceled()) {
390 throw new OperationCanceledException();
391 }
392 // Otherwise declare this step as done.
393 newMonitor.worked(steps);
394 }
395
396 public static String getPluginId() {
397 return "eu.taxeditor";
398 }
399
400 public static Object getActiveEditor() {
401 MPart activePart = EventUtility.getActivePart();
402 if(activePart!=null && activePart.getObject()!=null
403 && activePart.getObject() instanceof IE4SavablePart){
404 return activePart.getObject();
405 }
406 return null;
407 }
408
409 public static DetailsPartE4 getDetailsView(EPartService partService) {
410 MPart part = partService.findPart("eu.etaxonomy.taxeditor.view.e4.details.DetailsPartE4");
411 if(part!=null){
412 return (DetailsPartE4) part.getObject();
413 }
414 return null;
415 }
416
417 public static void refreshDetailsViewer(EPartService partService) {
418 if (getDetailsView(partService) != null) {
419 ((AbstractCdmDataViewer) getDetailsView(partService).getViewer()).refresh();
420 }
421 }
422
423 public static void reflowDetailsViewer(EPartService partService) {
424 if (getDetailsView(partService) != null) {
425 ((AbstractCdmDataViewer) getDetailsView(partService).getViewer()).reflow();
426 }
427 }
428
429
430 /**
431 * Orders a Collection of {@link IEnumTerm}s according to the term
432 * hierarchy. <br>
433 * <br>
434 * The returned map will be be ordered primarily by root elements,
435 * secondarily by the child elements and their children resp., both ascending alphabetically. <br>
436 * @param terms
437 * A {@link Collection} of {@link IEnumTerm}s for which the term
438 * hierarchy should be created
439 * @return a map which holds the terms as keys and their string
440 * representation via {@link IEnumTerm#getMessage()} as values
441 */
442 public static <T extends IEnumTerm<T>> LinkedHashMap<T, String> orderTerms(Collection<T> terms) {
443 TreeSet<TermNode<T>> parentElements = new TreeSet<TermNode<T>>();
444 parentElements.addAll(getTermHierarchy(terms));
445
446 // create list according to the type hierarchy (root elements alphabetically with recursive children also alphabetically)
447 LinkedHashMap<T, String> result = new LinkedHashMap<T, String>();
448 parseTermTree(parentElements, result, -1);
449 return result;
450 }
451
452 private static<T extends IEnumTerm<T>> void parseTermTree(Collection<TermNode<T>> children, LinkedHashMap<T, String> result, int depth){
453 depth++;
454 for(TermNode<T> node:children){
455 String indentString = "";
456 for(int i=0;i<depth;i++){
457 indentString += " ";
458 }
459 if(depth>0){
460 indentString += "- ";
461 }
462 result.put(node.term, indentString + node.term.getLabel());
463 parseTermTree(node.children, result, depth);
464 }
465 }
466
467 private static<T extends IEnumTerm<T>> void addToParents(List<TermNode<T>> parents, Collection<T> terms){
468 List<TermNode<T>> hasChildrenList = new ArrayList<TermNode<T>>();
469 for(T term:terms){
470 // only terms with parents
471 if(term.getKindOf()!=null){
472 TermNode<T> parentNode = new TermNode<T>(term.getKindOf());
473 TermNode<T> childNode = new TermNode<T>(term);
474 if(parents.contains(parentNode)){
475 // parent found in parent list -> add this term to parent's child list
476 parents.get(parents.indexOf(parentNode)).addChild(childNode);
477 if(!term.getGeneralizationOf().isEmpty()){
478 // has more children -> add to list which will be the parent for the next recursion
479 hasChildrenList.add(childNode);
480 }
481 }
482 }
483 }
484 if(!hasChildrenList.isEmpty()){
485 addToParents(hasChildrenList, terms);
486 }
487 }
488
489 private static<T extends IEnumTerm<T>> List<TermNode<T>> getTermHierarchy(Collection<T> terms){
490 List<TermNode<T>> parents = new ArrayList<TermNode<T>>();
491 // get root elements
492 for(T term:terms){
493 T parentTerm = term.getKindOf();
494 if(parentTerm==null){
495 // root element
496 parents.add(new TermNode<T>(term));
497 }
498 }
499 addToParents(parents, terms);
500 return parents;
501 }
502
503 @SuppressWarnings("unchecked")
504 /**
505 * Recursively iterates over all term parents until no more parent is found i.e. the root node
506 * @param term The term for which the parent should be found
507 * @return the root terms of the term hierarchy
508 */
509 private static<T extends IEnumTerm<T>> T getParentFor(T term){
510 // PP: cast should be safe. Why is Eclipse complaining??
511 T parent = term.getKindOf();
512 if(parent==null){
513 return term;
514 }
515 else{
516 return getParentFor(term.getKindOf());
517 }
518 }
519
520 private static class TermNode<T extends IEnumTerm<T>> implements Comparable<TermNode<T>>{
521 private final T term;
522 private final TreeSet<TermNode<T>> children;
523
524 public TermNode(T term) {
525 super();
526 this.term = term;
527 this.children = new TreeSet<TermNode<T>>();
528 }
529
530 public void addChild(TermNode<T> child){
531 this.children.add(child);
532 }
533
534 public TreeSet<TermNode<T>> getChildren() {
535 return children;
536 }
537
538 public T getTerm() {
539 return term;
540 }
541
542 @Override
543 public int hashCode() {
544 final int prime = 31;
545 int result = 1;
546 result = prime * result + ((term == null) ? 0 : term.hashCode());
547 return result;
548 }
549
550 @Override
551 public boolean equals(Object obj) {
552 if (this == obj) {
553 return true;
554 }
555 if (obj == null) {
556 return false;
557 }
558 if (getClass() != obj.getClass()) {
559 return false;
560 }
561 TermNode<?> other = (TermNode<?>) obj;
562 if (term == null) {
563 if (other.term != null) {
564 return false;
565 }
566 } else if (!term.equals(other.term)) {
567 return false;
568 }
569 return true;
570 }
571
572 @Override
573 public int compareTo(TermNode<T> that) {
574 return this.term.getLabel().compareTo(that.term.getLabel());
575 }
576 }
577
578 public static Object getElementsFromSelectionChangedEvent(SelectionChangedEvent event) {
579 IStructuredSelection selection = (IStructuredSelection) event.getSelection();
580 Object selectionToSet = selection;
581 if(selection.size() == 1){
582 selectionToSet = selection.getFirstElement();
583 }
584 else if(!selection.isEmpty()){
585 selectionToSet = selection.toArray();
586 }
587 return selectionToSet;
588 }
589
590 /**
591 * Executes a remoting monitored import
592 *
593 * @param label for the import
594 * @param uuid of the remoting monitor already started on the server
595 * @param pollInterval in milliseconds
596 * @param cancelable flag which determines whether the operation can be cancelled
597 * @param postOp callback for running post operation logic
598 * @return
599 */
600 public static IStatus executeMoniteredOperation(final String label,
601 final UUID uuid,
602 final int pollInterval,
603 final boolean cancelable,
604 final IPostMoniteredOperationEnabled postOp,
605 final IFeedbackGenerator feedbackGenerator,
606 final boolean showResult,
607 final boolean updateNavigator) {
608
609 try{
610 // get the remoting monitor the first time to make sure that the
611 // operation is valid
612 final IProgressMonitorService progressMonitorService = CdmApplicationState.getCurrentAppConfig().getProgressMonitorService();
613 final IRemotingProgressMonitor firstRemotingMonitor = progressMonitorService.getRemotingMonitor(uuid);
614 if(firstRemotingMonitor == null) {
615 throw new IllegalStateException("Remoting progress monitor is null");
616 }
617 if (firstRemotingMonitor.isDone()){
618 createResult(label, showResult, firstRemotingMonitor);
619 Set<Taxon> taxaToUpdate = getTaxaToUpdate(firstRemotingMonitor);
620 updateNameEditors(taxaToUpdate);
621 return Status.OK_STATUS;
622 }
623
624 Job job = new Job(label) {
625 @Override
626 public IStatus run(IProgressMonitor monitor) {
627 // run the monitor until the operation is finished
628 SubMonitor subMonitor = SubMonitor.convert(monitor, 100);
629
630
631 IRemotingProgressMonitor remotingMonitor;
632 try {
633 remotingMonitor = CdmStore.getProgressMonitorClientManager().pollMonitor(label,
634 uuid,
635 pollInterval,
636 postOp,
637 feedbackGenerator,
638 subMonitor);
639 } catch (Exception ex) {
640 return new Status(IStatus.ERROR, TaxeditorStorePlugin.PLUGIN_ID, "Operation Interrupted", ex);
641 }
642
643 // collect reports
644 // for(String report : remotingMonitor.getResult()) {
645 createResult(label, showResult, remotingMonitor);
646 Set<Taxon> taxaToUpdate = getTaxaToUpdate(remotingMonitor);
647 updateNameEditors(taxaToUpdate);
648 if (!taxaToUpdate.isEmpty() && updateNavigator){
649 refreshNavigator();
650 }
651 subMonitor.subTask("");
652 return Status.OK_STATUS;
653 }
654
655 private void refreshNavigator() {
656 EventUtility.postEvent(WorkbenchEventConstants.REFRESH_NAVIGATOR, true);
657 }
658
659 @Override
660 protected void canceling() {
661 CdmStore.getCurrentApplicationConfiguration().getProgressMonitorService().cancel(uuid);
662 }
663 };
664
665 // configure the job
666 job.setProperty(IProgressConstants.KEEP_PROPERTY, true);
667
668 job.setUser(true);
669 // schedule job
670 job.schedule();
671
672 } catch (Exception e) {
673 MessagingUtils.errorDialog("Error executing operation",
674 AbstractUtility.class,
675 "An error occurred while executing " + label,
676 TaxeditorStorePlugin.PLUGIN_ID,
677 e,
678 true);
679 }
680
681 return Status.OK_STATUS;
682 }
683
684 private static Set<Taxon> getTaxaToUpdate(IRemotingProgressMonitor remotingMonitor) {
685 Set<Taxon> taxaToUpdate = new HashSet<>();
686 if (remotingMonitor != null && remotingMonitor.getResult() instanceof UpdateResult){
687 for (CdmBase object: ((UpdateResult)remotingMonitor.getResult()).getUpdatedObjects()){
688 Taxon taxon = null;
689
690 if (object instanceof Taxon){
691 taxon = HibernateProxyHelper.deproxy(object, Taxon.class);
692 }else if (object instanceof Synonym){
693 Synonym syn = HibernateProxyHelper.deproxy(object, Synonym.class);
694 taxon = syn.getAcceptedTaxon();
695 }else if (object instanceof TaxonNode){
696 taxon = ((TaxonNode)object).getTaxon() != null? ((TaxonNode)object).getTaxon():null;
697 }
698 if (taxon != null){
699 taxaToUpdate.add(taxon);
700 }
701 }
702 }
703 return taxaToUpdate;
704 }
705
706 public static void createResult(String label, boolean showResult,
707 IRemotingProgressMonitor remotingMonitor) {
708 final StringBuilder reportSb = new StringBuilder();
709 if (remotingMonitor == null){
710 reportSb.append("Something went wrong. No result returned from server.");
711 }else if (remotingMonitor.getResult() instanceof ExportResult) {
712 reportSb.append(((ExportResult)remotingMonitor.getResult()).createReport());
713 }else if (remotingMonitor.getResult() instanceof UpdateResult){
714 UpdateResult result = (UpdateResult)remotingMonitor.getResult();
715 createUpdateResultReport(reportSb, result);
716 }else if (remotingMonitor.getReports()!= null){
717 for (String o:remotingMonitor.getReports()){
718 reportSb.append(o);
719 }
720 }
721 String report = reportSb.toString();
722 if(showResult && !StringUtils.isBlank(report)) {
723 Display.getDefault().asyncExec(new Runnable() {
724 @Override
725 public void run() {
726 // display reports with possibility to save
727 ReportTextDialog dialog = new ReportTextDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
728 dialog.setTitle(label + " Report");
729 dialog.setReportText(report);
730 dialog.open();
731 }
732 });
733 }
734 }
735
736 public static void createUpdateResultReport(final StringBuilder reportSb, UpdateResult result) {
737 if (result.isOk() || result.isAbort()){
738 SetMap<Class<? extends CdmBase>, Integer> map = getUpdateResultStatistics(result);
739 reportSb.append("Update successful. \n"
740 + "Updated Objects: " + map.sizeAll() + "\n================\n");
741 for (Class<? extends CdmBase> clazz : map.keySet()){
742 reportSb.append( CdmUtils.userFriendlyClassName(clazz)+": " + map.get(clazz).size() + "\n");
743 }
744 }
745 if (!result.getExceptions().isEmpty()){
746 reportSb.append(result.getExceptions().toString());
747 }
748 }
749
750 //TODO move to cdmlib
751 public static SetMap<Class<? extends CdmBase>, Integer> getUpdateResultStatistics(UpdateResult result) {
752 SetMap<Class<? extends CdmBase>, Integer> map = new SetMap<>();
753 for (CdmBase cdmBase : result.getUpdatedObjects()){
754 map.putItem(cdmBase.getClass(), cdmBase.getId());
755 }
756 for (CdmEntityIdentifier entity : result.getUpdatedCdmIds()){
757 map.putItem(entity.getCdmClass(), entity.getId());
758 }
759
760 return map;
761 }
762
763 private static void createExportResult(final String label, String urlString, boolean createZip,
764 IRemotingProgressMonitor remotingMonitor) {
765
766 final StringBuilder reportSb = new StringBuilder();
767 if (remotingMonitor.getResult() instanceof ExportResult){
768 ExportResult result = (ExportResult)remotingMonitor.getResult();
769
770 reportSb.append(result.createReport());
771
772 if(!StringUtils.isBlank(reportSb.toString())) {
773 Display.getDefault().asyncExec(new Runnable() {
774 @Override
775 public void run() {
776 // display reports with possibility to save
777 ReportTextDialog dialog = new ReportTextDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
778 dialog.setTitle(label + " Report");
779 dialog.setReportText(reportSb.toString());
780 dialog.open();
781 }
782 });
783 }
784
785 if (urlString != null){
786 ExportDataWrapper<?> data = result.getExportData();
787 try{
788 if (result.getExportData().getType().equals(ExportResultType.BYTE_ARRAY)){
789 byte[] exportData = (byte[])data.getExportData();
790 if(exportData != null){
791 File file = new File(urlString);
792 FileOutputStream stream = new FileOutputStream(file);
793 Writer out = new BufferedWriter(new OutputStreamWriter(
794 stream, "UTF8"));
795
796 stream.write(exportData);
797 out.flush();
798 stream.close();
799 }
800 } else if (result.getExportData().getType().equals(ExportResultType.MAP_BYTE_ARRAY)){
801 Map<String, byte[]> resultMap = (Map<String, byte[]>)data.getExportData();
802 Set<String> keySet = resultMap.keySet();
803 SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_NOW);
804 Calendar cal = Calendar.getInstance();
805 String fileEnding = ".csv";
806
807 if (createZip){
808 // File file = new File(urlString+File.separator + sdf.format(cal.getTime())+ ".zip");
809 File file = new File(urlString+ ".zip");
810 FileOutputStream stream = new FileOutputStream(file);
811 ZipOutputStream zos = new ZipOutputStream(stream);
812 for (String key: keySet){
813 byte[] fileData = resultMap.get(key);
814 ZipEntry entry = new ZipEntry( key + fileEnding);
815 zos.putNextEntry(entry);
816 zos.write(fileData);
817 zos.closeEntry();
818 }
819 zos.close();
820 }else{
821 if(result.getExportType().equals(ExportType.DWCA)){
822
823 File file = new File(urlString);
824 FileOutputStream stream = new FileOutputStream(file);
825 ZipOutputStream zos = new ZipOutputStream(stream);
826 for (String key: keySet){
827 byte[] fileData = resultMap.get(key);
828 ZipEntry entry = new ZipEntry( key);
829 zos.putNextEntry(entry);
830 zos.write(fileData);
831 zos.closeEntry();
832 }
833 zos.close();
834 }else{
835 for (String key: keySet){
836 byte[] fileData = resultMap.get(key);
837 File file = new File(urlString+File.separator + key + fileEnding);
838 FileOutputStream stream = new FileOutputStream(file);
839 Writer out = new BufferedWriter(new OutputStreamWriter(
840 stream, "UTF8"));
841 stream.write(fileData);
842 stream.close();
843 }
844 }
845 }
846 }else{
847 logger.error("This kind of result data is not supported yet." + result.getExportData().getType().toString());
848 }
849 } catch(Exception e){
850 logger.error(e.getStackTrace());
851 }
852 }
853 }
854 }
855
856 public static void updateNameEditors(Set<Taxon> taxaToUpdate){
857 for (Taxon tax: taxaToUpdate){
858 if (tax != null){
859 EventUtility.postEvent(WorkbenchEventConstants.REFRESH_NAME_EDITOR, tax.getUuid());
860 }
861 }
862 }
863 }