2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
9 package eu
.etaxonomy
.taxeditor
.model
;
11 import java
.io
.BufferedWriter
;
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
;
25 import java
.util
.TreeSet
;
26 import java
.util
.UUID
;
27 import java
.util
.zip
.ZipEntry
;
28 import java
.util
.zip
.ZipOutputStream
;
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
;
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
;
95 public abstract class AbstractUtility
{
97 protected static final Logger logger
= Logger
.getLogger(AbstractUtility
.class);
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";
104 public static Object
getActivePart() {
105 MPart activePart
= EventUtility
.getActivePart();
106 if(activePart
!=null){
107 return activePart
.getObject();
112 public static Shell
getShell() {
113 return EventUtility
.getShell();
116 public static IWorkbench
getWorkbench() {
117 return TaxeditorStorePlugin
.getDefault().getWorkbench();
120 @SuppressWarnings("unchecked")
121 public static Object
getService(Class api
) {
122 return TaxeditorStorePlugin
.getDefault().getWorkbench().getService(api
);
125 public static Font
getFont(String symbolicName
) {
126 return FontResources
.getFont(symbolicName
);
129 public static Color
getColor(String symbolicName
) {
130 return ColorResources
.getColor(symbolicName
);
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");
139 final IAdaptable uiInfoAdapter
= WorkspaceUndoUtil
.getUIInfoAdapter(getShell());
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
;
147 operation
.addContext(IOperationHistory
.GLOBAL_UNDO_CONTEXT
);
148 status
= operation
.execute(monitor
, uiInfoAdapter
);
149 } catch (ExecutionException e
) {
151 MessagingUtils
.operationDialog(AbstractUtility
.class, e
, TaxeditorStorePlugin
.PLUGIN_ID
, operationlabel
, null);
157 String statusString
= status
.equals(Status
.OK_STATUS
) ?
"completed"
159 setStatusLine(operationlabel
+ " " + statusString
+ ".");
160 IPostOperationEnabled postOperationEnabled
= operation
161 .getPostOperationEnabled();
162 if (postOperationEnabled
!= null) {
163 postOperationEnabled
.onComplete();
171 } catch (Exception e
) {
172 MessagingUtils
.messageDialog("Error executing operation", AbstractUtility
.class, "An error occurred while executing " + operation
.getLabel(), e
);
175 return Status
.OK_STATUS
;
178 public static IStatus
executeOperation(final AbstractOperation operation
, final CdmHandlerE4 handler
, UISynchronize sync
) {
179 return executeOperation_internal(operation
, handler
, sync
);
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");
189 final IAdaptable uiInfoAdapter
= WorkspaceUndoUtil
190 .getUIInfoAdapter(getShell());
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
;
199 operation
.addContext(IOperationHistory
.GLOBAL_UNDO_CONTEXT
);
200 status
= operation
.execute(monitor
,
202 handler
.postOperation(status
);
203 } catch (ExecutionException e
) {
204 MessagingUtils
.operationDialog(AbstractUtility
.class, e
, TaxeditorStorePlugin
.PLUGIN_ID
, operationlabel
, null);
209 String statusString
= status
.equals(Status
.OK_STATUS
) ?
"completed"
211 setStatusLine(operationlabel
+ " " + statusString
+ ".");
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
);
222 return Status
.OK_STATUS
;
226 * Executes a remoting monitored operation
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
235 public static IStatus
executeMoniteredExport(final String label
,
237 final int pollInterval
,
238 final boolean cancelable
,
239 final IPostMoniteredOperationEnabled postOp
,
240 final IFeedbackGenerator feedbackGenerator
,
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");
252 if (firstRemotingMonitor
.isDone()){
253 createExportResult(label
, urlString
, createZip
, firstRemotingMonitor
);
256 Job job
= new Job(label
) {
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
;
266 remotingMonitor
= CdmStore
.getProgressMonitorClientManager().pollMonitor(label
,
272 } catch (Exception ex
) {
273 return new Status(IStatus
.ERROR
, TaxeditorStorePlugin
.PLUGIN_ID
, "Operation Interrupted", ex
);
276 createExportResult(label
, urlString
, createZip
, remotingMonitor
);
277 return Status
.OK_STATUS
;
283 protected void canceling() {
284 CdmStore
.getCurrentApplicationConfiguration().getProgressMonitorService().cancel(uuid
);
289 job
.setProperty(IProgressConstants
.KEEP_PROPERTY
, true);
295 } catch (Exception e
) {
296 MessagingUtils
.errorDialog("Error executing operation",
297 AbstractUtility
.class,
298 "An error occurred while executing " + label
,
299 TaxeditorStorePlugin
.PLUGIN_ID
,
304 return Status
.OK_STATUS
;
307 public static IOperationHistory
getOperationHistory() {
308 return getWorkbench().getOperationSupport().getOperationHistory();
311 public static void setStatusLine(final String message
) {
312 Display
.getDefault().asyncExec(new Runnable() {
316 statusLineManager
.setMessage(message
);
323 public static IProgressMonitor
getMonitor() {
324 statusLineManager
.setCancelEnabled(false);
325 return statusLineManager
.getProgressMonitor();
329 * Starts either the given {@link IProgressMonitor} if it's not
330 * <code>null</code> or a new {@link NullProgressMonitor}.
332 * @param progressMonitor
333 * The {@link IProgressMonitor} or <code>null</code> if no
334 * progress should be reported.
336 * The name of the main task.
338 * The number of steps this task is subdivided into.
339 * @return The {@link IProgressMonitor}.
341 public static IProgressMonitor
startMainMonitor(
342 IProgressMonitor progressMonitor
, String taskName
, int steps
) {
343 IProgressMonitor newMonitor
= progressMonitor
;
344 if (newMonitor
== null) {
345 newMonitor
= new NullProgressMonitor();
347 newMonitor
.beginTask(taskName
== null ?
"" : taskName
, steps
);
348 newMonitor
.subTask(" ");
353 * Creates a {@link SubProgressMonitor} if the given
354 * {@link IProgressMonitor} is not <code>null</code> and not a
355 * {@link NullProgressMonitor}.
357 * @param progressMonitor
358 * The parent {@link IProgressMonitor} of the
359 * {@link SubProgressMonitor} to be created.
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}.
366 public static IProgressMonitor
getSubProgressMonitor(
367 IProgressMonitor progressMonitor
, int ticks
) {
368 if (progressMonitor
== null) {
369 return new NullProgressMonitor();
371 if (progressMonitor
instanceof NullProgressMonitor
) {
372 return progressMonitor
;
375 return new SubProgressMonitor(progressMonitor
, ticks
);
379 * Checks whether the user canceled this operation. If not canceled, the
380 * given number of steps are declared as done.
383 * a {@link org.eclipse.core.runtime.IProgressMonitor} object.
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();
392 // Otherwise declare this step as done.
393 newMonitor
.worked(steps
);
396 public static String
getPluginId() {
397 return "eu.taxeditor";
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();
409 public static DetailsPartE4
getDetailsView(EPartService partService
) {
410 MPart part
= partService
.findPart("eu.etaxonomy.taxeditor.view.e4.details.DetailsPartE4");
412 return (DetailsPartE4
) part
.getObject();
417 public static void refreshDetailsViewer(EPartService partService
) {
418 if (getDetailsView(partService
) != null) {
419 ((AbstractCdmDataViewer
) getDetailsView(partService
).getViewer()).refresh();
423 public static void reflowDetailsViewer(EPartService partService
) {
424 if (getDetailsView(partService
) != null) {
425 ((AbstractCdmDataViewer
) getDetailsView(partService
).getViewer()).reflow();
431 * Orders a Collection of {@link IEnumTerm}s according to the term
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>
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
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
));
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);
452 private static<T
extends IEnumTerm
<T
>> void parseTermTree(Collection
<TermNode
<T
>> children
, LinkedHashMap
<T
, String
> result
, int depth
){
454 for(TermNode
<T
> node
:children
){
455 String indentString
= "";
456 for(int i
=0;i
<depth
;i
++){
460 indentString
+= "- ";
462 result
.put(node
.term
, indentString
+ node
.term
.getLabel());
463 parseTermTree(node
.children
, result
, depth
);
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
>>();
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
);
484 if(!hasChildrenList
.isEmpty()){
485 addToParents(hasChildrenList
, terms
);
489 private static<T
extends IEnumTerm
<T
>> List
<TermNode
<T
>> getTermHierarchy(Collection
<T
> terms
){
490 List
<TermNode
<T
>> parents
= new ArrayList
<TermNode
<T
>>();
493 T parentTerm
= term
.getKindOf();
494 if(parentTerm
==null){
496 parents
.add(new TermNode
<T
>(term
));
499 addToParents(parents
, terms
);
503 @SuppressWarnings("unchecked")
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
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();
516 return getParentFor(term
.getKindOf());
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
;
524 public TermNode(T term
) {
527 this.children
= new TreeSet
<TermNode
<T
>>();
530 public void addChild(TermNode
<T
> child
){
531 this.children
.add(child
);
534 public TreeSet
<TermNode
<T
>> getChildren() {
543 public int hashCode() {
544 final int prime
= 31;
546 result
= prime
* result
+ ((term
== null) ?
0 : term
.hashCode());
551 public boolean equals(Object obj
) {
558 if (getClass() != obj
.getClass()) {
561 TermNode
<?
> other
= (TermNode
<?
>) obj
;
563 if (other
.term
!= null) {
566 } else if (!term
.equals(other
.term
)) {
573 public int compareTo(TermNode
<T
> that
) {
574 return this.term
.getLabel().compareTo(that
.term
.getLabel());
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();
584 else if(!selection
.isEmpty()){
585 selectionToSet
= selection
.toArray();
587 return selectionToSet
;
591 * Executes a remoting monitored import
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
600 public static IStatus
executeMoniteredOperation(final String label
,
602 final int pollInterval
,
603 final boolean cancelable
,
604 final IPostMoniteredOperationEnabled postOp
,
605 final IFeedbackGenerator feedbackGenerator
,
606 final boolean showResult
,
607 final boolean updateNavigator
) {
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");
617 if (firstRemotingMonitor
.isDone()){
618 createResult(label
, showResult
, firstRemotingMonitor
);
619 Set
<Taxon
> taxaToUpdate
= getTaxaToUpdate(firstRemotingMonitor
);
620 updateNameEditors(taxaToUpdate
);
621 return Status
.OK_STATUS
;
624 Job job
= new Job(label
) {
626 public IStatus
run(IProgressMonitor monitor
) {
627 // run the monitor until the operation is finished
628 SubMonitor subMonitor
= SubMonitor
.convert(monitor
, 100);
631 IRemotingProgressMonitor remotingMonitor
;
633 remotingMonitor
= CdmStore
.getProgressMonitorClientManager().pollMonitor(label
,
639 } catch (Exception ex
) {
640 return new Status(IStatus
.ERROR
, TaxeditorStorePlugin
.PLUGIN_ID
, "Operation Interrupted", ex
);
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
){
651 subMonitor
.subTask("");
652 return Status
.OK_STATUS
;
655 private void refreshNavigator() {
656 EventUtility
.postEvent(WorkbenchEventConstants
.REFRESH_NAVIGATOR
, true);
660 protected void canceling() {
661 CdmStore
.getCurrentApplicationConfiguration().getProgressMonitorService().cancel(uuid
);
666 job
.setProperty(IProgressConstants
.KEEP_PROPERTY
, true);
672 } catch (Exception e
) {
673 MessagingUtils
.errorDialog("Error executing operation",
674 AbstractUtility
.class,
675 "An error occurred while executing " + label
,
676 TaxeditorStorePlugin
.PLUGIN_ID
,
681 return Status
.OK_STATUS
;
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()){
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;
699 taxaToUpdate
.add(taxon
);
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()){
721 String report
= reportSb
.toString();
722 if(showResult
&& !StringUtils
.isBlank(report
)) {
723 Display
.getDefault().asyncExec(new Runnable() {
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
);
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");
745 if (!result
.getExceptions().isEmpty()){
746 reportSb
.append(result
.getExceptions().toString());
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());
756 for (CdmEntityIdentifier entity
: result
.getUpdatedCdmIds()){
757 map
.putItem(entity
.getCdmClass(), entity
.getId());
763 private static void createExportResult(final String label
, String urlString
, boolean createZip
,
764 IRemotingProgressMonitor remotingMonitor
) {
766 final StringBuilder reportSb
= new StringBuilder();
767 if (remotingMonitor
.getResult() instanceof ExportResult
){
768 ExportResult result
= (ExportResult
)remotingMonitor
.getResult();
770 reportSb
.append(result
.createReport());
772 if(!StringUtils
.isBlank(reportSb
.toString())) {
773 Display
.getDefault().asyncExec(new Runnable() {
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());
785 if (urlString
!= null){
786 ExportDataWrapper
<?
> data
= result
.getExportData();
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(
796 stream
.write(exportData
);
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";
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
);
821 if(result
.getExportType().equals(ExportType
.DWCA
)){
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
);
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(
841 stream
.write(fileData
);
847 logger
.error("This kind of result data is not supported yet." + result
.getExportData().getType().toString());
849 } catch(Exception e
){
850 logger
.error(e
.getStackTrace());
856 public static void updateNameEditors(Set
<Taxon
> taxaToUpdate
){
857 for (Taxon tax
: taxaToUpdate
){
859 EventUtility
.postEvent(WorkbenchEventConstants
.REFRESH_NAME_EDITOR
, tax
.getUuid());