Project

General

Profile

Download (30.7 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

    
10
package eu.etaxonomy.taxeditor.model;
11

    
12
import java.io.BufferedWriter;
13
import java.io.File;
14
import java.io.FileOutputStream;
15
import java.io.OutputStreamWriter;
16
import java.io.Writer;
17
import java.text.SimpleDateFormat;
18
import java.util.ArrayList;
19
import java.util.Calendar;
20
import java.util.Collection;
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.lang.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.SubProgressMonitor;
43
import org.eclipse.core.runtime.jobs.Job;
44
import org.eclipse.e4.ui.di.UISynchronize;
45
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
46
import org.eclipse.e4.ui.workbench.modeling.EPartService;
47
import org.eclipse.jface.action.IStatusLineManager;
48
import org.eclipse.jface.viewers.IStructuredSelection;
49
import org.eclipse.jface.viewers.SelectionChangedEvent;
50
import org.eclipse.swt.graphics.Color;
51
import org.eclipse.swt.graphics.Font;
52
import org.eclipse.swt.widgets.Display;
53
import org.eclipse.swt.widgets.Shell;
54
import org.eclipse.ui.IWorkbench;
55
import org.eclipse.ui.PlatformUI;
56
import org.eclipse.ui.ide.undo.WorkspaceUndoUtil;
57
import org.eclipse.ui.progress.IProgressConstants;
58

    
59
import eu.etaxonomy.cdm.api.application.CdmApplicationState;
60
import eu.etaxonomy.cdm.api.service.IProgressMonitorService;
61
import eu.etaxonomy.cdm.api.service.UpdateResult;
62
import eu.etaxonomy.cdm.common.monitor.IRemotingProgressMonitor;
63
import eu.etaxonomy.cdm.io.common.ExportDataWrapper;
64
import eu.etaxonomy.cdm.io.common.ExportResult;
65
import eu.etaxonomy.cdm.io.common.ExportResultType;
66
import eu.etaxonomy.cdm.io.common.ExportType;
67
import eu.etaxonomy.cdm.model.common.IEnumTerm;
68
import eu.etaxonomy.taxeditor.event.EventUtility;
69
import eu.etaxonomy.taxeditor.operation.AbstractPostOperation;
70
import eu.etaxonomy.taxeditor.operation.IFeedbackGenerator;
71
import eu.etaxonomy.taxeditor.operation.IPostMoniteredOperationEnabled;
72
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
73
import eu.etaxonomy.taxeditor.operation.RemotingCdmHandler;
74
import eu.etaxonomy.taxeditor.operation.e4.RemotingCdmHandlerE4;
75
import eu.etaxonomy.taxeditor.store.CdmStore;
76
import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
77
import eu.etaxonomy.taxeditor.ui.dialog.ReportTextDialog;
78
import eu.etaxonomy.taxeditor.view.e4.AbstractCdmDataViewerE4;
79
import eu.etaxonomy.taxeditor.view.e4.details.DetailsPartE4;
80
import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
81

    
82
/**
83
 *
84
 * @author n.hoffmann
85
 * @created 11.05.2009
86
 * @version 1.0
87
 */
88
public abstract class AbstractUtility {
89

    
90
    protected static final Logger logger = Logger.getLogger(AbstractUtility.class);
91

    
92
    /** Constant <code>statusLineManager</code> */
93
    protected static IStatusLineManager statusLineManager;
94
    /** Constant <code>DATE_FORMAT_NOW="yyyyMMddHHmm"</code> */
95
   	public static final String DATE_FORMAT_NOW = "yyyyMMddHHmm";
96

    
97
    public static Object getActivePart() {
98
        MPart activePart = EventUtility.getActivePart();
99
        if(activePart!=null){
100
            return activePart.getObject();
101
        }
102
        return null;
103
    }
104

    
105
    public static Shell getShell() {
106
        return EventUtility.getShell();
107
    }
108

    
109
    public static IWorkbench getWorkbench() {
110
        return TaxeditorStorePlugin.getDefault().getWorkbench();
111
    }
112

    
113
    public static Object getService(Class api) {
114
        return TaxeditorStorePlugin.getDefault().getWorkbench().getService(api);
115
    }
116

    
117
    public static Font getFont(String symbolicName) {
118
        return FontResources.getFont(symbolicName);
119
    }
120

    
121
    public static Color getColor(String symbolicName) {
122
        return ColorResources.getColor(symbolicName);
123
    }
124

    
125
    public static IStatus executeOperation(final AbstractPostOperation operation, UISynchronize sync) {
126
        if (getOperationHistory() == null) {
127
            throw new IllegalArgumentException(
128
                    "There is no operation history for this context");
129
        }
130

    
131
        final IAdaptable uiInfoAdapter = WorkspaceUndoUtil
132
                .getUIInfoAdapter(getShell());
133

    
134
        Job job = Job.create(operation.getLabel(), (ICoreRunnable) monitor -> {
135
            sync.syncExec(() -> {
136
                String operationlabel = operation.getLabel();
137
                monitor.beginTask(operationlabel, 100);
138
                IStatus status = Status.CANCEL_STATUS;
139
                try {
140
                    operation.addContext(IOperationHistory.GLOBAL_UNDO_CONTEXT);
141
                    status = operation.execute(monitor, uiInfoAdapter);
142
                } catch (ExecutionException e) {
143

    
144
                    MessagingUtils.operationDialog(AbstractUtility.class, e, TaxeditorStorePlugin.PLUGIN_ID, operationlabel, null);
145

    
146
                } finally {
147
                    monitor.done();
148
                }
149

    
150
                String statusString = status.equals(Status.OK_STATUS) ? "completed"
151
                        : "cancelled";
152
                setStatusLine(operationlabel + " " + statusString + ".");
153
                IPostOperationEnabled postOperationEnabled = operation
154
                        .getPostOperationEnabled();
155
                if (postOperationEnabled != null) {
156
                    postOperationEnabled.onComplete();
157
                }
158
            });
159
        });
160

    
161
        try {
162
            job.setUser(true);
163
            job.schedule();
164
        } catch (Exception e) {
165
            MessagingUtils.messageDialog("Error executing operation", AbstractUtility.class, "An error occurred while executing " + operation.getLabel(), e);
166
        }
167

    
168
        return Status.OK_STATUS;
169
    }
170

    
171
    public static IStatus executeOperation(final AbstractOperation operation, final RemotingCdmHandlerE4 handler, UISynchronize sync) {
172
        return executeOperation_internal(operation, handler, sync);
173
    }
174

    
175
    public static IStatus executeOperation(final AbstractOperation operation, final RemotingCdmHandler handler, UISynchronize sync) {
176
        return executeOperation_internal(operation, handler, sync);
177
    }
178

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

    
186
        final IAdaptable uiInfoAdapter = WorkspaceUndoUtil
187
                .getUIInfoAdapter(getShell());
188

    
189

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

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

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

    
224
        return Status.OK_STATUS;
225
    }
226

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

    
246
        try {
247
            // get the remoting monitor the first time to make sure that the
248
            // operation is valid
249
            final IProgressMonitorService progressMonitorService = CdmApplicationState.getCurrentAppConfig().getProgressMonitorService();
250
            final IRemotingProgressMonitor firstRemotingMonitor = progressMonitorService.getRemotingMonitor(uuid);
251
            if(firstRemotingMonitor == null) {
252
                throw new IllegalStateException("Remoting progress monitor is null");
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
                	monitor.beginTask("Start", 100);
262
                    IRemotingProgressMonitor remotingMonitor;
263
                    try {
264
                        remotingMonitor = CdmStore.getProgressMonitorClientManager().pollMonitor(label,
265
                                uuid,
266
                                pollInterval,
267
                                postOp,
268
                                feedbackGenerator,
269
                                monitor);
270
                    } catch (Exception ex) {
271
                        return new Status(Status.ERROR, TaxeditorStorePlugin.PLUGIN_ID, "Operation Interrupted", ex);
272
                    }
273
                    final StringBuilder reportSb = new StringBuilder();
274
                    if (remotingMonitor.getResult() instanceof ExportResult){
275
                    	ExportResult result = (ExportResult)remotingMonitor.getResult();
276

    
277
	                    reportSb.append(result.createReport());
278

    
279
	                    if(!StringUtils.isBlank(reportSb.toString())) {
280
	                        Display.getDefault().asyncExec(new Runnable() {
281
	                            @Override
282
	                            public void run() {
283
	                                // display reports with possibility to save
284
	                                ReportTextDialog dialog = new ReportTextDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
285
	                                dialog.setTitle(label + " Report");
286
	                                dialog.setReportText(reportSb.toString());
287
	                                dialog.open();
288
	                            }
289
	                        });
290
	                    }
291

    
292
	                    if (urlString != null){
293
	                    	 ExportDataWrapper data = result.getExportData();
294
	                         try{
295
	                             if (result.getExportData().getType().equals(ExportResultType.BYTE_ARRAY)){
296
	                                 byte[] exportData = (byte[])data.getExportData();
297
	                                 if(exportData != null){
298
	                                     File file = new File(urlString);
299
	                                     FileOutputStream stream = new FileOutputStream(file);
300
	                                     Writer out = new BufferedWriter(new OutputStreamWriter(
301
	                                 			stream, "UTF8"));
302

    
303
	                                 	stream.write(exportData);
304
	                                    out.flush();
305
	                                    stream.close();
306
	                                 }
307
	                             } else if (result.getExportData().getType().equals(ExportResultType.MAP_BYTE_ARRAY)){
308
	                                 Map<String, byte[]> resultMap = (Map<String, byte[]>)data.getExportData();
309
	                                 Set<String> keySet = resultMap.keySet();
310
	                                 SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_NOW);
311
	                                 Calendar cal = Calendar.getInstance();
312
	                                 String fileEnding = ".csv";
313

    
314
	                                 if (createZip){
315
	                            		 File file = new File(urlString+File.separator +  sdf.format(cal.getTime())+ ".zip");
316
	                                     FileOutputStream stream = new FileOutputStream(file);
317
	                                     ZipOutputStream zos = new ZipOutputStream(stream);
318
	                                     for (String key: keySet){
319
	                                    	byte[] fileData = resultMap.get(key);
320
	                                    	ZipEntry entry = new ZipEntry( key + fileEnding);
321
	         								zos.putNextEntry(entry);
322
	         								zos.write(fileData);
323
	         								zos.closeEntry();
324
	                                     }
325
	                                     zos.close();
326
	                            	 }else{
327
	                            		if(result.getExportType().equals(ExportType.DWCA)){
328

    
329
	                                        File file = new File(urlString);
330
	                                        FileOutputStream stream = new FileOutputStream(file);
331
	                                        ZipOutputStream zos = new ZipOutputStream(stream);
332
	                                        for (String key: keySet){
333
             	                               	byte[] fileData = resultMap.get(key);
334
             	                               	ZipEntry entry = new ZipEntry( key);
335
             	    								zos.putNextEntry(entry);
336
             	    								zos.write(fileData);
337
             	    								zos.closeEntry();
338
	                                         }
339
	                                         zos.close();
340
	                                      }else{
341
		                            		 for (String key: keySet){
342
		                            			 byte[] fileData = resultMap.get(key);
343
		                            			 File file = new File(urlString+File.separator + key + fileEnding);
344
		                                         FileOutputStream stream = new FileOutputStream(file);
345
		                                         Writer out = new BufferedWriter(new OutputStreamWriter(
346
		                                     			stream, "UTF8"));
347
		                                         stream.write(fileData);
348
		                                         stream.close();
349
		                                     }
350
	                                      }
351
	                            	 }
352
	                            }else{
353
	                                 logger.error("This kind of result data is not supported yet." + result.getExportData().getType().toString());
354
	                             }
355
	                         } catch(Exception e){
356
	                             logger.error(e.getStackTrace());
357
	                         }
358
	                    }
359
                    }
360
                    return Status.OK_STATUS;
361
                }
362

    
363
                @Override
364
                protected void canceling() {
365
                    CdmStore.getCurrentApplicationConfiguration().getProgressMonitorService().cancel(uuid);
366
                }
367
            };
