Project

General

Profile

Download (34.4 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.logging.log4j.LogManager;import org.apache.logging.log4j.Logger;
32
import org.eclipse.core.commands.ExecutionException;
33
import org.eclipse.core.commands.operations.AbstractOperation;
34
import org.eclipse.core.commands.operations.IOperationHistory;
35
import org.eclipse.core.runtime.IAdaptable;
36
import org.eclipse.core.runtime.ICoreRunnable;
37
import org.eclipse.core.runtime.IProgressMonitor;
38
import org.eclipse.core.runtime.IStatus;
39
import org.eclipse.core.runtime.NullProgressMonitor;
40
import org.eclipse.core.runtime.OperationCanceledException;
41
import org.eclipse.core.runtime.Status;
42
import org.eclipse.core.runtime.SubMonitor;
43
import org.eclipse.core.runtime.SubProgressMonitor;
44
import org.eclipse.core.runtime.jobs.Job;
45
import org.eclipse.e4.ui.di.UISynchronize;
46
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
47
import org.eclipse.e4.ui.workbench.modeling.EPartService;
48
import org.eclipse.jface.action.IStatusLineManager;
49
import org.eclipse.jface.viewers.IStructuredSelection;
50
import org.eclipse.jface.viewers.SelectionChangedEvent;
51
import org.eclipse.swt.graphics.Color;
52
import org.eclipse.swt.graphics.Font;
53
import org.eclipse.swt.widgets.Display;
54
import org.eclipse.swt.widgets.Shell;
55
import org.eclipse.ui.IWorkbench;
56
import org.eclipse.ui.PlatformUI;
57
import org.eclipse.ui.ide.undo.WorkspaceUndoUtil;
58
import org.eclipse.ui.progress.IProgressConstants;
59

    
60
import eu.etaxonomy.cdm.api.application.CdmApplicationState;
61
import eu.etaxonomy.cdm.api.service.IProgressMonitorService;
62
import eu.etaxonomy.cdm.api.service.UpdateResult;
63
import eu.etaxonomy.cdm.api.service.dto.CdmEntityIdentifier;
64
import eu.etaxonomy.cdm.common.CdmUtils;
65
import eu.etaxonomy.cdm.common.SetMap;
66
import eu.etaxonomy.cdm.common.monitor.IRemotingProgressMonitor;
67
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
68
import eu.etaxonomy.cdm.io.common.ExportDataWrapper;
69
import eu.etaxonomy.cdm.io.common.ExportResult;
70
import eu.etaxonomy.cdm.io.common.ExportResultType;
71
import eu.etaxonomy.cdm.io.common.ExportType;
72
import eu.etaxonomy.cdm.model.common.CdmBase;
73
import eu.etaxonomy.cdm.model.taxon.Synonym;
74
import eu.etaxonomy.cdm.model.taxon.Taxon;
75
import eu.etaxonomy.cdm.model.taxon.TaxonNode;
76
import eu.etaxonomy.cdm.model.term.IEnumTerm;
77
import eu.etaxonomy.taxeditor.event.EventUtility;
78
import eu.etaxonomy.taxeditor.event.WorkbenchEventConstants;
79
import eu.etaxonomy.taxeditor.operation.AbstractPostOperation;
80
import eu.etaxonomy.taxeditor.operation.IFeedbackGenerator;
81
import eu.etaxonomy.taxeditor.operation.IPostMoniteredOperationEnabled;
82
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
83
import eu.etaxonomy.taxeditor.operation.e4.CdmHandlerE4;
84
import eu.etaxonomy.taxeditor.store.CdmStore;
85
import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
86
import eu.etaxonomy.taxeditor.ui.dialog.ReportTextDialog;
87
import eu.etaxonomy.taxeditor.view.e4.AbstractCdmDataViewer;
88
import eu.etaxonomy.taxeditor.view.e4.details.DetailsPartE4;
89
import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
90

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

    
97
    protected static final Logger logger = LogManager.getLogger(AbstractUtility.class);
98

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

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

    
112
    public static Shell getShell() {
113
        return EventUtility.getShell();
114
    }
115

    
116
    public static IWorkbench getWorkbench() {
117
        return TaxeditorStorePlugin.getDefault().getWorkbench();
118
    }
119

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

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

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

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

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

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

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

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

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

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

    
175
        return Status.OK_STATUS;
176
    }
