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