Project

General

Profile

Download (34 KB) Statistics
| Branch: | Tag: | Revision:
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.common.monitor.IRemotingProgressMonitor;
64
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
65
import eu.etaxonomy.cdm.io.common.ExportDataWrapper;
66
import eu.etaxonomy.cdm.io.common.ExportResult;
67
import eu.etaxonomy.cdm.io.common.ExportResultType;
68
import eu.etaxonomy.cdm.io.common.ExportType;
69
import eu.etaxonomy.cdm.io.common.ImportResult;
70
import eu.etaxonomy.cdm.model.common.CdmBase;
71
import eu.etaxonomy.cdm.model.taxon.Synonym;
72
import eu.etaxonomy.cdm.model.taxon.Taxon;
73
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
74
import eu.etaxonomy.cdm.model.term.IEnumTerm;
75
import eu.etaxonomy.taxeditor.event.EventUtility;
76
import eu.etaxonomy.taxeditor.event.WorkbenchEventConstants;
77
import eu.etaxonomy.taxeditor.operation.AbstractPostOperation;
78
import eu.etaxonomy.taxeditor.operation.IFeedbackGenerator;
79
import eu.etaxonomy.taxeditor.operation.IPostMoniteredOperationEnabled;
80
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
81
import eu.etaxonomy.taxeditor.operation.e4.RemotingCdmHandlerE4;
82
import eu.etaxonomy.taxeditor.store.CdmStore;
83
import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
84
import eu.etaxonomy.taxeditor.ui.dialog.ReportTextDialog;
85
import eu.etaxonomy.taxeditor.view.e4.AbstractCdmDataViewerE4;
86
import eu.etaxonomy.taxeditor.view.e4.details.DetailsPartE4;
87
import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
88

    
89
/**
90
 * @author n.hoffmann
91
 * @created 11.05.2009
92
 */