177

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

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

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

    
192

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

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

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

    
222
        return Status.OK_STATUS;
223
    }
224

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

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

    
256
            Job job = new Job(label) {
257

    
258

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

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

    
280

    
281

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

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

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

    
304
        return Status.OK_STATUS;
305
    }
306

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

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

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

    
319
        });
320

    
321
    }
322

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

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

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

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

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

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

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

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

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

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

    
429

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
630

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

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

    
655
                private void refreshNavigator() {
656
                    EventUtility.postEvent(WorkbenchEventConstants.REFRESH_NAVIGATOR, true);
657
                }
658

    
659
                @Override
660
                protected void canceling() {
661
                    CdmStore.getCurrentApplicationConfiguration().getProgressMonitorService().cancel(uuid);
662
                }
663
            };
664

    
665
            // configure the job
666
            job.setProperty(IProgressConstants.KEEP_PROPERTY, true);
667

    
668
            job.setUser(true);
669
            // schedule job
670
            job.schedule();
671

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

    
681
        return Status.OK_STATUS;
682
    }
683

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

    
690
                if (object instanceof Taxon){
691
                    taxon = HibernateProxyHelper.deproxy(object, Taxon.class);
692
                }else if (object instanceof Synonym){
693
                    Synonym syn = HibernateProxyHelper.deproxy(object, Synonym.class);
694
                    taxon = syn.getAcceptedTaxon();
695
                }else if (object instanceof TaxonNode){
696
                    taxon = ((TaxonNode)object).getTaxon() != null? ((TaxonNode)object).getTaxon():null;
697
                }
698
                if (taxon != null){
699
                    taxaToUpdate.add(taxon);
700
                }
701
            }
702
        }
703
        return taxaToUpdate;
704
    }
705

    
706
    public static void createResult(String label, boolean showResult,
707
            IRemotingProgressMonitor remotingMonitor) {
708
        final StringBuilder reportSb = new StringBuilder();
709
        if (remotingMonitor == null){
710
            reportSb.append("Something went wrong. No result returned from server.");
711
        }else if (remotingMonitor.getResult() instanceof ExportResult) {
712
            reportSb.append(((ExportResult)remotingMonitor.getResult()).createReport());
713
        }else if (remotingMonitor.getResult() instanceof UpdateResult){
714
            UpdateResult result = (UpdateResult)remotingMonitor.getResult();
715
            createUpdateResultReport(reportSb, result);
716
        }else if (remotingMonitor.getReports()!= null){
717
            for (String o:remotingMonitor.getReports()){
718
                reportSb.append(o);
719
            }
720
        }
721
        String report = reportSb.toString();
722
        if(showResult && !StringUtils.isBlank(report)) {
723
            Display.getDefault().asyncExec(new Runnable() {
724
                @Override
725
                public void run() {
726
                    // display reports with possibility to save
727
                    ReportTextDialog dialog = new ReportTextDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
728
                    dialog.setTitle(label + " Report");
729
                    dialog.setReportText(report);
730
                    dialog.open();
731
                }
732
            });
733
        }
734
    }
735

    
736
    public static void createUpdateResultReport(final StringBuilder reportSb, UpdateResult result) {
737
        if (result.isOk() || result.isAbort()){
738
            SetMap<Class<? extends CdmBase>, Integer> map = getUpdateResultStatistics(result);
739
            reportSb.append("Update successful. \n"
740
              + "Updated Objects: " + map.sizeAll() + "\n================\n");
741
            for (Class<? extends CdmBase> clazz : map.keySet()){
742
                reportSb.append( CdmUtils.userFriendlyClassName(clazz)+": " + map.get(clazz).size() + "\n");
743
            }
744
        }
745
        if (!result.getExceptions().isEmpty()){
746
            reportSb.append(result.getExceptions().toString());
747
        }
748
    }
749

    
750
    //TODO move to cdmlib
751
    public static SetMap<Class<? extends CdmBase>, Integer> getUpdateResultStatistics(UpdateResult result) {
752
        SetMap<Class<? extends CdmBase>, Integer> map = new SetMap<>();
753
        for (CdmBase cdmBase : result.getUpdatedObjects()){
754
            map.putItem(cdmBase.getClass(), cdmBase.getId());
755
        }
756
        for (CdmEntityIdentifier entity : result.getUpdatedCdmIds()){
757
            map.putItem(entity.getCdmClass(), entity.getId());
758
        }
759

    
760
        return map;
761
    }