368

    
369
            // configure the job
370
            job.setProperty(IProgressConstants.KEEP_PROPERTY, true);
371
            job.setUser(true);
372
            // schedule job
373
            job.schedule();
374

    
375
        } catch (Exception e) {
376
            MessagingUtils.errorDialog("Error executing operation",
377
                    AbstractUtility.class,
378
                    "An error occurred while executing " + label,
379
                    TaxeditorStorePlugin.PLUGIN_ID,
380
                    e,
381
                    true);
382
        }
383

    
384
        return Status.OK_STATUS;
385
    }
386

    
387
    public static IOperationHistory getOperationHistory() {
388
        return getWorkbench().getOperationSupport().getOperationHistory();
389
    }
390

    
391
    public static void setStatusLine(final String message) {
392
        Display.getDefault().asyncExec(new Runnable() {
393

    
394
            @Override
395
            public void run() {
396
                statusLineManager.setMessage(message);
397
            }
398

    
399
        });
400

    
401
    }
402

    
403
    public static IProgressMonitor getMonitor() {
404
        statusLineManager.setCancelEnabled(false);
405
        return statusLineManager.getProgressMonitor();
406
    }
407

    
408
    /**
409
     * Starts either the given {@link IProgressMonitor} if it's not
410
     * <code>null</code> or a new {@link NullProgressMonitor}.
411
     *
412
     * @param progressMonitor
413
     *            The {@link IProgressMonitor} or <code>null</code> if no
414
     *            progress should be reported.
415
     * @param taskName
416
     *            The name of the main task.
417
     * @param steps
418
     *            The number of steps this task is subdivided into.
419
     * @return The {@link IProgressMonitor}.
420
     */