93
public abstract class AbstractUtility {
94

    
95
    protected static final Logger logger = Logger.getLogger(AbstractUtility.class);
96

    
97
    /** Constant <code>statusLineManager</code> */
98
    protected static IStatusLineManager statusLineManager;
99
    /** Constant <code>DATE_FORMAT_NOW="yyyyMMddHHmm"</code> */
100
   	public static final String DATE_FORMAT_NOW = "yyyyMMddHHmm";
101

    
102
    public static Object getActivePart() {
103
        MPart activePart = EventUtility.getActivePart();
104
        if(activePart!=null){
105
            return activePart.getObject();
106
        }
107
        return null;
108
    }
109

    
110
    public static Shell getShell() {
111
        return EventUtility.getShell();
112
    }
113

    
114
    public static IWorkbench getWorkbench() {
115
        return TaxeditorStorePlugin.getDefault().getWorkbench();
116
    }
117

    
118
    @SuppressWarnings("unchecked")
119
    public static Object getService(Class api) {
120
        return TaxeditorStorePlugin.getDefault().getWorkbench().getService(api);
121
    }
122

    
123
    public static Font getFont(String symbolicName) {
124
        return FontResources.getFont(symbolicName);
125
    }
126

    
127
    public static Color getColor(String symbolicName) {
128
        return ColorResources.getColor(symbolicName);
129
    }
130

    
131
    public static IStatus executeOperation(final AbstractPostOperation operation, UISynchronize sync) {
132
        if (getOperationHistory() == null) {
133
            throw new IllegalArgumentException(
134
                    "There is no operation history for this context");
135
        }
136

    
137
        final IAdaptable uiInfoAdapter = WorkspaceUndoUtil
138
                .getUIInfoAdapter(getShell());
139

    
140
        Job job = Job.create(operation.getLabel(), (ICoreRunnable) monitor -> {
141
            sync.syncExec(() -> {
142
                String operationlabel = operation.getLabel();
143
                monitor.beginTask(operationlabel, 100);
144
                IStatus status = Status.CANCEL_STATUS;
145
                try {
146
                    operation.addContext(IOperationHistory.GLOBAL_UNDO_CONTEXT);
147
                    status = operation.execute(monitor, uiInfoAdapter);
148
                } catch (ExecutionException e) {
149

    
150
                    MessagingUtils.operationDialog(AbstractUtility.class, e, TaxeditorStorePlugin.PLUGIN_ID, operationlabel, null);
151

    
152
                } finally {
153
                    monitor.done();
154
                }
155

    
156
                String statusString = status.equals(Status.OK_STATUS) ? "completed"
157
                        : "cancelled";
158
                setStatusLine(operationlabel + " " + statusString + ".");
159
                IPostOperationEnabled postOperationEnabled = operation
160
                        .getPostOperationEnabled();
161
                if (postOperationEnabled != null) {
162
                    postOperationEnabled.onComplete();
163
                }
164
            });
165
        });
166

    
167
        try {
168
            job.setUser(true);
169
            job.schedule();
170
        } catch (Exception e) {
171
            MessagingUtils.messageDialog("Error executing operation", AbstractUtility.class, "An error occurred while executing " + operation.getLabel(), e);
172
        }
173

    
174
        return Status.OK_STATUS;
175
    }
176

    
177
    public static IStatus executeOperation(final AbstractOperation operation, final RemotingCdmHandlerE4 handler, UISynchronize sync) {
178
        return executeOperation_internal(operation, handler, sync);
179
    }
180

    
181
    private static IStatus executeOperation_internal(final AbstractOperation operation, final RemotingCdmHandlerE4 handler,
182
            UISynchronize sync) {
183
        if (getOperationHistory() == null) {
184
            throw new IllegalArgumentException(
185
                    "There is no operation history for this context");
186
        }
187

    
188
        final IAdaptable uiInfoAdapter = WorkspaceUndoUtil
189
                .getUIInfoAdapter(getShell());
190

    
191

    
192
        Job job = Job.create(operation.getLabel(), (ICoreRunnable) monitor -> {
193
            sync.syncExec(() -> {
194
                String operationlabel = operation.getLabel();
195
                monitor.beginTask(operationlabel, 100);
196
                IStatus status = Status.CANCEL_STATUS;
197
                try {
198
                    operation.addContext(IOperationHistory.GLOBAL_UNDO_CONTEXT);
199
                    status = operation.execute(monitor,
200
                            uiInfoAdapter);
201
                    handler.postOperation(status);
202
                } catch (ExecutionException e) {
203
                    MessagingUtils.operationDialog(AbstractUtility.class, e, TaxeditorStorePlugin.PLUGIN_ID, operationlabel, null);
204
                } finally {
205
                    monitor.done();
206
                }
207

    
208
                String statusString = status.equals(Status.OK_STATUS) ? "completed"
209
                        : "cancelled";
210
                setStatusLine(operationlabel + " " + statusString + ".");
211
            });
212
        });
213

    
214
        try {
215
            job.setUser(true);
216
            sync.syncExec(()->job.schedule());
217
        } catch (Exception e) {
218
            MessagingUtils.messageDialog("Error executing operation", AbstractUtility.class, "An error occurred while executing " + operation.getLabel(), e);
219
        }
220

    
221
        return Status.OK_STATUS;
222
    }
223

    
224
    /**
225
     * Executes a remoting monitored operation
226
     *
227
     * @param label for the operation
228
     * @param uuid of the remoting monitor already started on the server
229
     * @param pollInterval in milliseconds
230
     * @param cancelable flag which determines whether the operation can be cancelled
231
     * @param postOp callback for running post operation logic
232
     * @return
233
     */
234
    public static IStatus executeMoniteredExport(final String label,
235
            final UUID uuid,
236
            final int pollInterval,
237
            final boolean cancelable,
238
            final IPostMoniteredOperationEnabled postOp,
239
            final IFeedbackGenerator feedbackGenerator,
240
            String urlString,
241
            boolean createZip) {
242

    
243
        try {
244
            // get the remoting monitor the first time to make sure that the
245
            // operation is valid
246
            final IProgressMonitorService progressMonitorService = CdmApplicationState.getCurrentAppConfig().getProgressMonitorService();
247
            final IRemotingProgressMonitor firstRemotingMonitor = progressMonitorService.getRemotingMonitor(uuid);
248
            if(firstRemotingMonitor == null) {
249
                throw new IllegalStateException("Remoting progress monitor is null");
250
            }
251
            if (firstRemotingMonitor.isDone()){
252
                createExportResult(label, urlString, createZip, firstRemotingMonitor);
253
            }
254

    
255
            Job job = new Job(label) {
256

    
257

    
258
                @Override
259
                public IStatus run(IProgressMonitor monitor) {
260
                    // run the monitor until the operation is finished
261
                    SubMonitor subMonitor = SubMonitor.convert(monitor, 100);
262
                    //subMonitor.beginTask("Start", 100);
263
                    IRemotingProgressMonitor remotingMonitor;
264
                    try {
265
                        remotingMonitor = CdmStore.getProgressMonitorClientManager().pollMonitor(label,
266
                                uuid,
267
                                pollInterval,
268
                                postOp,
269
                                feedbackGenerator,
270
                                subMonitor);
271
                    } catch (Exception ex) {
272
                        return new Status(Status.ERROR, TaxeditorStorePlugin.PLUGIN_ID, "Operation Interrupted", ex);
273
                    }
274

    
275
                    createExportResult(label, urlString, createZip, remotingMonitor);
276
                    return Status.OK_STATUS;
277
                }
278

    
279

    
280

    
281
                @Override
282
                protected void canceling() {
283
                    CdmStore.getCurrentApplicationConfiguration().getProgressMonitorService().cancel(uuid);
284
                }
285
            };
286

    
287
            // configure the job
288
            job.setProperty(IProgressConstants.KEEP_PROPERTY, true);
289
            job.setUser(true);
290
            job.setName(label);
291
            // schedule job
292
            job.schedule();
293

    
294
        } catch (Exception e) {
295
            MessagingUtils.errorDialog("Error executing operation",
296
                    AbstractUtility.class,
297
                    "An error occurred while executing " + label,
298
                    TaxeditorStorePlugin.PLUGIN_ID,
299
                    e,
300
                    true);
301
        }
302

    
303
        return Status.OK_STATUS;
304
    }
305

    
306
    public static IOperationHistory getOperationHistory() {
307
        return getWorkbench().getOperationSupport().getOperationHistory();
308
    }
309

    
310
    public static void setStatusLine(final String message) {
311
        Display.getDefault().asyncExec(new Runnable() {
312

    
313
            @Override
314
            public void run() {
315
                statusLineManager.setMessage(message);
316
            }
317

    
318
        });
319

    
320
    }
321

    
322
    public static IProgressMonitor getMonitor() {
323
        statusLineManager.setCancelEnabled(false);
324
        return statusLineManager.getProgressMonitor();
325
    }
326

    
327
    /**
328
     * Starts either the given {@link IProgressMonitor} if it's not
329
     * <code>null</code> or a new {@link NullProgressMonitor}.
330
     *
331
     * @param progressMonitor
332
     *            The {@link IProgressMonitor} or <code>null</code> if no
333
     *            progress should be reported.
334
     * @param taskName
335
     *            The name of the main task.
336
     * @param steps
337
     *            The number of steps this task is subdivided into.
338
     * @return The {@link IProgressMonitor}.
339
     */
340
    public static IProgressMonitor startMainMonitor(
341
            IProgressMonitor progressMonitor, String taskName, int steps) {
342
        IProgressMonitor newMonitor = progressMonitor;
343
        if (newMonitor == null) {
344
            newMonitor = new NullProgressMonitor();
345
        }
346
        newMonitor.beginTask(taskName == null ? "" : taskName, steps);
347
        newMonitor.subTask(" ");
348
        return newMonitor;
349
    }
350

    
351
    /**
352
     * Creates a {@link SubProgressMonitor} if the given
353
     * {@link IProgressMonitor} is not <code>null</code> and not a
354
     * {@link NullProgressMonitor}.
355
     *
356
     * @param progressMonitor
357
     *            The parent {@link IProgressMonitor} of the
358
     *            {@link SubProgressMonitor} to be created.
359
     * @param ticks
360
     *            The number of steps this subtask is subdivided into. Must be a
361
     *            positive number and must not be
362
     *            {@link IProgressMonitor#UNKNOWN}.
363
     * @return The {@link IProgressMonitor}.
364
     */
365
    public static IProgressMonitor getSubProgressMonitor(
366
            IProgressMonitor progressMonitor, int ticks) {
367
        if (progressMonitor == null) {
368
            return new NullProgressMonitor();
369
        }
370
        if (progressMonitor instanceof NullProgressMonitor) {
371
            return progressMonitor;
372
        }
373

    
374
        return new SubProgressMonitor(progressMonitor, ticks);
375
    }
376

    
377
    /**
378
     * Checks whether the user canceled this operation. If not canceled, the
379
     * given number of steps are declared as done.
380
     *
381
     * @param newMonitor
382
     *            a {@link org.eclipse.core.runtime.IProgressMonitor} object.
383
     * @param steps
384
     *            a int.
385
     */
386
    public static void workedChecked(IProgressMonitor newMonitor, int steps) {
387
        // In case the progress monitor was canceled throw an exception.
388
        if (newMonitor.isCanceled()) {
389
            throw new OperationCanceledException();
390
        }
391
        // Otherwise declare this step as done.
392
        newMonitor.worked(steps);
393
    }
394

    
395
    public static String getPluginId() {
396
        return "eu.taxeditor";
397
    }
398

    
399
    public static Object getActiveEditor() {
400
        MPart activePart = EventUtility.getActivePart();
401
        if(activePart!=null && activePart.getObject()!=null
402
                && activePart.getObject() instanceof IE4SavablePart){
403
            return activePart.getObject();
404
        }
405
        return null;
406
    }
407

    
408
    public static DetailsPartE4 getDetailsView(EPartService partService) {
409
        MPart part = partService.findPart("eu.etaxonomy.taxeditor.view.e4.details.DetailsPartE4");
410
        if(part!=null){
411
            return (DetailsPartE4) part.getObject();
412
        }
413
        return null;
414
    }
415

    
416
    public static void refreshDetailsViewer(EPartService partService) {
417
        if (getDetailsView(partService) != null) {
418
            ((AbstractCdmDataViewerE4) getDetailsView(partService).getViewer()).refresh();
419
        }
420
    }
421

    
422
    public static void reflowDetailsViewer(EPartService partService) {
423
        if (getDetailsView(partService) != null) {
424
            ((AbstractCdmDataViewerE4) getDetailsView(partService).getViewer()).reflow();
425
        }
426
    }
427

    
428

    
429
    /**
430
     * Orders a Collection of {@link IEnumTerm}s according to the term
431
     * hierarchy. <br>
432
     * <br>
433
     * The returned map will be be ordered primarily by root elements,
434
     * secondarily by the child elements and their children resp., both ascending alphabetically. <br>
435
     * @param terms
436
     *            A {@link Collection} of {@link IEnumTerm}s for which the term
437
     *            hierarchy should be created
438
     * @return a map which holds the terms as keys and their string
439
     *         representation via {@link IEnumTerm#getMessage()} as values
440
     */
441
    public static <T extends IEnumTerm<T>> LinkedHashMap<T, String> orderTerms(Collection<T> terms) {
442
        TreeSet<TermNode<T>> parentElements = new TreeSet<TermNode<T>>();
443
        parentElements.addAll(getTermHierarchy(terms));
444

    
445
        // create list according to the type hierarchy (root elements alphabetically with recursive children also alphabetically)
446
        LinkedHashMap<T, String> result = new LinkedHashMap<T, String>();
447
        parseTermTree(parentElements, result, -1);
448
        return result;
449
    }
450

    
451
    private static<T extends IEnumTerm<T>> void parseTermTree(Collection<TermNode<T>> children, LinkedHashMap<T, String> result, int depth){
452
        depth++;
453
        for(TermNode<T> node:children){
454
            String indentString = "";
455
            for(int i=0;i<depth;i++){
456
                indentString += "  ";
457
            }
458
            if(depth>0){
459
                indentString += "- ";
460
            }
461
            result.put(node.term, indentString + node.term.getLabel());
462
            parseTermTree(node.children, result, depth);
463
        }
464
    }
465

    
466
    private static<T extends IEnumTerm<T>> void addToParents(List<TermNode<T>> parents, Collection<T> terms){
467
        List<TermNode<T>> hasChildrenList = new ArrayList<TermNode<T>>();
468
        for(T term:terms){
469
            // only terms with parents
470
            if(term.getKindOf()!=null){
471
                TermNode<T> parentNode = new TermNode<T>(term.getKindOf());
472
                TermNode<T> childNode = new TermNode<T>(term);
473
                if(parents.contains(parentNode)){
474
                    // parent found in parent list -> add this term to parent's child list
475
                    parents.get(parents.indexOf(parentNode)).addChild(childNode);
476
                    if(!term.getGeneralizationOf().isEmpty()){
477
                        // has more children -> add to list which will be the parent for the next recursion
478
                        hasChildrenList.add(childNode);
479
                    }
480
                }
481
            }
482
        }
483
        if(!hasChildrenList.isEmpty()){
484
            addToParents(hasChildrenList, terms);
485
        }
486
    }
487

    
488
    private static<T extends IEnumTerm<T>> List<TermNode<T>> getTermHierarchy(Collection<T> terms){
489
        List<TermNode<T>> parents = new ArrayList<TermNode<T>>();
490
        // get root elements
491
        for(T term:terms){
492
            T parentTerm = term.getKindOf();
493
            if(parentTerm==null){
494
                // root element
495
                parents.add(new TermNode<T>(term));
496
            }
497
        }
498
        addToParents(parents, terms);
499
        return parents;
500
    }
501

    
502
    @SuppressWarnings("unchecked")
503
    /**
504
     * Recursively iterates over all term parents until no more parent is found i.e. the root node
505
     * @param term The term for which the parent should be found
506
     * @return the root terms of the term hierarchy
507
     */
508
    private static<T extends IEnumTerm<T>> T getParentFor(T term){
509
        // PP: cast should be safe. Why is Eclipse complaining??
510
        T parent = term.getKindOf();
511
        if(parent==null){
512
            return term;
513
        }
514
        else{
515
            return getParentFor(term.getKindOf());
516
        }
517
    }
518

    
519
    private static class TermNode<T extends IEnumTerm<T>> implements Comparable<TermNode<T>>{
520
        private final T term;
521
        private final TreeSet<TermNode<T>> children;
522

    
523
        public TermNode(T term) {
524
            super();
525
            this.term = term;
526
            this.children = new TreeSet<TermNode<T>>();
527
        }
528

    
529
        public void addChild(TermNode<T> child){
530
            this.children.add(child);
531
        }
532

    
533
        public TreeSet<TermNode<T>> getChildren() {
534
            return children;
535
        }
536

    
537
        public T getTerm() {
538
            return term;
539
        }
540

    
541
        @Override
542
        public int hashCode() {
543
            final int prime = 31;
544
            int result = 1;
545
            result = prime * result + ((term == null) ? 0 : term.hashCode());
546
            return result;
547
        }
548

    
549
        @Override
550
        public boolean equals(Object obj) {
551
            if (this == obj) {
552
                return true;
553
            }
554
            if (obj == null) {
555
                return false;
556
            }
557
            if (getClass() != obj.getClass()) {
558
                return false;
559
            }
560
            TermNode other = (TermNode) obj;
561
            if (term == null) {
562
                if (other.term != null) {
563
                    return false;
564
                }
565
            } else if (!term.equals(other.term)) {
566
                return false;
567
            }
568
            return true;
569
        }
570

    
571
        @Override
572
        public int compareTo(TermNode<T> that) {
573
            return this.term.getLabel().compareTo(that.term.getLabel());
574
        }
575
    }
576

    
577
    public static Object getElementsFromSelectionChangedEvent(SelectionChangedEvent event) {
578
        IStructuredSelection selection = (IStructuredSelection) event.getSelection();
579
        Object selectionToSet = selection;
580
        if(selection.size() == 1){
581
            selectionToSet = selection.getFirstElement();
582
        }
583
        else if(!selection.isEmpty()){
584
            selectionToSet = selection.toArray();
585
        }
586
        return selectionToSet;
587
    }
588

    
589
    /**
590
     * Executes a remoting monitored import
591
     *
592
     * @param label for the import
593
     * @param uuid of the remoting monitor already started on the server
594
     * @param pollInterval in milliseconds
595
     * @param cancelable flag which determines whether the operation can be cancelled
596
     * @param postOp callback for running post operation logic
597
     * @return
598
     */
599
    public static IStatus executeMoniteredOperation(final String label,
600
            final UUID uuid,
601
            final int pollInterval,
602
            final boolean cancelable,
603
            final IPostMoniteredOperationEnabled postOp,
604
            final IFeedbackGenerator feedbackGenerator,
605
            final boolean showResult) {
606

    
607
    	try{
608
    		// get the remoting monitor the first time to make sure that the
609
            // operation is valid
610
            final IProgressMonitorService progressMonitorService = CdmApplicationState.getCurrentAppConfig().getProgressMonitorService();
611
            final IRemotingProgressMonitor firstRemotingMonitor = progressMonitorService.getRemotingMonitor(uuid);
612
            if(firstRemotingMonitor == null) {
613
                throw new IllegalStateException("Remoting progress monitor is null");
614
            }
615
            if (firstRemotingMonitor.isDone()){
616
                createResult(label, showResult, firstRemotingMonitor);
617
                Set<Taxon> taxaToUpdate = getTaxaToUpdate(firstRemotingMonitor);
618
                updateNameEditors(taxaToUpdate);
619
                return Status.OK_STATUS;
620
            }
621

    
622
            Job job = new Job(label) {
623
                @Override
624
                public IStatus run(IProgressMonitor monitor) {
625
                    // run the monitor until the operation is finished
626
                    SubMonitor subMonitor = SubMonitor.convert(monitor, 100);
627

    
628

    
629
                    IRemotingProgressMonitor remotingMonitor;
630
                    try {
631
                        remotingMonitor = CdmStore.getProgressMonitorClientManager().pollMonitor(label,
632
                                uuid,
633
                                pollInterval,
634
                                postOp,
635
                                feedbackGenerator,
636
                                subMonitor);
637
                    } catch (Exception ex) {
638
                        return new Status(Status.ERROR, TaxeditorStorePlugin.PLUGIN_ID, "Operation Interrupted", ex);
639
                    }
640

    
641
                    // collect reports
642
//	                    for(String report : remotingMonitor.getResult()) {
643
                    createResult(label, showResult, remotingMonitor);
644
                    Set<Taxon> taxaToUpdate = getTaxaToUpdate(remotingMonitor);
645
                    updateNameEditors(taxaToUpdate);
646
                    if (!taxaToUpdate.isEmpty()){
647
                        refreshNavigator();
648
                    }
649
                    return Status.OK_STATUS;
650
                }
651

    
652
                private void refreshNavigator() {
653
                    EventUtility.postEvent(WorkbenchEventConstants.REFRESH_NAVIGATOR, true);
654
                }
655

    
656
                @Override
657
                protected void canceling() {
658
                    CdmStore.getCurrentApplicationConfiguration().getProgressMonitorService().cancel(uuid);
659
                }
660
            };
661

    
662
            // configure the job
663
            job.setProperty(IProgressConstants.KEEP_PROPERTY, true);
664

    
665
            job.setUser(true);
666
            // schedule job
667
            job.schedule();
668

    
669
        } catch (Exception e) {
670
            MessagingUtils.errorDialog("Error executing operation",
671
                    AbstractUtility.class,
672
                    "An error occurred while executing " + label,
673
                    TaxeditorStorePlugin.PLUGIN_ID,
674
                    e,
675
                    true);
676
        }
677

    
678
        return Status.OK_STATUS;
679
    }
680

    
681
    private static Set<Taxon> getTaxaToUpdate(IRemotingProgressMonitor remotingMonitor) {
682
        Set<Taxon> taxaToUpdate = new HashSet<>();
683
        if (remotingMonitor.getResult() instanceof UpdateResult){
684
            for (CdmBase object: ((UpdateResult)remotingMonitor.getResult()).getUpdatedObjects()){
685
                Taxon taxon = null;
686

    
687
                if (object instanceof Taxon){
688
                    taxon = HibernateProxyHelper.deproxy(object, Taxon.class);
689
                }else if (object instanceof Synonym){
690
                    Synonym syn = HibernateProxyHelper.deproxy(object, Synonym.class);
691
                    taxon = syn.getAcceptedTaxon();
692
                }else if (object instanceof TaxonNode){
693
                    taxon = ((TaxonNode)object).getTaxon() != null? ((TaxonNode)object).getTaxon():null;
694
                }
695
                if (taxon != null){
696
                    taxaToUpdate.add(taxon);
697
                }
698
            }
699
        }else if (remotingMonitor.getResult() instanceof ImportResult){
700
            Map<String, Integer> result = ((ImportResult)remotingMonitor.getResult()).getUpdatedRecords();
701
            for (Map.Entry<String, Integer> object: result.entrySet()){
702
                Taxon taxon = null;
703
                if (object instanceof Taxon){
704
                    taxon = HibernateProxyHelper.deproxy(object, Taxon.class);
705
                }else if (object instanceof Synonym){
706
                    Synonym syn = HibernateProxyHelper.deproxy(object, Synonym.class);
707
                    taxon = syn.getAcceptedTaxon();
708
                }
709
                taxaToUpdate.add(taxon);
710
           }
711
        }
712
        return taxaToUpdate;
713
    }
714
    public static void createResult(String label, boolean showResult,
715
            IRemotingProgressMonitor remotingMonitor) {
716
        final StringBuilder reportSb = new StringBuilder();
717
        if (remotingMonitor.getResult() instanceof ExportResult) {
718
            reportSb.append(((ExportResult)remotingMonitor.getResult()).createReport());
719
        }else if (remotingMonitor.getResult() instanceof UpdateResult){
720
            if (((UpdateResult)remotingMonitor.getResult()).isOk()){
721
                int count = ((UpdateResult)remotingMonitor.getResult()).getUpdatedObjects().size();
722
                if (count == 0){
723
                    count = ((UpdateResult)remotingMonitor.getResult()).getUpdatedCdmIds().size();
724
                }
725

    
726
                reportSb.append("Update successful. \n"+"Updated Objects: " +count);
727
            }
728
            if (!((UpdateResult)remotingMonitor.getResult()).getExceptions().isEmpty()){
729
                reportSb.append(((UpdateResult)remotingMonitor.getResult()).getExceptions().toString());
730
            }
731
        }else if (remotingMonitor.getReports()!= null){
732
            for (String o:remotingMonitor.getReports()){
733
                reportSb.append(o);
734
            }
735
        }
736
        if(showResult && !StringUtils.isBlank(reportSb.toString()) && reportSb.length() != 0) {
737
            Display.getDefault().asyncExec(new Runnable() {
738
                @Override
739
                public void run() {
740
                    // display reports with possibility to save
741
                    ReportTextDialog dialog = new ReportTextDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
742
                    dialog.setTitle(label + " Report");
743
                    dialog.setReportText(reportSb.toString());
744
                    dialog.open();
745
                }
746
            });
747
        }
748
    }
749

    
750
    private static void createExportResult(final String label, String urlString, boolean createZip,
751
            IRemotingProgressMonitor remotingMonitor) {
752

    
753
        final StringBuilder reportSb = new StringBuilder();
754
        if (remotingMonitor.getResult() instanceof ExportResult){
755
            ExportResult result = (ExportResult)remotingMonitor.getResult();
756

    
757
            reportSb.append(result.createReport());
758

    
759
            if(!StringUtils.isBlank(reportSb.toString())) {
760
                Display.getDefault().asyncExec(new Runnable() {
761
                    @Override
762
                    public void run() {
763
                        // display reports with possibility to save
764
                        ReportTextDialog dialog = new ReportTextDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
765
                        dialog.setTitle(label + " Report");
766
                        dialog.setReportText(reportSb.toString());
767
                        dialog.open();
768
                    }
769
                });
770
            }
771

    
772
            if (urlString != null){
773
                 ExportDataWrapper<?> data = result.getExportData();
774
                 try{
775
                     if (result.getExportData().getType().equals(ExportResultType.BYTE_ARRAY)){
776
                         byte[] exportData = (byte[])data.getExportData();
777
                         if(exportData != null){
778
                             File file = new File(urlString);
779
                             FileOutputStream stream = new FileOutputStream(file);
780
                             Writer out = new BufferedWriter(new OutputStreamWriter(
781
                                    stream, "UTF8"));
782

    
783
                            stream.write(exportData);
784
                            out.flush();
785
                            stream.close();
786
                         }
787
                     } else if (result.getExportData().getType().equals(ExportResultType.MAP_BYTE_ARRAY)){
788
                         Map<String, byte[]> resultMap = (Map<String, byte[]>)data.getExportData();
789
                         Set<String> keySet = resultMap.keySet();
790
                         SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_NOW);
791
                         Calendar cal = Calendar.getInstance();
792
                         String fileEnding = ".csv";
793

    
794
                         if (createZip){
795
//                             File file = new File(urlString+File.separator +  sdf.format(cal.getTime())+ ".zip");
796
                             File file = new File(urlString+ ".zip");
797
                             FileOutputStream stream = new FileOutputStream(file);
798
                             ZipOutputStream zos = new ZipOutputStream(stream);
799
                             for (String key: keySet){
800
                                byte[] fileData = resultMap.get(key);
801
                                ZipEntry entry = new ZipEntry( key + fileEnding);
802
                                zos.putNextEntry(entry);
803
                                zos.write(fileData);
804
                                zos.closeEntry();
805
                             }
806
                             zos.close();
807
                         }else{
808
                            if(result.getExportType().equals(ExportType.DWCA)){
809

    
810
                                File file = new File(urlString);
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);
816
                                        zos.putNextEntry(entry);
817
                                        zos.write(fileData);
818
                                        zos.closeEntry();
819
                                 }
820
                                 zos.close();
821
                              }else{
822
                                 for (String key: keySet){
823
                                     byte[] fileData = resultMap.get(key);
824
                                     File file = new File(urlString+File.separator + key + fileEnding);
825
                                     FileOutputStream stream = new FileOutputStream(file);
826
                                     Writer out = new BufferedWriter(new OutputStreamWriter(
827
                                            stream, "UTF8"));
828
                                     stream.write(fileData);
829
                                     stream.close();
830
                                 }
831
                              }
832
                         }
833
                    }else{
834
                         logger.error("This kind of result data is not supported yet." + result.getExportData().getType().toString());
835
                     }
836
                 } catch(Exception e){
837
                     logger.error(e.getStackTrace());
838
                 }
839
            }
840
        }
841
    }
842
    public static void updateNameEditors(Set<Taxon> taxaToUpdate){
843
        for (Taxon tax: taxaToUpdate){
844
            if (tax != null){
845
                EventUtility.postEvent(WorkbenchEventConstants.REFRESH_NAME_EDITOR, tax.getUuid());
846
            }
847
        }
848
    }
849
}
(2-2/41)