Project

General

Profile

Download (31.8 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.Comparator;
22
import java.util.LinkedHashMap;
23
import java.util.List;
24
import java.util.Map;
25
import java.util.Set;
26
import java.util.TreeSet;
27
import java.util.UUID;
28
import java.util.zip.ZipEntry;
29
import java.util.zip.ZipOutputStream;
30

    
31
import org.apache.commons.lang.StringUtils;
32
import org.apache.log4j.Logger;
33
import org.eclipse.core.commands.ExecutionException;
34
import org.eclipse.core.commands.operations.AbstractOperation;
35
import org.eclipse.core.commands.operations.IOperationHistory;
36
import org.eclipse.core.runtime.IAdaptable;
37
import org.eclipse.core.runtime.ICoreRunnable;
38
import org.eclipse.core.runtime.IProgressMonitor;
39
import org.eclipse.core.runtime.IStatus;
40
import org.eclipse.core.runtime.NullProgressMonitor;
41
import org.eclipse.core.runtime.OperationCanceledException;
42
import org.eclipse.core.runtime.Status;
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.model.common.IEnumTerm;
70
import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
71
import eu.etaxonomy.taxeditor.event.EventUtility;
72
import eu.etaxonomy.taxeditor.operation.AbstractPostOperation;
73
import eu.etaxonomy.taxeditor.operation.IFeedbackGenerator;
74
import eu.etaxonomy.taxeditor.operation.IPostMoniteredOperationEnabled;
75
import eu.etaxonomy.taxeditor.operation.IPostOperationEnabled;
76
import eu.etaxonomy.taxeditor.operation.RemotingCdmHandler;
77
import eu.etaxonomy.taxeditor.operation.e4.RemotingCdmHandlerE4;
78
import eu.etaxonomy.taxeditor.store.CdmStore;
79
import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
80
import eu.etaxonomy.taxeditor.ui.dialog.ReportTextDialog;
81
import eu.etaxonomy.taxeditor.view.e4.AbstractCdmDataViewerE4;
82
import eu.etaxonomy.taxeditor.view.e4.details.DetailsPartE4;
83
import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
84

    
85
/**
86
 *
87
 * @author n.hoffmann
88
 * @created 11.05.2009
89
 * @version 1.0
90
 */
91
public abstract class AbstractUtility {
92

    
93
    protected static final Logger logger = Logger.getLogger(AbstractUtility.class);
94

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

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

    
108
    public static Shell getShell() {
109
        return EventUtility.getShell();
110
    }
111

    
112
    public static IWorkbench getWorkbench() {
113
        return TaxeditorStorePlugin.getDefault().getWorkbench();
114
    }
115

    
116
    public static Object getService(Class api) {
117
        return TaxeditorStorePlugin.getDefault().getWorkbench().getService(api);
118
    }
119

    
120
    public static Font getFont(String symbolicName) {
121
        return FontResources.getFont(symbolicName);
122
    }
123

    
124
    public static Color getColor(String symbolicName) {
125
        return ColorResources.getColor(symbolicName);
126
    }
127

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

    
134
        final IAdaptable uiInfoAdapter = WorkspaceUndoUtil
135
                .getUIInfoAdapter(getShell());
136

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

    
147
                    MessagingUtils.operationDialog(AbstractUtility.class, e, TaxeditorStorePlugin.PLUGIN_ID, operationlabel, null);
148

    
149
                } finally {
150
                    monitor.done();
151
                }
152

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

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

    
171
        return Status.OK_STATUS;
172
    }
173

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

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

    
182
    private static IStatus executeOperation_internal(final AbstractOperation operation, final Object 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
                    if(handler instanceof RemotingCdmHandler) {
203
                        ((RemotingCdmHandler) handler).postOperation(status);
204
                    }
205
                    else if(handler instanceof RemotingCdmHandlerE4) {
206
                        ((RemotingCdmHandlerE4) handler).postOperation(status);
207
                    }
208
                } catch (ExecutionException e) {
209
                    MessagingUtils.operationDialog(AbstractUtility.class, e, TaxeditorStorePlugin.PLUGIN_ID, operationlabel, null);
210
                } finally {
211
                    monitor.done();
212
                }
213

    
214
                String statusString = status.equals(Status.OK_STATUS) ? "completed"
215
                        : "cancelled";
216
                setStatusLine(operationlabel + " " + statusString + ".");
217
            });
218
        });
219

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

    
227
        return Status.OK_STATUS;
228
    }