421
    public static IProgressMonitor startMainMonitor(
422
            IProgressMonitor progressMonitor, String taskName, int steps) {
423
        IProgressMonitor newMonitor = progressMonitor;
424
        if (newMonitor == null) {
425
            newMonitor = new NullProgressMonitor();
426
        }
427
        newMonitor.beginTask(taskName == null ? "" : taskName, steps);
428
        newMonitor.subTask(" ");
429
        return newMonitor;
430
    }
431

    
432
    /**
433
     * Creates a {@link SubProgressMonitor} if the given
434
     * {@link IProgressMonitor} is not <code>null</code> and not a
435
     * {@link NullProgressMonitor}.
436
     *
437
     * @param progressMonitor
438
     *            The parent {@link IProgressMonitor} of the
439
     *            {@link SubProgressMonitor} to be created.
440
     * @param ticks
441
     *            The number of steps this subtask is subdivided into. Must be a
442
     *            positive number and must not be
443
     *            {@link IProgressMonitor#UNKNOWN}.
444
     * @return The {@link IProgressMonitor}.
445
     */
446
    public static IProgressMonitor getSubProgressMonitor(
447
            IProgressMonitor progressMonitor, int ticks) {
448
        if (progressMonitor == null) {
449
            return new NullProgressMonitor();
450
        }
451
        if (progressMonitor instanceof NullProgressMonitor) {
452
            return progressMonitor;
453
        }
454

    
455
        return new SubProgressMonitor(progressMonitor, ticks);
456
    }
