1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.itracker.services.util;
20
21 import java.lang.reflect.Field;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.HashMap;
25 import java.util.LinkedList;
26 import java.util.List;
27 import java.util.Locale;
28 import java.util.Map;
29
30 import org.apache.log4j.Logger;
31 import org.apache.struts.action.ActionErrors;
32 import org.apache.struts.action.ActionMessage;
33 import org.apache.struts.action.ActionMessages;
34 import org.apache.struts.validator.ValidatorForm;
35 import org.itracker.core.resources.ITrackerResources;
36 import org.itracker.model.NameValuePair;
37 import org.itracker.model.ProjectScript;
38 import org.itracker.services.exceptions.WorkflowException;
39
40 import bsh.Interpreter;
41
42
43
44
45 public class WorkflowUtilities {
46
47
48 public static final int EVENT_FIELD_ONPOPULATE = 1;
49
50 public static final int EVENT_FIELD_ONSORT = 2;
51
52 public static final int EVENT_FIELD_ONSETDEFAULT = 3;
53
54 public static final int EVENT_FIELD_ONVALIDATE = 4;
55
56 public static final int EVENT_FIELD_ONPRESUBMIT = 5;
57
58 public static final int EVENT_FIELD_ONPOSTSUBMIT = 6;
59
60 private static final Logger logger = Logger.getLogger(WorkflowUtilities.class);
61
62 public WorkflowUtilities() {
63 }
64
65
66
67
68
69
70
71 public static String getEventName(int value, Locale locale) {
72 final String eventName = getEventName(Integer.toString(value), locale);
73
74 return eventName;
75 }
76
77 public static String getEventName(String value, Locale locale) {
78 return ITrackerResources.getString(ITrackerResources.KEY_BASE_WORKFLOW_EVENT + value, locale);
79 }
80
81
82
83
84
85
86
87 public static NameValuePair[] getEvents(Locale locale) {
88 NameValuePair[] eventNames = new NameValuePair[6];
89 eventNames[0] = new NameValuePair(getEventName(EVENT_FIELD_ONPOPULATE, locale), Integer.toString(EVENT_FIELD_ONPOPULATE));
90 eventNames[1] = new NameValuePair(getEventName(EVENT_FIELD_ONSORT, locale), Integer.toString(EVENT_FIELD_ONSORT));
91 eventNames[2] = new NameValuePair(getEventName(EVENT_FIELD_ONSETDEFAULT, locale), Integer.toString(EVENT_FIELD_ONSETDEFAULT));
92 eventNames[3] = new NameValuePair(getEventName(EVENT_FIELD_ONVALIDATE, locale), Integer.toString(EVENT_FIELD_ONVALIDATE));
93 eventNames[4] = new NameValuePair(getEventName(EVENT_FIELD_ONPRESUBMIT, locale), Integer.toString(EVENT_FIELD_ONPRESUBMIT));
94 eventNames[5] = new NameValuePair(getEventName(EVENT_FIELD_ONPOSTSUBMIT, locale), Integer.toString(EVENT_FIELD_ONPOSTSUBMIT));
95 return eventNames;
96 }
97
98
99
100
101
102
103
104
105
106 public static List<NameValuePair> getListOptions(Map<Integer, List<NameValuePair>> listOptions, int fieldId) {
107 return getListOptions(listOptions, Integer.valueOf(fieldId));
108 }
109
110
111
112
113
114
115
116
117
118 @SuppressWarnings("unchecked")
119 public static List<NameValuePair> getListOptions(Map listOptions, Integer fieldId) {
120 List<NameValuePair> options = new ArrayList<NameValuePair>();
121
122 if(listOptions != null && listOptions.size() != 0 && fieldId != null) {
123 Object mapOptions = listOptions.get(fieldId);
124 if(mapOptions != null) {
125 options = (List<NameValuePair>) mapOptions;
126 }
127 }
128
129 return options;
130 }
131
132
133
134
135
136
137
138
139
140
141
142
143
144 public static void processFieldScripts(List<ProjectScript> projectScriptModels, int event, Map<Integer, List<NameValuePair>> currentValues, ActionMessages currentErrors, ValidatorForm form) throws WorkflowException {
145 if(projectScriptModels == null || projectScriptModels.size() == 0) {
146 return;
147 }
148 logger.debug("Processing " + projectScriptModels.size() + " field scripts for project " + projectScriptModels.get(0).getProject().getId());
149
150 List<ProjectScript> scriptsToRun = new ArrayList<ProjectScript>();
151 for(int i = 0; i < projectScriptModels.size(); i++) {
152 if(projectScriptModels.get(i).getScript().getEvent() == event) {
153 int insertIndex = 0;
154 for(insertIndex = 0; insertIndex < scriptsToRun.size(); insertIndex++) {
155 if(projectScriptModels.get(i).getPriority() < ((ProjectScript) scriptsToRun.get(insertIndex)).getPriority()) {
156 break;
157 }
158 }
159 scriptsToRun.add(insertIndex,projectScriptModels.get(i));
160 }
161 }
162 logger.debug(scriptsToRun.size() + " eligible scripts found for event " + event);
163
164 if (currentValues == null) {
165 currentValues = new HashMap<Integer, List<NameValuePair>>();
166 }
167
168 for (int i = 0; i < scriptsToRun.size(); i++) {
169 ProjectScript currentScript = (ProjectScript) scriptsToRun.get(i);
170 try {
171 logger.debug("Running script " + currentScript.getScript().getId() + " with priority " + currentScript.getPriority());
172 List<NameValuePair> currentValue = currentValues.get(currentScript.getFieldId());
173
174 logger.debug("Before script current value for field " + IssueUtilities.getFieldName(currentScript.getFieldId()) + " (" + currentScript.getFieldId() + ") is " + (currentValue == null ? "NULL" : "'" + currentValue.toString() + "' (" + currentValue.getClass().getName() + "'"));
175 currentValue = processFieldScript(currentScript, event, currentScript.getFieldId(), currentValue, currentErrors, form);
176 logger.debug("After script current value for field " + IssueUtilities.getFieldName(currentScript.getFieldId()) + " (" + currentScript.getFieldId() + ") is " + (currentValue == null ? "NULL" : "'" + currentValue.toString() + "' (" + currentValue.getClass().getName() + "'"));
177
178 currentValues.put(currentScript.getFieldId(), currentValue);
179 } catch(WorkflowException we) {
180 logger.error("Error processing script " + currentScript.getScript().getId() + ": " + we.getMessage());
181 }
182 }
183 }
184
185
186
187
188
189
190
191
192
193
194
195
196
197 public static List<NameValuePair> processFieldScripts(List<ProjectScript> projectScripts, int event, Integer fieldId, List<NameValuePair> currentValue, ActionErrors currentErrors, ValidatorForm form) throws WorkflowException {
198 if(projectScripts == null || projectScripts.size() == 0 || fieldId == null) {
199 return null;
200 }
201 logger.debug("Processing " + projectScripts.size() + " field scripts for project " + projectScripts.get(0).getProject().getId());
202
203 List<ProjectScript> scriptsToRun = new LinkedList<ProjectScript>();
204 for(int i = 0; i < projectScripts.size(); i++) {
205 if(projectScripts.get(i).getScript().getEvent() == event && fieldId.equals(projectScripts.get(i).getFieldId())) {
206 int insertIndex = 0;
207 for(insertIndex = 0; insertIndex < scriptsToRun.size(); insertIndex++) {
208 if(projectScripts.get(i).getPriority() < ((ProjectScript) scriptsToRun.get(insertIndex)).getPriority()) {
209 break;
210 }
211 }
212 scriptsToRun.add(insertIndex,projectScripts.get(i));
213 }
214 }
215 logger.debug(scriptsToRun.size() + " eligible scripts found for event " + event + " on field " + fieldId);
216
217 for(int i = 0; i < scriptsToRun.size(); i++) {
218 ProjectScript currentScript = (ProjectScript) scriptsToRun.get(i);
219 try {
220 logger.debug("Running script " + currentScript.getScript().getId() + " with priority " + currentScript.getPriority());
221 currentValue = processFieldScript(currentScript, event, fieldId, currentValue, currentErrors, form);
222 } catch(WorkflowException we) {
223 logger.error("Error processing script " + currentScript.getScript().getId() + ": " + we.getMessage());
224 }
225 }
226
227 return currentValue;
228 }
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246 public static List<NameValuePair> processFieldScript(ProjectScript projectScript, int event, Integer fieldId, List<NameValuePair> currentValues, ActionMessages currentErrors, ValidatorForm form) throws WorkflowException {
247 if (projectScript == null) {
248 throw new WorkflowException("ProjectScript was null.", WorkflowException.INVALID_ARGS);
249 }
250 if (currentErrors == null) {
251 throw new WorkflowException("Errors was null.", WorkflowException.INVALID_ARGS);
252 }
253
254 try {
255 Interpreter bshInterpreter = new Interpreter();
256 bshInterpreter.set("event", event);
257 bshInterpreter.set("fieldId", fieldId);
258
259 bshInterpreter.set("currentValue", currentValues);
260 bshInterpreter.set("currentValues", currentValues);
261 bshInterpreter.set("currentErrors", currentErrors);
262 bshInterpreter.set("currentForm", form);
263 bshInterpreter.eval(projectScript.getScript().getScript());
264
265
266 if (logger.isDebugEnabled()) {
267 logger.debug("processFieldScript: Script returned current value of '" + currentValues + "' (" + (currentValues != null ? currentValues.getClass().getName() : "NULL") + ")");
268 }
269 if (event == EVENT_FIELD_ONSETDEFAULT && form != null && currentValues != null) {
270 if (logger.isDebugEnabled()) {
271 logger.debug("processFieldScript: Setting current form field value for field " + IssueUtilities.getFieldName(projectScript.getFieldId()) + " to '" + currentValues + "'");
272 }
273 setFormProperty(form, projectScript.getFieldId(), currentValues);
274 }
275 } catch(Exception e) {
276 logger.error("processFieldScript: Error processing field script.", e);
277
278 currentErrors.add(ActionMessages.GLOBAL_MESSAGE,
279 new ActionMessage("itracker.web.error.system.message",
280 new Object[]{ITrackerResources.getString("itracker.web.attr.script"),
281 e.getMessage()
282 }));
283 }
284 if (logger.isDebugEnabled()) {
285 logger.debug("processFieldScript: returning " + currentValues + ", errors: " + currentErrors);
286 }
287 return currentValues;
288 }
289
290 @SuppressWarnings("unchecked")
291 private static void setFormProperty(ValidatorForm form, Integer fieldId, Object currentValue) {
292 String fieldName = IssueUtilities.getFieldName(fieldId);
293 int fieldType = IssueUtilities.getFieldType(fieldId);
294 if(fieldType == IssueUtilities.FIELD_TYPE_SINGLE) {
295 try {
296 Field formField = form.getClass().getField( fieldName );
297 if ( formField != null ) {
298 formField.set( form , currentValue );
299 } else {
300 throw new IllegalArgumentException( "no field with name "
301 + fieldName + " found in form " + form );
302 }
303 } catch ( NoSuchFieldException e ) {
304 e.printStackTrace();
305 } catch ( IllegalAccessException e ) {
306 e.printStackTrace();
307 }
308 } else if(fieldType == IssueUtilities.FIELD_TYPE_INDEXED) {
309 try {
310 Object indexedField = null;
311 Field formField = form.getClass().getField(fieldName);
312 indexedField = formField.get( form );
313 if ( indexedField instanceof List ) {
314 ((List)indexedField).set( 0 , currentValue );
315 } else if ( indexedField instanceof Collection ) {
316 ((Collection)indexedField).add( currentValue );
317 } else {
318 throw new IllegalArgumentException( "field with name "
319 + fieldName + " found in form " + form + " is of unknown type" );
320 }
321 } catch ( NoSuchFieldException e ) {
322 e.printStackTrace();
323 } catch ( IllegalAccessException e ) {
324 e.printStackTrace();
325 }
326 } else if(fieldType == IssueUtilities.FIELD_TYPE_MAP) {
327 try {
328 Object indexedField = null;
329 Field formField = form.getClass().getField( fieldName );
330 indexedField = formField.get( form );
331 if ( indexedField instanceof Map ) {
332 ((Map)indexedField).put( fieldId.toString(), currentValue );
333 } else {
334 throw new IllegalArgumentException( "field with name "
335 + fieldName + " found in form " + form + " is of unknown type" );
336 }
337 } catch ( NoSuchFieldException e ) {
338 e.printStackTrace();
339 } catch ( IllegalAccessException e ) {
340 e.printStackTrace();
341 }
342 }
343 }
344
345 }