762

    
763
    private static void createExportResult(final String label, String urlString, boolean createZip,
764
            IRemotingProgressMonitor remotingMonitor) {
765

    
766
        final StringBuilder reportSb = new StringBuilder();
767
        if (remotingMonitor.getResult() instanceof ExportResult){
768
            ExportResult result = (ExportResult)remotingMonitor.getResult();
769

    
770
            reportSb.append(result.createReport());
771

    
772
            if(!StringUtils.isBlank(reportSb.toString())) {
773
                Display.getDefault().asyncExec(new Runnable() {
774
                    @Override
775
                    public void run() {
776
                        // display reports with possibility to save
777
                        ReportTextDialog dialog = new ReportTextDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
778
                        dialog.setTitle(label + " Report");
779
                        dialog.setReportText(reportSb.toString());
780
                        dialog.open();
781
                    }
782
                });
783
            }
784

    
785
            if (urlString != null){
786
                 ExportDataWrapper<?> data = result.getExportData();
787
                 try{
788
                     if (result.getExportData().getType().equals(ExportResultType.BYTE_ARRAY)){
789
                         byte[] exportData = (byte[])data.getExportData();
790
                         if(exportData != null){
791
                             File file = new File(urlString);
792
                             FileOutputStream stream = new FileOutputStream(file);
793
                             Writer out = new BufferedWriter(new OutputStreamWriter(
794
                                    stream, "UTF8"));
795

    
796
                            stream.write(exportData);
797
                            out.flush();
798
                            stream.close();
799
                         }
800
                     } else if (result.getExportData().getType().equals(ExportResultType.MAP_BYTE_ARRAY)){
801
                         Map<String, byte[]> resultMap = (Map<String, byte[]>)data.getExportData();
802
                         Set<String> keySet = resultMap.keySet();
803
                         SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_NOW);
804
                         Calendar cal = Calendar.getInstance();
805
                         String fileEnding = ".csv";
806

    
807
                         if (createZip){
808
//                             File file = new File(urlString+File.separator +  sdf.format(cal.getTime())+ ".zip");
809
                             File file = new File(urlString+ ".zip");
810
                             FileOutputStream stream = new FileOutputStream(file);
811
                             ZipOutputStream zos = new ZipOutputStream(stream);
812
                             for (String key: keySet){
813
                                byte[] fileData = resultMap.get(key);
814
                                ZipEntry entry = new ZipEntry( key + fileEnding);
815
                                zos.putNextEntry(entry);
816
                                zos.write(fileData);
817
                                zos.closeEntry();
818
                             }
819
                             zos.close();
820
                         }else{
821
                            if(result.getExportType().equals(ExportType.DWCA)){
822

    
823
                                File file = new File(urlString);
824
                                FileOutputStream stream = new FileOutputStream(file);
825
                                ZipOutputStream zos = new ZipOutputStream(stream);
826
                                for (String key: keySet){
827
                                    byte[] fileData = resultMap.get(key);
828
                                    ZipEntry entry = new ZipEntry( key);
829
                                        zos.putNextEntry(entry);
830
                                        zos.write(fileData);
831
                                        zos.closeEntry();
832
                                 }
833
                                 zos.close();
834
                              }else{
835
                                 for (String key: keySet){
836
                                     byte[] fileData = resultMap.get(key);
837
                                     File file = new File(urlString+File.separator + key + fileEnding);
838
                                     FileOutputStream stream = new FileOutputStream(file);
839
                                     Writer out = new BufferedWriter(new OutputStreamWriter(
840
                                            stream, "UTF8"));
841
                                     stream.write(fileData);
842
                                     stream.close();
843
                                 }
844
                              }
845
                         }
846
                    }else{
847
                         logger.error("This kind of result data is not supported yet." + result.getExportData().getType().toString());
848
                     }
849
                 } catch(Exception e){
850
                     logger.error(e.getStackTrace());
851
                 }
852
            }
853
        }
854
    }
855

    
856
    public static void updateNameEditors(Set<Taxon> taxaToUpdate){
857
        for (Taxon tax: taxaToUpdate){
858
            if (tax != null){
859
                EventUtility.postEvent(WorkbenchEventConstants.REFRESH_NAME_EDITOR, tax.getUuid());
860
            }
861
        }
862
    }
863
}
(2-2/41)