457

    
458
    /**
459
     * Checks whether the user canceled this operation. If not canceled, the
460
     * given number of steps are declared as done.
461
     *
462
     * @param newMonitor
463
     *            a {@link org.eclipse.core.runtime.IProgressMonitor} object.
464
     * @param steps
465
     *            a int.
466
     */
467
    public static void workedChecked(IProgressMonitor newMonitor, int steps) {
468
        // In case the progress monitor was canceled throw an exception.
469
        if (newMonitor.isCanceled()) {
470
            throw new OperationCanceledException();
471
        }
472
        // Otherwise declare this step as done.
473
        newMonitor.worked(steps);
474
    }
475

    
476
    public static String getPluginId() {
477
        return "eu.taxeditor";
478
    }
479

    
480
    public static Object getActiveEditor() {
481
        MPart activePart = EventUtility.getActivePart();
482
        if(activePart!=null && activePart.getObject()!=null
483
                && activePart.getObject() instanceof IE4SavablePart){
484
            return activePart.getObject();
485
        }
486
        return null;
487
    }
488

    
489
    public static DetailsPartE4 getDetailsView(EPartService partService) {
490
        MPart part = partService.findPart("eu.etaxonomy.taxeditor.view.e4.details.DetailsPartE4");
491
        if(part!=null){
492
            return (DetailsPartE4) part.getObject();
493
        }
494
        return null;
495
    }
496

    
497
    public static void refreshDetailsViewer(EPartService partService) {
498
        if (getDetailsView(partService) != null) {
499
            ((AbstractCdmDataViewerE4) getDetailsView(partService).getViewer()).refresh();
500
        }
501
    }
502

    
503
    public static void reflowDetailsViewer(EPartService partService) {
504
        if (getDetailsView(partService) != null) {
505
            ((AbstractCdmDataViewerE4) getDetailsView(partService).getViewer()).reflow();
506
        }
507
    }
508

    
509

    
510
    /**
511
     * Orders a Collection of {@link IEnumTerm}s according to the term
512
     * hierarchy. <br>
513
     * <br>
514
     * The returned map will be be ordered primarily by root elements,
515
     * secondarily by the child elements and their children resp., both ascending alphabetically. <br>
516
     * @param terms
517
     *            A {@link Collection} of {@link IEnumTerm}s for which the term
518
     *            hierarchy should be created
519
     * @return a map which holds the terms as keys and their string
520
     *         representation via {@link IEnumTerm#getMessage()} as values
521
     */
