3579bdbecd09a92c79abb33de7c3dfe44b6991b7
[taxeditor.git] / eu.etaxonomy.taxeditor.store / src / main / java / eu / etaxonomy / taxeditor / util / ProgressMonitorClientManager.java
1 /**
2 * Copyright (C) 2015 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9 package eu.etaxonomy.taxeditor.util;
10
11 import java.text.DecimalFormat;
12 import java.util.Arrays;
13 import java.util.List;
14 import java.util.UUID;
15
16 import org.apache.log4j.Logger;
17 import org.eclipse.core.runtime.SubMonitor;
18 import org.springframework.remoting.RemoteAccessException;
19
20 import eu.etaxonomy.cdm.api.application.CdmApplicationState;
21 import eu.etaxonomy.cdm.api.service.IProgressMonitorService;
22 import eu.etaxonomy.cdm.api.service.UpdateResult;
23 import eu.etaxonomy.cdm.common.monitor.IRemotingProgressMonitor;
24 import eu.etaxonomy.taxeditor.operation.IFeedbackGenerator;
25 import eu.etaxonomy.taxeditor.operation.IPostMoniteredOperationEnabled;
26
27 /**
28 * Manages client side progress monitors
29 *
30 * @author cmathew
31 * @date 23 Oct 2015
32 */
33 public class ProgressMonitorClientManager {
34 private static final Logger logger = Logger.getLogger(ProgressMonitorClientManager.class);
35
36 /**
37 * Polls the progress monitor service for the progress status of a monitor
38 * corresponding to the given uuid.
39 *
40 * @param label for the operation
41 * @param uuid of the remoting monitor already started on the server
42 * @param pollInterval in milliseconds
43 * @param cancelable flag which determines whether the operation can be cancelled
44 * @param postOp callback for running post operation logic
45 * @param feedbackGenerator feedback generator corresponding to the
46 * 'wait on feedback' request made on the remoting monitor
47 * @param monitor to be updated
48 * @return a final progress monitor after the operation is completed
49 * @throws InterruptedException
50 */
51 public IRemotingProgressMonitor pollMonitor(final String label,
52 final UUID uuid,
53 final int pollInterval,
54 final IPostMoniteredOperationEnabled postOp,
55 IFeedbackGenerator feedbackGenerator,
56 SubMonitor monitor) throws InterruptedException {
57 return pollMonitor(label, uuid, pollInterval, postOp, Arrays.asList(feedbackGenerator), monitor);
58 }
59
60 /**
61 * Polls the progress monitor service for the progress status of a monitor
62 * corresponding to the given uuid.
63 *
64 *
65 * @param label for the operation
66 * @param uuid of the remoting monitor already started on the server
67 * @param pollInterval in milliseconds
68 * @param cancelable flag which determines whether the operation can be cancelled
69 * @param postOp callback for running post operation logic
70 * @param feedbackGenerators list of feedback generators corresponding to the
71 * size and exact order of the 'wait on feedback' requests made on the
72 * remoting monitor
73 * @param monitor to be updated
74 * @return a final progress monitor after the operation is completed
75 * @throws InterruptedException
76 */
77 public IRemotingProgressMonitor pollMonitor(final String label,
78 final UUID uuid,
79 final int pollInterval,
80 final IPostMoniteredOperationEnabled postOp,
81 List<IFeedbackGenerator> feedbackGenerators,
82 SubMonitor monitor) throws InterruptedException {
83
84 IProgressMonitorService progressMonitorService = CdmApplicationState.getCurrentAppConfig().getProgressMonitorService();
85 IRemotingProgressMonitor remotingMonitor = progressMonitorService.getRemotingMonitor(uuid);
86 try {
87 final int START_DELAY=10;
88 // wait about 10 seconds for the remoting monitor to be initialised
89 // (i.e. for the begin task method to be called ON THE REMOTING MONITOR)
90 if (remotingMonitor != null && remotingMonitor.isDone()){
91 return remotingMonitor;
92 }
93 for(int i=0;remotingMonitor==null && i<START_DELAY;i++) {
94 Thread.sleep(500);
95 logger.info("Waiting for monitored work to start ..");
96 remotingMonitor = progressMonitorService.getRemotingMonitor(uuid);
97 }
98 if (remotingMonitor == null){
99 return null;
100 }
101
102 // if the total work is still not been set then we assume that the
103 // operation has zero work units
104 if(remotingMonitor.getTotalWork() == 0 && remotingMonitor.isDone()) {
105 return remotingMonitor;
106 }else if (remotingMonitor.getTotalWork() == 0 ){
107 Object result = remotingMonitor.getResult();
108 InterruptedException exception = new InterruptedException("Monitor has zero work units");
109 if (result instanceof UpdateResult){
110 ((UpdateResult)result).addException(exception);
111 }else if (result == null){
112 result = new UpdateResult();
113 }
114 }
115
116 // start the client monitor
117 logger.info("Work to be done: " + remotingMonitor.getTotalWork());
118 int editorTotalWorkDone = 0;
119 int serverTotalWorkDone = 0;
120 // loop until the operation is done
121 int feedbackCount = 0;
122 int failCount = 10;
123 while(!(remotingMonitor.isCanceled() || remotingMonitor.isFailed() || remotingMonitor.isDone())) {
124 // wait for pollInterval, then
125 // .... retrieve remoting monitor, then
126 // .... set client monitor info
127
128 IRemotingProgressMonitor previousRemotingMonitor = remotingMonitor;
129 Thread.sleep(pollInterval);
130 try{
131 remotingMonitor = progressMonitorService.getRemotingMonitor(uuid);
132 }catch(RemoteAccessException e){
133 failCount--;
134 if (failCount > 0){
135 remotingMonitor = previousRemotingMonitor;
136 continue;
137 }else{
138 throw e;
139 }
140 }
141
142 // check if remoting monitor is waiting for feedback
143 if(remotingMonitor.getIsWaitingForFeedback()) {
144 if(feedbackGenerators != null) {
145 // if we have run out of feedback generators while
146 // the remoting monitor is waiting on feedback
147 // then throw exception
148 if(feedbackCount + 1 > feedbackGenerators.size()) {
149 IllegalStateException exception = new IllegalStateException("Remoting monitor waiting on feedback that does not exist");
150 Object result = remotingMonitor.getResult();
151 if (result instanceof UpdateResult){
152 ((UpdateResult)result).addException(exception);
153 }
154 return remotingMonitor;
155 }
156 feedbackGenerators.get(feedbackCount).setFeedbackForMonitor(uuid);
157 feedbackCount++;
158 }
159 }
160
161 serverTotalWorkDone = (int) remotingMonitor.getWorkDone();
162 logger.info("Work done from start: " + serverTotalWorkDone);
163
164 if (serverTotalWorkDone > editorTotalWorkDone){
165 int worked = serverTotalWorkDone - editorTotalWorkDone;
166 if(worked > 0) {
167 logger.info("Work done since last check: " + worked);
168 monitor.worked(worked);
169 }
170 }
171
172 // set dialog text
173 String subTaskName = remotingMonitor.getSubTask();
174 String percentage = "0";
175 if (remotingMonitor.getTotalWork() != 0){
176 percentage = new DecimalFormat("#.##").format(remotingMonitor.getPercentage());
177 }
178 subTaskName = subTaskName + " (" + percentage +"% done)";
179 //Note: do not update taskname as it resets percentage in status line
180 monitor.subTask(subTaskName );
181
182 editorTotalWorkDone = serverTotalWorkDone;
183 }
184 if(remotingMonitor.getResult() instanceof Exception) {
185 UpdateResult result = new UpdateResult();
186 result.addException((Exception) remotingMonitor.getResult());
187 }
188 return remotingMonitor;
189 } finally {
190 if(postOp != null && remotingMonitor != null && remotingMonitor.isDone()) {
191 postOp.postOperation(remotingMonitor);
192 }
193 }
194 }
195 }