Fix potential NPE
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / model / AbstractUtility.java
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.e4.RemotingCdmHandlerE4;
74 import eu.etaxonomy.taxeditor.store.CdmStore;
75 import eu.etaxonomy.taxeditor.store.internal.TaxeditorStorePlugin;
76 import eu.etaxonomy.taxeditor.ui.dialog.ReportTextDialog;
77 import eu.etaxonomy.taxeditor.view.e4.AbstractCdmDataViewerE4;
78 import eu.etaxonomy.taxeditor.view.e4.details.DetailsPartE4;
79 import eu.etaxonomy.taxeditor.workbench.part.IE4SavablePart;
80
81 /**
82 *
83 * @author n.hoffmann
84 * @created 11.05.2009
85 * @version 1.0
86 */
87 public abstract class AbstractUtility {
88
89 protected static final Logger logger = Logger.getLogger(AbstractUtility.class);
90
91 /** Constant <code>statusLineManager</code> */
92 protected static IStatusLineManager statusLineManager;
93 /** Constant <code>DATE_FORMAT_NOW="yyyyMMddHHmm"</code> */
94 public static final String DATE_FORMAT_NOW = "yyyyMMddHHmm";
95
96 public static Object getActivePart() {
97 MPart activePart = EventUtility.getActivePart();
98 if(activePart!=null){
99 return activePart.getObject();
100 }
101 return null;
102 }
103
104 public static Shell getShell() {
105 return EventUtility.getShell();
106 }
107
108 public static IWorkbench getWorkbench() {
109 return TaxeditorStorePlugin.getDefault().getWorkbench();
110 }
111
112 public static Object getService(Class api) {
113 return TaxeditorStorePlugin.getDefault().getWorkbench().getService(api);
114 }
115
116 public static Font getFont(String symbolicName) {
117 return FontResources.getFont(symbolicName);
118 }
119
120 public static Color getColor(String symbolicName) {
121 return ColorResources.getColor(symbolicName);
122 }
123
124 public static IStatus executeOperation(final AbstractPostOperation operation, UISynchronize sync) {
125 if (getOperationHistory() == null) {
126 throw new IllegalArgumentException(
127 "There is no operation history for this context");
128 }
129
130 final IAdaptable uiInfoAdapter = WorkspaceUndoUtil
131 .getUIInfoAdapter(getShell());
132
133 Job job = Job.create(operation.getLabel(), (ICoreRunnable) monitor -> {
134 sync.syncExec(() -> {
135 String operationlabel = operation.getLabel();
136 monitor.beginTask(operationlabel, 100);
137 IStatus status = Status.CANCEL_STATUS;
138 try {
139 operation.addContext(IOperationHistory.GLOBAL_UNDO_CONTEXT);
140 status = operation.execute(monitor, uiInfoAdapter);
141 } catch (ExecutionException e) {
142
143 MessagingUtils.operationDialog(AbstractUtility.class, e, TaxeditorStorePlugin.PLUGIN_ID, operationlabel, null);
144
145 } finally {
146 monitor.done();
147 }
148
149 String statusString = status.equals(Status.OK_STATUS) ? "completed"
150 : "cancelled";
151 setStatusLine(operationlabel + " " + statusString + ".");
152 IPostOperationEnabled postOperationEnabled = operation
153 .getPostOperationEnabled();
154 if (postOperationEnabled != null) {
155 postOperationEnabled.onComplete();
156 }
157 });
158 });
159
160 try {
161 job.setUser(true);
162 job.schedule();
163 } catch (Exception e) {
164 MessagingUtils.messageDialog("Error executing operation", AbstractUtility.class, "An error occurred while executing " + operation.getLabel(), e);
165 }
166
167 return Status.OK_STATUS;
168 }
169
170 public static IStatus executeOperation(final AbstractOperation operation, final RemotingCdmHandlerE4 handler, UISynchronize sync) {
171 return executeOperation_internal(operation, handler, sync);
172 }
173
174 private static IStatus executeOperation_internal(final AbstractOperation operation, final RemotingCdmHandlerE4 handler,
175 UISynchronize sync) {
176 if (getOperationHistory() == null) {
177 throw new IllegalArgumentException(
178 "There is no operation history for this context");
179 }
180
181 final IAdaptable uiInfoAdapter = WorkspaceUndoUtil
182 .getUIInfoAdapter(getShell());
183
184
185 Job job = Job.create(operation.getLabel(), (ICoreRunnable) monitor -> {
186 sync.syncExec(() -> {
187 String operationlabel = operation.getLabel();
188 monitor.beginTask(operationlabel, 100);
189 IStatus status = Status.CANCEL_STATUS;
190 try {
191 operation.addContext(IOperationHistory.GLOBAL_UNDO_CONTEXT);
192 status = operation.execute(monitor,
193 uiInfoAdapter);
194 handler.postOperation(status);
195 } catch (ExecutionException e) {
196 MessagingUtils.operationDialog(AbstractUtility.class, e, TaxeditorStorePlugin.PLUGIN_ID, operationlabel, null);
197 } finally {
198 monitor.done();
199 }
200
201 String statusString = status.equals(Status.OK_STATUS) ? "completed"
202 : "cancelled";
203 setStatusLine(operationlabel + " " + statusString + ".");
204 });
205 });
206
207 try {
208 job.setUser(true);
209 sync.syncExec(()->job.schedule());
210 } catch (Exception e) {
211 MessagingUtils.messageDialog("Error executing operation", AbstractUtility.class, "An error occurred while executing " + operation.getLabel(), e);
212 }
213
214 return Status.OK_STATUS;
215 }
216
217 /**
218 * Executes a remoting monitored operation
219 *
220 * @param label for the operation
221 * @param uuid of the remoting monitor already started on the server
222 * @param pollInterval in milliseconds
223 * @param cancelable flag which determines whether the operation can be cancelled
224 * @param postOp callback for running post operation logic
225 * @return
226 */
227 public static IStatus executeMoniteredExport(final String label,
228 final UUID uuid,
229 final int pollInterval,
230 final boolean cancelable,
231 final IPostMoniteredOperationEnabled postOp,
232 final IFeedbackGenerator feedbackGenerator,
233 String urlString,
234 boolean createZip) {
235
236 try {
237 // get the remoting monitor the first time to make sure that the
238 // operation is valid
239 final IProgressMonitorService progressMonitorService = CdmApplicationState.getCurrentAppConfig().getProgressMonitorService();
240 // final IRemotingProgressMonitor firstRemotingMonitor = progressMonitorService.getRemotingMonitor(uuid);
241 // if(firstRemotingMonitor == null) {
242 // throw new IllegalStateException("Remoting progress monitor is null");
243 // }
244
245 Job job = new Job(label) {
246
247
248 @Override
249 public IStatus run(IProgressMonitor monitor) {
250 // run the monitor until the operation is finished
251 monitor.beginTask("Start", 100);
252 IRemotingProgressMonitor remotingMonitor;
253 try {
254 remotingMonitor = CdmStore.getProgressMonitorClientManager().pollMonitor(label,
255 uuid,
256 pollInterval,
257 postOp,
258 feedbackGenerator,
259 monitor);
260 } catch (Exception ex) {
261 return new Status(Status.ERROR, TaxeditorStorePlugin.PLUGIN_ID, "Operation Interrupted", ex);
262 }
263 final StringBuilder reportSb = new StringBuilder();
264 if (remotingMonitor.getResult() instanceof ExportResult){
265 ExportResult result = (ExportResult)remotingMonitor.getResult();
266
267 reportSb.append(result.createReport());
268
269 if(!StringUtils.isBlank(reportSb.toString())) {
270 Display.getDefault().asyncExec(new Runnable() {
271 @Override
272 public void run() {
273 // display reports with possibility to save
274 ReportTextDialog dialog = new ReportTextDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
275 dialog.setTitle(label + " Report");
276 dialog.setReportText(reportSb.toString());
277 dialog.open();
278 }
279 });
280 }
281
282 if (urlString != null){
283 ExportDataWrapper data = result.getExportData();
284 try{
285 if (result.getExportData().getType().equals(ExportResultType.BYTE_ARRAY)){
286 byte[] exportData = (byte[])data.getExportData();
287 if(exportData != null){
288 File file = new File(urlString);
289 FileOutputStream stream = new FileOutputStream(file);
290 Writer out = new BufferedWriter(new OutputStreamWriter(
291 stream, "UTF8"));
292
293 stream.write(exportData);
294 out.flush();
295 stream.close();
296 }
297 } else if (result.getExportData().getType().equals(ExportResultType.MAP_BYTE_ARRAY)){
298 Map<String, byte[]> resultMap = (Map<String, byte[]>)data.getExportData();
299 Set<String> keySet = resultMap.keySet();
300 SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_NOW);
301 Calendar cal = Calendar.getInstance();
302 String fileEnding = ".csv";
303
304 if (createZip){
305 File file = new File(urlString+File.separator + sdf.format(cal.getTime())+ ".zip");
306 FileOutputStream stream = new FileOutputStream(file);
307 ZipOutputStream zos = new ZipOutputStream(stream);
308 for (String key: keySet){
309 byte[] fileData = resultMap.get(key);
310 ZipEntry entry = new ZipEntry( key + fileEnding);
311 zos.putNextEntry(entry);
312 zos.write(fileData);
313 zos.closeEntry();
314 }
315 zos.close();
316 }else{
317 if(result.getExportType().equals(ExportType.DWCA)){
318
319 File file = new File(urlString);
320 FileOutputStream stream = new FileOutputStream(file);
321 ZipOutputStream zos = new ZipOutputStream(stream);
322 for (String key: keySet){
323 byte[] fileData = resultMap.get(key);
324 ZipEntry entry = new ZipEntry( key);
325 zos.putNextEntry(entry);
326 zos.write(fileData);
327 zos.closeEntry();
328 }
329 zos.close();
330 }else{
331 for (String key: keySet){
332 byte[] fileData = resultMap.get(key);
333 File file = new File(urlString+File.separator + key + fileEnding);
334 FileOutputStream stream = new FileOutputStream(file);
335 Writer out = new BufferedWriter(new OutputStreamWriter(
336 stream, "UTF8"));
337 stream.write(fileData);
338 stream.close();
339 }
340 }
341 }
342 }else{
343 logger.error("This kind of result data is not supported yet." + result.getExportData().getType().toString());
344 }
345 } catch(Exception e){
346 logger.error(e.getStackTrace());
347 }
348 }
349 }
350 return Status.OK_STATUS;
351 }
352
353 @Override
354 protected void canceling() {
355 CdmStore.getCurrentApplicationConfiguration().getProgressMonitorService().cancel(uuid);
356 }
357 };
358
359 // configure the job
360 job.setProperty(IProgressConstants.KEEP_PROPERTY, true);
361 job.setUser(true);
362 // schedule job
363 job.schedule();
364
365 } catch (Exception e) {
366 MessagingUtils.errorDialog("Error executing operation",
367 AbstractUtility.class,
368 "An error occurred while executing " + label,
369 TaxeditorStorePlugin.PLUGIN_ID,
370 e,
371 true);
372 }
373
374 return Status.OK_STATUS;
375 }
376
377 public static IOperationHistory getOperationHistory() {
378 return getWorkbench().getOperationSupport().getOperationHistory();
379 }
380
381 public static void setStatusLine(final String message) {
382 Display.getDefault().asyncExec(new Runnable() {
383
384 @Override
385 public void run() {
386 statusLineManager.setMessage(message);
387 }
388
389 });
390
391 }
392
393 public static IProgressMonitor getMonitor() {
394 statusLineManager.setCancelEnabled(false);
395 return statusLineManager.getProgressMonitor();
396 }
397
398 /**
399 * Starts either the given {@link IProgressMonitor} if it's not
400 * <code>null</code> or a new {@link NullProgressMonitor}.
401 *
402 * @param progressMonitor
403 * The {@link IProgressMonitor} or <code>null</code> if no
404 * progress should be reported.
405 * @param taskName
406 * The name of the main task.
407 * @param steps
408 * The number of steps this task is subdivided into.
409 * @return The {@link IProgressMonitor}.
410 */
411 public static IProgressMonitor startMainMonitor(
412 IProgressMonitor progressMonitor, String taskName, int steps) {
413 IProgressMonitor newMonitor = progressMonitor;
414 if (newMonitor == null) {
415 newMonitor = new NullProgressMonitor();
416 }
417 newMonitor.beginTask(taskName == null ? "" : taskName, steps);
418 newMonitor.subTask(" ");
419 return newMonitor;
420 }
421
422 /**
423 * Creates a {@link SubProgressMonitor} if the given
424 * {@link IProgressMonitor} is not <code>null</code> and not a
425 * {@link NullProgressMonitor}.
426 *
427 * @param progressMonitor
428 * The parent {@link IProgressMonitor} of the
429 * {@link SubProgressMonitor} to be created.
430 * @param ticks
431 * The number of steps this subtask is subdivided into. Must be a
432 * positive number and must not be
433 * {@link IProgressMonitor#UNKNOWN}.
434 * @return The {@link IProgressMonitor}.
435 */
436 public static IProgressMonitor getSubProgressMonitor(
437 IProgressMonitor progressMonitor, int ticks) {
438 if (progressMonitor == null) {
439 return new NullProgressMonitor();
440 }
441 if (progressMonitor instanceof NullProgressMonitor) {
442 return progressMonitor;
443 }
444
445 return new SubProgressMonitor(progressMonitor, ticks);
446 }
447
448 /**
449 * Checks whether the user canceled this operation. If not canceled, the
450 * given number of steps are declared as done.
451 *
452 * @param newMonitor
453 * a {@link org.eclipse.core.runtime.IProgressMonitor} object.
454 * @param steps
455 * a int.
456 */
457 public static void workedChecked(IProgressMonitor newMonitor, int steps) {
458 // In case the progress monitor was canceled throw an exception.
459 if (newMonitor.isCanceled()) {
460 throw new OperationCanceledException();
461 }
462 // Otherwise declare this step as done.
463 newMonitor.worked(steps);
464 }
465
466 public static String getPluginId() {
467 return "eu.taxeditor";
468 }
469
470 public static Object getActiveEditor() {
471 MPart activePart = EventUtility.getActivePart();
472 if(activePart!=null && activePart.getObject()!=null
473 && activePart.getObject() instanceof IE4SavablePart){
474 return activePart.getObject();
475 }
476 return null;
477 }
478
479 public static DetailsPartE4 getDetailsView(EPartService partService) {
480 MPart part = partService.findPart("eu.etaxonomy.taxeditor.view.e4.details.DetailsPartE4");
481 if(part!=null){
482 return (DetailsPartE4) part.getObject();
483 }
484 return null;
485 }
486
487 public static void refreshDetailsViewer(EPartService partService) {
488 if (getDetailsView(partService) != null) {
489 ((AbstractCdmDataViewerE4) getDetailsView(partService).getViewer()).refresh();
490 }
491 }
492
493 public static void reflowDetailsViewer(EPartService partService) {
494 if (getDetailsView(partService) != null) {
495 ((AbstractCdmDataViewerE4) getDetailsView(partService).getViewer()).reflow();
496 }
497 }
498
499
500 /**
501 * Orders a Collection of {@link IEnumTerm}s according to the term
502 * hierarchy. <br>
503 * <br>
504 * The returned map will be be ordered primarily by root elements,
505 * secondarily by the child elements and their children resp., both ascending alphabetically. <br>
506 * @param terms
507 * A {@link Collection} of {@link IEnumTerm}s for which the term
508 * hierarchy should be created
509 * @return a map which holds the terms as keys and their string
510 * representation via {@link IEnumTerm#getMessage()} as values
511 */
512 public static <T extends IEnumTerm<T>> LinkedHashMap<T, String> orderTerms(Collection<T> terms) {
513 TreeSet<TermNode<T>> parentElements = new TreeSet<TermNode<T>>();
514 parentElements.addAll(getTermHierarchy(terms));
515
516 // create list according to the type hierarchy (root elements alphabetically with recursive children also alphabetically)
517 LinkedHashMap<T, String> result = new LinkedHashMap<T, String>();
518 parseTermTree(parentElements, result, -1);
519 return result;
520 }
521
522 private static<T extends IEnumTerm<T>> void parseTermTree(Collection<TermNode<T>> children, LinkedHashMap<T, String> result, int depth){
523 depth++;
524 for(TermNode<T> node:children){
525 String indentString = "";
526 for(int i=0;i<depth;i++){
527 indentString += " ";
528 }
529 if(depth>0){
530 indentString += "- ";
531 }
532 result.put(node.term, indentString + node.term.getMessage());
533 parseTermTree(node.children, result, depth);
534 }
535 }
536
537 private static<T extends IEnumTerm<T>> void addToParents(List<TermNode<T>> parents, Collection<T> terms){
538 List<TermNode<T>> hasChildrenList = new ArrayList<TermNode<T>>();
539 for(T term:terms){
540 // only terms with parents
541 if(term.getKindOf()!=null){
542 TermNode<T> parentNode = new TermNode<T>(term.getKindOf());
543 TermNode<T> childNode = new TermNode<T>(term);
544 if(parents.contains(parentNode)){
545 // parent found in parent list -> add this term to parent's child list
546 parents.get(parents.indexOf(parentNode)).addChild(childNode);
547 if(!term.getGeneralizationOf().isEmpty()){
548 // has more children -> add to list which will be the parent for the next recursion
549 hasChildrenList.add(childNode);
550 }
551 }
552 }
553 }
554 if(!hasChildrenList.isEmpty()){
555 addToParents(hasChildrenList, terms);
556 }
557 }
558
559 private static<T extends IEnumTerm<T>> List<TermNode<T>> getTermHierarchy(Collection<T> terms){
560 List<TermNode<T>> parents = new ArrayList<TermNode<T>>();
561 // get root elements
562 for(T term:terms){
563 T parentTerm = term.getKindOf();
564 if(parentTerm==null){
565 // root element
566 parents.add(new TermNode<T>(term));
567 }
568 }
569 addToParents(parents, terms);
570 return parents;
571 }
572
573 @SuppressWarnings("unchecked")
574 /**
575 * Recursively iterates over all term parents until no more parent is found i.e. the root node
576 * @param term The term for which the parent should be found
577 * @return the root terms of the term hierarchy
578 */
579 private static<T extends IEnumTerm<T>> T getParentFor(T term){
580 // PP: cast should be safe. Why is Eclipse complaining??
581 T parent = term.getKindOf();
582 if(parent==null){
583 return term;
584 }
585 else{
586 return getParentFor(term.getKindOf());
587 }
588 }
589
590 private static class TermNode<T extends IEnumTerm<T>> implements Comparable<TermNode<T>>{
591 private final T term;
592 private final TreeSet<TermNode<T>> children;
593
594 public TermNode(T term) {
595 super();
596 this.term = term;
597 this.children = new TreeSet<TermNode<T>>();
598 }
599
600 public void addChild(TermNode<T> child){
601 this.children.add(child);
602 }
603
604 public TreeSet<TermNode<T>> getChildren() {
605 return children;
606 }
607
608 public T getTerm() {
609 return term;
610 }
611
612 @Override
613 public int hashCode() {
614 final int prime = 31;
615 int result = 1;
616 result = prime * result + ((term == null) ? 0 : term.hashCode());
617 return result;
618 }
619
620 @Override
621 public boolean equals(Object obj) {
622 if (this == obj) {
623 return true;
624 }
625 if (obj == null) {
626 return false;
627 }
628 if (getClass() != obj.getClass()) {
629 return false;
630 }
631 TermNode other = (TermNode) obj;
632 if (term == null) {
633 if (other.term != null) {
634 return false;
635 }
636 } else if (!term.equals(other.term)) {
637 return false;
638 }
639 return true;
640 }
641
642 @Override
643 public int compareTo(TermNode<T> that) {
644 return this.term.getMessage().compareTo(that.term.getMessage());
645 }
646 }
647
648 public static Object getElementsFromSelectionChangedEvent(SelectionChangedEvent event) {
649 IStructuredSelection selection = (IStructuredSelection) event.getSelection();
650 Object selectionToSet = selection;
651 if(selection.size() == 1){
652 selectionToSet = selection.getFirstElement();
653 }
654 else if(!selection.isEmpty()){
655 selectionToSet = selection.toArray();
656 }
657 return selectionToSet;
658 }
659
660 /**
661 * Executes a remoting monitored import
662 *
663 * @param label for the import
664 * @param uuid of the remoting monitor already started on the server
665 * @param pollInterval in milliseconds
666 * @param cancelable flag which determines whether the operation can be cancelled
667 * @param postOp callback for running post operation logic
668 * @return
669 */
670 public static IStatus executeMoniteredOperation(final String label,
671 final UUID uuid,
672 final int pollInterval,
673 final boolean cancelable,
674 final IPostMoniteredOperationEnabled postOp,
675 final IFeedbackGenerator feedbackGenerator) {
676
677 try{
678 // get the remoting monitor the first time to make sure that the
679 // operation is valid
680 final IProgressMonitorService progressMonitorService = CdmApplicationState.getCurrentAppConfig().getProgressMonitorService();
681 final IRemotingProgressMonitor firstRemotingMonitor = progressMonitorService.getRemotingMonitor(uuid);
682 if(firstRemotingMonitor == null) {
683 throw new IllegalStateException("Remoting progress monitor is null");
684 }
685
686 Job job = new Job(label) {
687
688
689 @Override
690 public IStatus run(IProgressMonitor monitor) {
691 // run the monitor until the operation is finished
692 monitor.beginTask("Start", 100);
693 IRemotingProgressMonitor remotingMonitor;
694 try {
695 remotingMonitor = CdmStore.getProgressMonitorClientManager().pollMonitor(label,
696 uuid,
697 pollInterval,
698 postOp,
699 feedbackGenerator,
700 monitor);
701 } catch (Exception ex) {
702 return new Status(Status.ERROR, TaxeditorStorePlugin.PLUGIN_ID, "Operation Interrupted", ex);
703 }
704 final StringBuilder reportSb = new StringBuilder();
705 // collect reports
706 // for(String report : remotingMonitor.getResult()) {
707 if (remotingMonitor.getResult() instanceof ExportResult) {
708 reportSb.append(((ExportResult)remotingMonitor.getResult()).createReport());
709 }else if (remotingMonitor.getResult() instanceof UpdateResult){
710 if (((UpdateResult)remotingMonitor.getResult()).isOk()){
711 reportSb.append("Update successfull. \n"+"Updated Objects: " + ((UpdateResult)remotingMonitor.getResult()).getUpdatedObjects().size());
712 }
713 if (!((UpdateResult)remotingMonitor.getResult()).getExceptions().isEmpty()){
714 reportSb.append(((UpdateResult)remotingMonitor.getResult()).getExceptions().toString());
715 }
716 }
717 // }
718 if(!StringUtils.isBlank(reportSb.toString()) && reportSb.length() != 0) {
719 Display.getDefault().asyncExec(new Runnable() {
720 @Override
721 public void run() {
722 // display reports with possibility to save
723 ReportTextDialog dialog = new ReportTextDialog(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell());
724 dialog.setTitle(label + " Report");
725 dialog.setReportText(reportSb.toString());
726 dialog.open();
727 }
728 });
729 }
730 return Status.OK_STATUS;
731 }
732
733 @Override
734 protected void canceling() {
735 CdmStore.getCurrentApplicationConfiguration().getProgressMonitorService().cancel(uuid);
736 }
737 };
738
739 // configure the job
740 job.setProperty(IProgressConstants.KEEP_PROPERTY, true);
741 job.setUser(true);
742 // schedule job
743 job.schedule();
744
745 } catch (Exception e) {
746 MessagingUtils.errorDialog("Error executing operation",
747 AbstractUtility.class,
748 "An error occurred while executing " + label,
749 TaxeditorStorePlugin.PLUGIN_ID,
750 e,
751 true);
752 }
753
754 return Status.OK_STATUS;
755 }
756
757 }