522
    public static <T extends IEnumTerm<T>> LinkedHashMap<T, String> orderTerms(Collection<T> terms) {
523
        TreeSet<TermNode<T>> parentElements = new TreeSet<TermNode<T>>();
524
        parentElements.addAll(getTermHierarchy(terms));
525

    
526
        // create list according to the type hierarchy (root elements alphabetically with recursive children also alphabetically)
527
        LinkedHashMap<T, String> result = new LinkedHashMap<T, String>();
528
        parseTermTree(parentElements, result, -1);
529
        return result;
530
    }
531

    
532
    private static<T extends IEnumTerm<T>> void parseTermTree(Collection<TermNode<T>> children, LinkedHashMap<T, String> result, int depth){
533
        depth++;
534
        for(TermNode<T> node:children){
535
            String indentString = "";
536
            for(int i=0;i<depth;i++){
537
                indentString += "  ";
538
            }
539
            if(depth>0){
540
                indentString += "- ";
541
            }
542
            result.put(node.term, indentString + node.term.getMessage());
543
            parseTermTree(node.children, result, depth);
544
        }
545
    }
546

    
547
    private static<T extends IEnumTerm<T>> void addToParents(List<TermNode<T>> parents, Collection<T> terms){
548
        List<TermNode<T>> hasChildrenList = new ArrayList<TermNode<T>>();
549
        for(T term:terms){
550
            // only terms with parents
551
            if(term.getKindOf()!=null){
552
                TermNode<T> parentNode = new TermNode<T>(term.getKindOf());
553
                TermNode<T> childNode = new TermNode<T>(term);
554
                if(parents.contains(parentNode)){
555
                    // parent found in parent list -> add this term to parent's child list
556
                    parents.get(parents.indexOf(parentNode)).addChild(childNode);
557
                    if(!term.getGeneralizationOf().isEmpty()){
558
                        // has more children -> add to list which will be the parent for the next recursion
559
                        hasChildrenList.add(childNode);
560
                    }
561
                }
562
            }
563
        }
564
        if(!hasChildrenList.isEmpty()){
565
            addToParents(hasChildrenList, terms);
566
        }
567
    }
568

    
569
    private static<T extends IEnumTerm<T>> List<TermNode<T>> getTermHierarchy(Collection<T> terms){
570
        List<TermNode<T>> parents = new ArrayList<TermNode<T>>();
571
        // get root elements
572
        for(T term:terms){
573
            T parentTerm = term.getKindOf();
574
            if(parentTerm==null){
575
                // root element
576
                parents.add(new TermNode<T>(term));
577
            }
578
        }
579
        addToParents(parents, terms);
580
        return parents;
581
    }
582

    
583
    @SuppressWarnings("unchecked")
584
    /**
585
     * Recursively iterates over all term parents until no more parent is found i.e. the root node
586
     * @param term The term for which the parent should be found
587
     * @return the root terms of the term hierarchy
588
     */
589
    private static<T extends IEnumTerm<T>> T getParentFor(T term){
590
        // PP: cast should be safe. Why is Eclipse complaining??
591
        T parent = term.getKindOf();
592
        if(parent==null){
593
            return term;
594
        }
595
        else{
596
            return getParentFor(term.getKindOf());
597
        }
598
    }
599

    
600
    private static class TermNode<T extends IEnumTerm<T>> implements Comparable<TermNode<T>>{
601
        private final T term;
602
        private final TreeSet<TermNode<T>> children;
603

    
604
        public TermNode(T term) {
605
            super();
606
            this.term = term;
607
            this.children = new TreeSet<TermNode<T>>();
608
        }
609

    
610
        public void addChild(TermNode<T> child){
611
            this.children.add(child);
612
        }
613

    
614
        public TreeSet<TermNode<T>> getChildren() {
615
            return children;
616
        }
617

    
618
        public T getTerm() {
619
            return term;
620
        }
621

    
622
        @Override
623
        public int hashCode() {
624
            final int prime = 31;
625
            int result = 1;
626
            result = prime * result + ((term == null) ? 0 : term.hashCode());
627
            return result;
628
        }
629

    
630
        @Override
631
        public boolean equals(Object obj) {
632
            if (this == obj) {
633
                return true;
634
            }
635
            if (obj == null) {
636
                return false;
637
            }
638
            if (getClass() != obj.getClass()) {
639
                return false;
640
            }
641
            TermNode other = (TermNode) obj;
642
            if (term == null) {
643
                if (other.term != null) {
644
                    return false;
645
                }
646
            } else if (!term.equals(other.term)) {
647
                return false;
648
            }
649
            return true;
650
        }
651

    
652
        @Override
653
        public int compareTo(TermNode<T> that) {
654
            return this.term.getMessage().compareTo(that.term.getMessage());
655
        }
656
    }