229

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

    
249
        try {
250
            // get the remoting monitor the first time to make sure that the
251
            // operation is valid
252
            final IProgressMonitorService progressMonitorService = CdmApplicationState.getCurrentAppConfig().getProgressMonitorService();
253
//            final IRemotingProgressMonitor firstRemotingMonitor = progressMonitorService.getRemotingMonitor(uuid);
254
//            if(firstRemotingMonitor == null) {
255
//                throw new IllegalStateException("Remoting progress monitor is null");
256
//            }
257

    
258
            Job job = new Job(label) {
259

    
260

    
261
                @Override
262
                public IStatus run(IProgressMonitor monitor) {
263
                    // run the monitor until the operation is finished
264
                	monitor.beginTask("Start", 100);
265
                    IRemotingProgressMonitor remotingMonitor;
266
                    try {
267
                        remotingMonitor = CdmStore.getProgressMonitorClientManager().pollMonitor(label,
268
                                uuid,
269
                                pollInterval,
270
                                postOp,
271
                                feedbackGenerator,
272
                                monitor);
273
                    } catch (Exception ex) {
274
                        return new Status(Status.ERROR, TaxeditorStorePlugin.PLUGIN_ID, "Operation Interrupted", ex);
275
                    }
276
                    final StringBuilder reportSb = new StringBuilder();
277
                    if (remotingMonitor.getResult() instanceof ExportResult){
278
                    	ExportResult result = (ExportResult)remotingMonitor.getResult();
279

    
280
	                    reportSb.append(result.createReport());
281

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

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

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

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

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

    
366
                @Override
367
                protected void canceling() {
368
                    CdmStore.getCurrentApplicationConfiguration().getProgressMonitorService().cancel(uuid);
369
                }
370
            };
371

    
372
            // configure the job
373
            job.setProperty(IProgressConstants.KEEP_PROPERTY, true);
374
            job.setUser(true);
375
            // schedule job
376
            job.schedule();
377

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

    
387
        return Status.OK_STATUS;
388
    }
389

    
390
    public static IOperationHistory getOperationHistory() {
391
        return getWorkbench().getOperationSupport().getOperationHistory();
392
    }
393

    
394
    public static void setStatusLine(final String message) {
395
        Display.getDefault().asyncExec(new Runnable() {
396

    
397
            @Override
398
            public void run() {
399
                statusLineManager.setMessage(message);
400
            }
401

    
402
        });
403

    
404
    }
405

    
406
    public static IProgressMonitor getMonitor() {
407
        statusLineManager.setCancelEnabled(false);
408
        return statusLineManager.getProgressMonitor();
409
    }
410

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

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

    
458
        return new SubProgressMonitor(progressMonitor, ticks);
459
    }
460

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

    
479
    public static String getPluginId() {
480
        return "eu.taxeditor";
481
    }
482

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

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

    
500
    public static void refreshDetailsViewer(EPartService partService) {
501
        if (getDetailsView(partService) != null) {
502
            ((AbstractCdmDataViewerE4) getDetailsView(partService).getViewer()).refresh();
503
        }
504
    }
505

    
506
    public static void reflowDetailsViewer(EPartService partService) {
507
        if (getDetailsView(partService) != null) {
508
            ((AbstractCdmDataViewerE4) getDetailsView(partService).getViewer()).reflow();
509
        }
510
    }
511

    
512

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

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

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

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

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

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

    
603
    private static class TermNode<T extends IEnumTerm<T>> implements Comparable<TermNode<T>>{
604
        private final T term;
605
        private final TreeSet<TermNode<T>> children;
606

    
607
        public TermNode(T term) {
608
            super();
609
            this.term = term;
610
            this.children = new TreeSet<TermNode<T>>();
611
        }
612

    
613
        public void addChild(TermNode<T> child){
614
            this.children.add(child);
615
        }
616

    
617
        public TreeSet<TermNode<T>> getChildren() {
618
            return children;
619
        }
620

    
621
        public T getTerm() {
622
            return term;
623
        }
624

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

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

    
655
        @Override
656
        public int compareTo(TermNode<T> that) {
657
            return this.term.getMessage().compareTo(that.term.getMessage());
658
        }
659
    }
660

    
661
    public static Object getElementsFromSelectionChangedEvent(SelectionChangedEvent event) {
662
        IStructuredSelection selection = (IStructuredSelection) event.getSelection();
663
        Object selectionToSet = selection;
664
        if(selection.size() == 1){
665
            selectionToSet = selection.getFirstElement();
666
            if (selectionToSet instanceof Object[]){
667
                Object[] selectionArray = (Object[])selectionToSet;
668
                selectionToSet = selectionArray;
669
            }
670
        }
671
        else if(!selection.isEmpty()){
672
            selectionToSet = selection.toArray();
673
        }
674
        return selectionToSet;
675
    }
676

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

    
694
    	try{
695
    		// get the remoting monitor the first time to make sure that the
696
            // operation is valid
697
            final IProgressMonitorService progressMonitorService = CdmApplicationState.getCurrentAppConfig().getProgressMonitorService();
698
            final IRemotingProgressMonitor firstRemotingMonitor = progressMonitorService.getRemotingMonitor(uuid);
699
            if(firstRemotingMonitor == null) {
700
                throw new IllegalStateException("Remoting progress monitor is null");
701
            }
702

    
703
            Job job = new Job(label) {
704

    
705

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

    
745
                @Override
746
                protected void canceling() {
747
                    CdmStore.getCurrentApplicationConfiguration().getProgressMonitorService().cancel(uuid);
748
                }
749
            };
750

    
751
            // configure the job
752
            job.setProperty(IProgressConstants.KEEP_PROPERTY, true);
753
            job.setUser(true);
754
            // schedule job
755
            job.schedule();
756

    
757
        } catch (Exception e) {
758
            MessagingUtils.errorDialog("Error executing operation",
759
                    AbstractUtility.class,
760
                    "An error occurred while executing " + label,
761
                    TaxeditorStorePlugin.PLUGIN_ID,
762
                    e,
763
                    true);
764
        }
765

    
766
        return Status.OK_STATUS;
767
        }
768

    
769
    public static Comparator<TypeDesignationBase> getTypeDesignationComparator(){
770
        return new Comparator<TypeDesignationBase>() {
771
            @Override
772
            public int compare(TypeDesignationBase o1, TypeDesignationBase o2) {
773
                if(o1==null){
774
                    return 1;
775
                }
776
                if(o2==null){
777
                    return -1;
778
                }
779
                if(o1.getTypeStatus()==null){
780
                    return 1;
781
                }
782
                if(o2.getTypeStatus()==null){
783
                    return-1;
784
                }
785
                return HibernateProxyHelper.deproxy(o2, TypeDesignationBase.class).getTypeStatus().compareTo(HibernateProxyHelper.deproxy(o1, TypeDesignationBase.class).getTypeStatus());
786
            }
787
        };
788
    }
789

    
790
}
(2-2/41)