657

    
658
    public static Object getElementsFromSelectionChangedEvent(SelectionChangedEvent event) {
659
        IStructuredSelection selection = (IStructuredSelection) event.getSelection();
660
        Object selectionToSet = selection;
661
        if(selection.size() == 1){
662
            selectionToSet = selection.getFirstElement();
663
        }
664
        else if(!selection.isEmpty()){
665
            selectionToSet = selection.toArray();
666
        }
667
        return selectionToSet;
668
    }
669

    
670
    /**
671
     * Executes a remoting monitored import
672
     *
673
     * @param label for the import
674
     * @param uuid of the remoting monitor already started on the server
675
     * @param pollInterval in milliseconds
676
     * @param cancelable flag which determines whether the operation can be cancelled
677
     * @param postOp callback for running post operation logic
678
     * @return
679
     */
680
    public static IStatus executeMoniteredOperation(final String label,
681
            final UUID uuid,
682
            final int pollInterval,
683
            final boolean cancelable,
684
            final IPostMoniteredOperationEnabled postOp,
685
            final IFeedbackGenerator feedbackGenerator) {
686

    
687
    	try{
688
    		// get the remoting monitor the first time to make sure that the
689
            // operation is valid
690
            final IProgressMonitorService progressMonitorService = CdmApplicationState.getCurrentAppConfig().getProgressMonitorService();
691
            final IRemotingProgressMonitor firstRemotingMonitor = progressMonitorService.getRemotingMonitor(uuid);
692
            if(firstRemotingMonitor == null) {
693
                throw new IllegalStateException("Remoting progress monitor is null");
694
            }
695

    
696
            Job job = new Job(label) {
697

    
698

    
699
                @Override
700
                public IStatus run(IProgressMonitor monitor) {
701
                    // run the monitor until the operation is finished
702
                	monitor.beginTask("Start", 100);
703
                    IRemotingProgressMonitor remotingMonitor;
704
                    try {
705
                        remotingMonitor = CdmStore.getProgressMonitorClientManager().pollMonitor(label,
706
                                uuid,
707
                                pollInterval,
708
                                postOp,
709
                                feedbackGenerator,
710
                                monitor);
711
                    } catch (Exception ex) {
712
                        return new Status(Status.ERROR, TaxeditorStorePlugin.PLUGIN_ID, "Operation Interrupted", ex);
713
                    }
714
                    final StringBuilder reportSb = new StringBuilder();
715
                    // collect reports
716
//	                    for(String report : remotingMonitor.getResult()) {
717
                    if (remotingMonitor.getResult() instanceof ExportResult) {
718
                        reportSb.append(((ExportResult)remotingMonitor.getResult()).createReport());
719
                    }else if (remotingMonitor.getResult() instanceof UpdateResult){
720
                        reportSb.append(((UpdateResult)remotingMonitor.getResult()).getExceptions().toString());
721
                    }
722
//	                    }
723
                    if(!StringUtils.isBlank(reportSb.toString())) {
724
                        Display.getDefault().asyncExec(new Runnable() {
725
                            @Override
726
                            public void run() {
727
                                // display reports with possibility to save
728
                                ReportTextDialog dialog = new ReportTextDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
729
                                dialog.setTitle(label + " Report");
730
                                dialog.setReportText(reportSb.toString());
731
                                dialog.open();
732
                            }
733
                        });
734
                    }
735
                    return Status.OK_STATUS;
736
                }
737

    
738
                @Override
739
                protected void canceling() {
740
                    CdmStore.getCurrentApplicationConfiguration().getProgressMonitorService().cancel(uuid);
741
                }
742
            };
743

    
744
            // configure the job
745
            job.setProperty(IProgressConstants.KEEP_PROPERTY, true);
746
            job.setUser(true);
747
            // schedule job
748
            job.schedule();
749

    
750
        } catch (Exception e) {
751
            MessagingUtils.errorDialog("Error executing operation",
752
                    AbstractUtility.class,
753
                    "An error occurred while executing " + label,
754
                    TaxeditorStorePlugin.PLUGIN_ID,
755
                    e,
756
                    true);
757
        }
758

    
759
        return Status.OK_STATUS;
760
        }
761

    
762
}
(2-2/41)