View Javadoc
1   /**
2    * Copyright 2005-2015 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.kew.documentoperation.web;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.apache.struts.action.ActionForm;
20  import org.apache.struts.action.ActionForward;
21  import org.apache.struts.action.ActionMapping;
22  import org.apache.struts.action.ActionMessage;
23  import org.apache.struts.action.ActionMessages;
24  import org.kuali.rice.core.api.util.RiceConstants;
25  import org.kuali.rice.core.api.util.RiceKeyConstants;
26  import org.kuali.rice.kew.actionitem.ActionItem;
27  import org.kuali.rice.kew.actionlist.service.ActionListService;
28  import org.kuali.rice.kew.actionrequest.ActionRequestValue;
29  import org.kuali.rice.kew.actionrequest.service.ActionRequestService;
30  import org.kuali.rice.kew.actiontaken.ActionTakenValue;
31  import org.kuali.rice.kew.actiontaken.service.ActionTakenService;
32  import org.kuali.rice.kew.api.KewApiConstants;
33  import org.kuali.rice.kew.api.KewApiServiceLocator;
34  import org.kuali.rice.kew.api.WorkflowDocument;
35  import org.kuali.rice.kew.api.WorkflowDocumentFactory;
36  import org.kuali.rice.kew.api.WorkflowRuntimeException;
37  import org.kuali.rice.kew.api.action.ActionInvocation;
38  import org.kuali.rice.kew.api.action.ActionInvocationQueue;
39  import org.kuali.rice.kew.api.action.ActionType;
40  import org.kuali.rice.kew.api.document.DocumentOrchestrationQueue;
41  import org.kuali.rice.kew.api.document.DocumentProcessingOptions;
42  import org.kuali.rice.kew.api.document.DocumentProcessingQueue;
43  import org.kuali.rice.kew.api.document.DocumentRefreshQueue;
44  import org.kuali.rice.kew.api.document.OrchestrationConfig;
45  import org.kuali.rice.kew.api.document.attribute.DocumentAttributeIndexingQueue;
46  import org.kuali.rice.kew.doctype.service.DocumentTypeService;
47  import org.kuali.rice.kew.engine.node.Branch;
48  import org.kuali.rice.kew.engine.node.BranchState;
49  import org.kuali.rice.kew.engine.node.NodeState;
50  import org.kuali.rice.kew.engine.node.RouteNodeInstance;
51  import org.kuali.rice.kew.engine.node.service.BranchService;
52  import org.kuali.rice.kew.engine.node.service.RouteNodeService;
53  import org.kuali.rice.kew.exception.WorkflowServiceErrorException;
54  import org.kuali.rice.kew.exception.WorkflowServiceErrorImpl;
55  import org.kuali.rice.kew.notes.Note;
56  import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
57  import org.kuali.rice.kew.routeheader.service.RouteHeaderService;
58  import org.kuali.rice.kew.service.KEWServiceLocator;
59  import org.kuali.rice.kew.web.KewKualiAction;
60  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
61  import org.kuali.rice.krad.util.GlobalVariables;
62  
63  import javax.servlet.ServletException;
64  import javax.servlet.http.HttpServletRequest;
65  import javax.servlet.http.HttpServletResponse;
66  import java.io.IOException;
67  import java.sql.Timestamp;
68  import java.text.ParseException;
69  import java.util.ArrayList;
70  import java.util.HashMap;
71  import java.util.HashSet;
72  import java.util.Iterator;
73  import java.util.List;
74  import java.util.Map;
75  import java.util.Set;
76  import java.util.StringTokenizer;
77  
78  
79  /**
80   * Struts Action for doing editing of workflow documents.
81   *
82   * @author Kuali Rice Team (rice.collab@kuali.org)
83   */
84  public class DocumentOperationAction extends KewKualiAction {
85  	private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DocumentOperationAction.class);
86  	private static final String DEFAULT_LOG_MSG = "Admin change via document operation";
87  
88  	public ActionForward start(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
89  		return mapping.findForward("basic");
90  	}
91  
92  	public ActionForward getDocument(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
93  		DocumentOperationForm docForm = (DocumentOperationForm) form;
94  		String docId = null;
95  		
96  		// check if we have a plausible docId first
97  		if (StringUtils.isEmpty(docForm.getDocumentId())) {
98  			GlobalVariables.getMessageMap().putError("documentId", RiceKeyConstants.ERROR_REQUIRED, "Document ID");
99  		} else {
100 			try {
101 				docId = docForm.getDocumentId().trim();
102 			} catch (NumberFormatException nfe) {
103 				GlobalVariables.getMessageMap().putError("documentId", RiceKeyConstants.ERROR_NUMERIC, "Document ID");
104 			}
105 		}
106 
107 		if (docId != null) {
108 			//to clear Document Field first;
109 			docForm.resetOps();
110 			DocumentRouteHeaderValue routeHeader = getRouteHeaderService().getRouteHeader(docId);
111 			List routeNodeInstances=getRouteNodeService().findRouteNodeInstances(docId);
112 			Map branches1=new HashMap();
113 			List branches=new ArrayList();
114 
115 			if (routeHeader == null) {
116 				GlobalVariables.getMessageMap().putError("documentId", RiceKeyConstants.ERROR_EXISTENCE, "document");
117 			} else {
118 				materializeDocument(routeHeader);
119 				docForm.setRouteHeader(routeHeader);
120 				setRouteHeaderTimestampsToString(docForm);
121 				docForm.setRouteHeaderOp(KewApiConstants.NOOP);
122 				docForm.setDocumentId(docForm.getDocumentId().trim());
123 				String initials="";
124 				for(Iterator lInitials=routeHeader.getInitialRouteNodeInstances().iterator();lInitials.hasNext();){
125 					String initial=((RouteNodeInstance)lInitials.next()).getRouteNodeInstanceId();
126 					LOG.debug(initial);
127 					initials=initials+initial+", ";
128 				}
129 				if(initials.trim().length()>1){
130 					initials=initials.substring(0,initials.lastIndexOf(","));
131 				}
132 				docForm.setInitialNodeInstances(initials);
133 				request.getSession().setAttribute("routeNodeInstances",routeNodeInstances);
134 				docForm.setRouteNodeInstances(routeNodeInstances);
135 				if(routeNodeInstances!=null){
136 					Iterator routeNodeInstanceIter=routeNodeInstances.iterator();
137 					while(routeNodeInstanceIter.hasNext()){
138 						RouteNodeInstance routeNodeInstance=(RouteNodeInstance) routeNodeInstanceIter.next();
139 						Branch branch=routeNodeInstance.getBranch();
140 						if (! branches1.containsKey(branch.getName())){
141 							branches1.put(branch.getName(),branch);
142 							branches.add(branch);
143 							LOG.debug(branch.getName()+"; "+branch.getBranchState());
144 						}
145 					}
146 					if(branches.size()<1){
147 						branches=null;
148 					}
149 				}
150 				branches1.clear();
151 				request.getSession().setAttribute("branches",branches);
152 				docForm.setBranches(branches);
153 			}
154 		}
155 			
156 		return mapping.findForward("basic");
157 	}
158 
159 	/**
160 	 * Sets up various objects on the document which are required for use inside of the Struts and JSP framework.
161 	 *
162 	 * Specifically, if a document has action requests with null RouteNodeInstances, it will create empty node instance
163 	 * objects.
164 	 */
165 	private void materializeDocument(DocumentRouteHeaderValue document) {
166 		for (Iterator iterator = document.getActionRequests().iterator(); iterator.hasNext();) {
167 			ActionRequestValue request = (ActionRequestValue) iterator.next();
168 			if (request.getNodeInstance() == null) {
169 				request.setNodeInstance(new RouteNodeInstance());
170 			}
171 		}
172 	}
173 
174 	public ActionForward clear(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
175 		DocumentOperationForm docForm = (DocumentOperationForm) form;
176 		docForm.setRouteHeader(new DocumentRouteHeaderValue());
177 		docForm.setDocumentId(null);
178 		return mapping.findForward("basic");
179 	}
180 
181 	public ActionMessages establishRequiredState(HttpServletRequest request, ActionForm form) throws Exception {
182 		return null;
183 	}
184 
185 	public ActionForward save(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
186 		DocumentOperationForm docForm = (DocumentOperationForm) form;
187 		boolean change = false;
188 
189 		String routeHeaderOp = docForm.getRouteHeaderOp();
190 		if (!KewApiConstants.UPDATE.equals(routeHeaderOp) && !KewApiConstants.NOOP.equals(routeHeaderOp)) {
191 			throw new WorkflowServiceErrorException("Document operation not defined", new WorkflowServiceErrorImpl("Document operation not defined", "docoperation.operation.invalid"));
192 		}
193 		if (KewApiConstants.UPDATE.equals(routeHeaderOp)) {
194 			setRouteHeaderTimestamps(docForm);
195 			DocumentRouteHeaderValue dHeader = docForm.getRouteHeader();
196             List<Note> docNotes = KEWServiceLocator.getNoteService().getNotesByDocumentId(dHeader.getDocumentId());
197 
198             if (docNotes != null && !docNotes.isEmpty()) {
199                 dHeader.setNotes(docNotes);
200             }
201             String initials=docForm.getInitialNodeInstances();
202 			List<RouteNodeInstance> lInitials = new ArrayList<RouteNodeInstance>();
203 			if (StringUtils.isNotEmpty(initials)){ 
204 				StringTokenizer tokenInitials=new StringTokenizer(initials,",");
205 				while (tokenInitials.hasMoreTokens()) {
206 					String instanceId = tokenInitials.nextToken().trim();
207 					LOG.debug(instanceId);
208 					RouteNodeInstance instance = getRouteNodeService().findRouteNodeInstanceById(instanceId);
209 					lInitials.add(instance);
210 				}
211 			}
212 			dHeader.setInitialRouteNodeInstances(lInitials);
213 			getRouteHeaderService().validateRouteHeader(docForm.getRouteHeader());
214 			DocumentRouteHeaderValue documentRouteHeaderValue = getRouteHeaderService().
215                                         saveRouteHeader(docForm.getRouteHeader());
216             docForm.setRouteHeader(documentRouteHeaderValue);
217 			change = true;
218 		}
219 
220 		for (Iterator actionRequestIter = docForm.getActionRequestOps().iterator(); actionRequestIter.hasNext();) {
221 			DocOperationIndexedParameter actionRequestOp = (DocOperationIndexedParameter) actionRequestIter.next();
222 			int index = actionRequestOp.getIndex().intValue();
223 			String opValue = actionRequestOp.getValue();
224 			ActionRequestValue actionRequest = docForm.getActionRequests().get(index);
225 			String createDateParamName = "actionRequestCreateDate" + index;
226 
227 			if (!KewApiConstants.UPDATE.equals(opValue) && !KewApiConstants.DELETE.equals(opValue) && !KewApiConstants.NOOP.equals(opValue)) {
228 				throw new WorkflowServiceErrorException("Action request operation not defined", new WorkflowServiceErrorImpl("Action request operation not defined", "docoperation.actionrequest.operation.invalid"));
229 			}
230 			if (KewApiConstants.UPDATE.equals(opValue)) {
231 				try {
232 					actionRequest.setCreateDate(new Timestamp(RiceConstants.getDefaultDateFormat().parse(request.getParameter(createDateParamName)).getTime()));
233 					actionRequest.setCreateDateString(RiceConstants.getDefaultDateFormat().format(actionRequest.getCreateDate()));
234 					actionRequest.setDocumentId(docForm.getRouteHeader().getDocumentId());
235 
236                     if (StringUtils.isNotBlank(actionRequest.getParentActionRequestId())) {
237                         actionRequest.setParentActionRequest(getActionRequestService().findByActionRequestId(actionRequest.getParentActionRequestId()));
238                     }
239 
240                     if (StringUtils.isNotBlank(actionRequest.getActionTakenId())) {
241 					    actionRequest.setActionTaken(getActionTakenService().findByActionTakenId(actionRequest.getActionTakenId()));
242                     }
243 
244 					if (actionRequest.getNodeInstance() != null && actionRequest.getNodeInstance().getRouteNodeInstanceId() == null) {
245 						actionRequest.setNodeInstance(null);
246 					} else if (actionRequest.getNodeInstance() != null && actionRequest.getNodeInstance().getRouteNodeInstanceId() != null) {
247 						actionRequest.setNodeInstance(KEWServiceLocator.getRouteNodeService().findRouteNodeInstanceById(actionRequest.getNodeInstance().getRouteNodeInstanceId()));
248 					}
249 					// getActionRequestService().validateActionRequest(actionRequest);
250 					actionRequest = getActionRequestService().saveActionRequest(actionRequest);
251 					change = true;
252 				} catch (ParseException pe) {
253 					throw new WorkflowServiceErrorException("Action request create date parsing error", new WorkflowServiceErrorImpl("Action request create date parsing error", "docoperation.actionrequests.dateparsing.error", actionRequest.getActionRequestId().toString()));
254 				}
255 
256 			}
257 			if (KewApiConstants.DELETE.equals(opValue)) {
258 			    getActionRequestService().deleteActionRequestGraphNoOutbox(actionRequest);
259 			    change = true;
260 			}
261 		}
262 
263 		for (Iterator actionTakenIter = docForm.getActionTakenOps().iterator(); actionTakenIter.hasNext();) {
264 			DocOperationIndexedParameter actionTakenOp = (DocOperationIndexedParameter) actionTakenIter.next();
265 			int index = actionTakenOp.getIndex().intValue();
266 			String opValue = actionTakenOp.getValue();
267 
268 			String actionDateParamName = "actionTakenActionDate" + index;
269             ActionTakenValue actionTaken = docForm.getActionsTaken().get(index);
270 			if (!KewApiConstants.UPDATE.equals(opValue) && !KewApiConstants.DELETE.equals(opValue) && !KewApiConstants.NOOP.equals(opValue)) {
271 				throw new WorkflowServiceErrorException("Action taken operation not defined", new WorkflowServiceErrorImpl("Action taken operation not defined", "docoperation.actiontaken.operation.invalid"));
272 			}
273 			if (KewApiConstants.UPDATE.equals(opValue)) {
274 				try {
275 					actionTaken.setActionDate(new Timestamp(RiceConstants.getDefaultDateFormat().parse(request.getParameter(actionDateParamName)).getTime()));
276 					actionTaken.setActionDateString(RiceConstants.getDefaultDateFormat().format(actionTaken.getActionDate()));
277 					actionTaken = getActionTakenService().saveActionTaken(actionTaken);
278 					change = true;
279 				} catch (ParseException pe) {
280 					throw new WorkflowServiceErrorException("Action taken action date parsing error", new WorkflowServiceErrorImpl("Action taken action date parse error", "docoperation.actionstaken.dateparsing.error", actionTaken.getActionTakenId().toString()));
281 				}
282 			}
283 			if (KewApiConstants.DELETE.equals(opValue)) {
284 				getActionTakenService().delete(actionTaken);
285 				change = true;
286 			}
287 		}
288 
289 		for (Iterator actionItemIter = docForm.getActionItemOps().iterator(); actionItemIter.hasNext();) {
290 			DocOperationIndexedParameter actionItemOp = (DocOperationIndexedParameter) actionItemIter.next();
291 			int index = actionItemOp.getIndex().intValue();
292 			String opValue = actionItemOp.getValue();
293 
294 			String dateAssignedParamName = "actionItemDateAssigned" + index;
295             ActionItem actionItem =  docForm.getActionItems().get(index);
296 
297             if (!KewApiConstants.UPDATE.equals(opValue) && !KewApiConstants.DELETE.equals(opValue) && !KewApiConstants.NOOP.equals(opValue)) {
298 				throw new WorkflowServiceErrorException("Action Item operation not defined", new WorkflowServiceErrorImpl("Action Item operation not defined", "docoperation.operation.invalid"));
299 			}
300 			if (KewApiConstants.UPDATE.equals(opValue)) {
301 				try {
302 					actionItem.setDateAssigned(new Timestamp(RiceConstants.getDefaultDateFormat().parse(request.getParameter(dateAssignedParamName)).getTime()));
303 					actionItem.setDateAssignedStringValue(RiceConstants.getDefaultDateFormat().format(actionItem.getDateAssigned()));
304 					actionItem.setDocumentId(docForm.getRouteHeader().getDocumentId());
305 					// getActionItemService().validateActionItem(actionItem);
306 					getActionListService().saveActionItem(actionItem);
307 					change = true;
308 				} catch (ParseException pe) {
309 					throw new WorkflowServiceErrorException("Action item date assigned parsing error", new WorkflowServiceErrorImpl("Action item date assigned parse error", "docoperation.actionitem.dateassignedparsing.error", actionItem.getId().toString()));
310 				}
311 			}
312 			if (KewApiConstants.DELETE.equals(opValue)) {
313                 try {
314                     actionItem.setDateAssigned(new Timestamp(RiceConstants.getDefaultDateFormat().parse(request.getParameter(dateAssignedParamName)).getTime()));
315                     actionItem.setDateAssignedStringValue(RiceConstants.getDefaultDateFormat().format(actionItem.getDateAssigned()));
316                     actionItem.setDocumentId(docForm.getRouteHeader().getDocumentId());
317                     getActionListService().deleteActionItem(actionItem);
318                     change = true;
319                 } catch (ParseException pe) {
320                     throw new WorkflowServiceErrorException("Action item date assigned parsing error", new WorkflowServiceErrorImpl("Action item date assigned parse error", "docoperation.actionitem.dateassignedparsing.error", actionItem.getId().toString()));
321                 }
322 			}
323 		}
324 
325 		List routeNodeInstances=(List)(request.getSession().getAttribute("routeNodeInstances"));
326 		String ids = (docForm.getNodeStatesDelete() != null) ? docForm.getNodeStatesDelete().trim() : null;
327 		List statesToBeDeleted=new ArrayList();
328 		if(ids!=null && !ids.equals("")){
329 		    StringTokenizer idSets=new StringTokenizer(ids);
330 		    while (idSets.hasMoreTokens()) {
331 		    	String id=idSets.nextToken().trim();
332 		    	statesToBeDeleted.add(Long.valueOf(id));
333 		     }
334 		}
335 
336 		for (Iterator routeNodeInstanceIter = docForm.getRouteNodeInstanceOps().iterator(); routeNodeInstanceIter.hasNext();) {
337 			DocOperationIndexedParameter routeNodeInstanceOp = (DocOperationIndexedParameter) routeNodeInstanceIter.next();
338 			int index = routeNodeInstanceOp.getIndex().intValue();
339 			String opValue = routeNodeInstanceOp.getValue();
340             LOG.debug(opValue);
341 			RouteNodeInstance routeNodeInstance = (RouteNodeInstance)(routeNodeInstances.get(index));
342 			RouteNodeInstance routeNodeInstanceNew = (RouteNodeInstance)(docForm.getRouteNodeInstance(index));
343 			if (!KewApiConstants.UPDATE.equals(opValue) && !KewApiConstants.DELETE.equals(opValue) && !KewApiConstants.NOOP.equals(opValue)) {
344 				throw new WorkflowServiceErrorException("Route Node Instance Operation not defined", new WorkflowServiceErrorImpl("Route Node Instance Operation not defined", "docoperation.routenodeinstance.operation.invalid"));
345 			}
346 			if (KewApiConstants.UPDATE.equals(opValue)) {
347 				//LOG.debug("saving routeNodeInstance:"+routeNodeInstance.getRouteNodeInstanceId());
348 				//getRouteNodeService().save(routeNodeInstance);
349 				routeNodeInstance.setActive(routeNodeInstanceNew.isActive());
350 				LOG.debug(Boolean.toString(routeNodeInstanceNew.isActive()));
351 				routeNodeInstance.setComplete(routeNodeInstanceNew.isComplete());
352 				routeNodeInstance.setInitial(routeNodeInstanceNew.isInitial());
353 				List nodeStates=routeNodeInstance.getState();
354 				List nodeStatesNew=routeNodeInstanceNew.getState();
355 
356 				if(nodeStates!=null){
357 					for(int i=0;i<nodeStates.size();i++){
358 					   NodeState nodeState=(NodeState)nodeStates.get(i);
359 					   NodeState nodeStateNew=(NodeState)nodeStatesNew.get(i);
360 					   if(nodeStateNew.getKey()!=null && ! nodeStateNew.getKey().trim().equals("")){
361 					   nodeState.setKey(nodeStateNew.getKey());
362 					   LOG.debug(nodeState.getKey());
363 					   nodeState.setValue(nodeStateNew.getValue());
364 					   LOG.debug(nodeState.getValue());
365 					   }
366 				    }
367 				}
368 				routeNodeInstance = getRouteNodeService().save(routeNodeInstance);
369 				LOG.debug("saved");
370 				change = true;
371 			}
372 
373 
374 			if (KewApiConstants.DELETE.equals(opValue)) {
375 				List nodeStates=routeNodeInstance.getState();
376 				List nodeStatesNew=routeNodeInstanceNew.getState();
377 
378 				if(nodeStates!=null){
379 					for(int i=0;i<nodeStates.size();i++){
380 					   NodeState nodeState=(NodeState)nodeStates.get(i);
381 					   NodeState nodeStateNew=(NodeState)nodeStatesNew.get(i);
382 					   if(nodeStateNew.getKey()==null || nodeStateNew.getKey().trim().equals("")){
383 					     statesToBeDeleted.remove(nodeState.getNodeStateId());
384 					   }
385 				    }
386 				}
387 				getRouteNodeService().deleteByRouteNodeInstance(routeNodeInstance);
388 				LOG.debug(routeNodeInstance.getRouteNodeInstanceId()+" is deleted");
389 				change = true;
390 				break;
391 			}
392 
393 			if (KewApiConstants.NOOP.equals(opValue)){
394 				routeNodeInstanceNew.setActive(routeNodeInstance.isActive());
395 				routeNodeInstanceNew.setComplete(routeNodeInstance.isComplete());
396 				routeNodeInstanceNew.setInitial(routeNodeInstance.isInitial());
397 				List nodeStates=routeNodeInstance.getState();
398 				List nodeStatesNew=routeNodeInstanceNew.getState();
399 				if(nodeStates!=null){
400 				   for(int i=0;i<nodeStates.size();i++){
401 					   NodeState nodeState=(NodeState)nodeStates.get(i);
402 					   NodeState nodeStateNew=(NodeState)nodeStatesNew.get(i);
403 					   if(nodeStateNew.getKey()==null || nodeStateNew.getKey().trim().equals("")){
404 						     statesToBeDeleted.remove(nodeState.getNodeStateId());
405 					   }
406 					   nodeStateNew.setKey(nodeState.getKey());
407 					   nodeStateNew.setValue(nodeState.getValue());
408 				   }
409 				}
410 			}
411 
412 			//((DocOperationIndexedParameter)(docForm.getRouteNodeInstanceOps().get(index))).setValue(KewApiConstants.NOOP);
413 		}
414 
415 		if(statesToBeDeleted!=null && statesToBeDeleted.size()>0){
416 			getRouteNodeService().deleteNodeStates(statesToBeDeleted);
417 		}
418 
419 
420 		List branches=(List)(request.getSession().getAttribute("branches"));
421 		String branchStateIds = (docForm.getBranchStatesDelete() != null) ? docForm.getBranchStatesDelete().trim() : null;
422 		List branchStatesToBeDeleted=new ArrayList();
423 		if(branchStateIds!=null && !branchStateIds.equals("")){
424 		    StringTokenizer idSets=new StringTokenizer(branchStateIds);
425 		    while (idSets.hasMoreTokens()) {
426 		    	String id=idSets.nextToken().trim();
427 		    	branchStatesToBeDeleted.add(Long.valueOf(id));
428 		    }
429 		}
430 
431 		for (Iterator branchesOpIter = docForm.getBranchOps().iterator(); branchesOpIter.hasNext();) {
432 			DocOperationIndexedParameter branchesOp = (DocOperationIndexedParameter) branchesOpIter.next();
433 			int index = branchesOp.getIndex().intValue();
434 			String opValue = branchesOp.getValue();
435             LOG.debug(opValue);
436 			Branch branch = (Branch)(branches.get(index));
437 			Branch branchNew = (Branch)(docForm.getBranche(index));
438 			if (!KewApiConstants.UPDATE.equals(opValue) && !KewApiConstants.NOOP.equals(opValue)) {
439 				throw new WorkflowServiceErrorException("Route Node Instance Operation not defined", new WorkflowServiceErrorImpl("Route Node Instance Operation not defined", "docoperation.routenodeinstance.operation.invalid"));
440 			}
441 			if (KewApiConstants.UPDATE.equals(opValue)) {
442 				//LOG.debug("saving routeNodeInstance:"+routeNodeInstance.getRouteNodeInstanceId());
443 				//getRouteNodeService().save(routeNodeInstance);
444 				branch.setName(branchNew.getName());
445 				List branchStates=branch.getBranchState();
446 				List branchStatesNew=branchNew.getBranchState();
447 				if(branchStates!=null){
448 				   for(int i=0;i<branchStates.size();i++){
449 					   BranchState branchState=(BranchState)branchStates.get(i);
450 					   if (i < branchStatesNew.size()) {
451 					        BranchState branchStateNew=(BranchState)branchStatesNew.get(i);
452 					        if(branchStateNew.getKey()!=null && ! branchStateNew.getKey().trim().equals("")){
453 					            branchState.setKey(branchStateNew.getKey());
454 					            LOG.debug(branchState.getKey());
455 					            branchState.setValue(branchStateNew.getValue());
456 					            LOG.debug(branchState.getValue());
457                             }
458 					   }
459 				   }
460 				}
461 				getBranchService().save(branch);
462 				LOG.debug("branch saved");
463 				change = true;
464 
465 			}
466 
467 
468 			if (KewApiConstants.NOOP.equals(opValue)){
469 				branchNew.setName(branch.getName());
470 				List branchStates=branch.getBranchState();
471 				List branchStatesNew=branchNew.getBranchState();
472 				if(branchStates!=null){
473 				   for(int i=0;i<branchStates.size();i++){
474 					   BranchState branchState=(BranchState)branchStates.get(i);
475 					   BranchState branchStateNew=(BranchState)branchStatesNew.get(i);
476 					   if(branchStateNew.getKey()==null || branchStateNew.getKey().trim().equals("")){
477 						   branchStatesToBeDeleted.remove(branchState.getBranchStateId());
478 					   }
479 					   branchStateNew.setKey(branchState.getKey());
480 					   LOG.debug(branchState.getKey());
481 					   branchStateNew.setValue(branchState.getValue());
482 					   LOG.debug(branchState.getValue());
483 				   }
484 				}
485 			}
486 			//((DocOperationIndexedParameter)(docForm.getBranchOps().get(index))).setValue(KewApiConstants.NOOP);
487 		}
488 
489 		if(branchStatesToBeDeleted!=null && branchStatesToBeDeleted.size()>0){
490 			getBranchService().deleteBranchStates(branchStatesToBeDeleted);
491 		}
492 
493 		WorkflowDocument workflowDocument = WorkflowDocumentFactory.loadDocument(GlobalVariables.getUserSession().getPrincipalId(), docForm.getDocumentId());
494 
495 		String annotation = docForm.getAnnotation();
496 		if (StringUtils.isEmpty(annotation)) {
497 			annotation = DEFAULT_LOG_MSG;
498 		}
499 		workflowDocument.logAnnotation(annotation);
500 
501 		ActionMessages messages = new ActionMessages();
502 		String forward = null;
503 		if (change) {
504 			messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("docoperation.operation.saved"));
505 			docForm.setRouteHeader(getRouteHeaderService().getRouteHeader(docForm.getRouteHeader().getDocumentId()));
506 			forward = "summary";
507 		} else {
508 			messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("docoperation.operation.noop"));
509 			forward = "basic";
510 		}
511 		saveMessages(request, messages);
512 		return mapping.findForward(forward);
513 
514 	}
515 
516 	private RouteHeaderService getRouteHeaderService() {
517 		return (RouteHeaderService) KEWServiceLocator.getService(KEWServiceLocator.DOC_ROUTE_HEADER_SRV);
518 	}
519 
520 	private RouteNodeService getRouteNodeService(){
521 		return (RouteNodeService) KEWServiceLocator.getService(KEWServiceLocator.ROUTE_NODE_SERVICE);
522 	}
523 
524 	private ActionRequestService getActionRequestService() {
525 		return (ActionRequestService) KEWServiceLocator.getService(KEWServiceLocator.ACTION_REQUEST_SRV);
526 	}
527 
528 	private ActionTakenService getActionTakenService() {
529 		return (ActionTakenService) KEWServiceLocator.getService(KEWServiceLocator.ACTION_TAKEN_SRV);
530 	}
531 
532 	private ActionListService getActionListService() {
533 		return (ActionListService) KEWServiceLocator.getActionListService();
534 	}
535 
536 	private void setRouteHeaderTimestamps(DocumentOperationForm docForm) {
537 		if (docForm.getCreateDate() == null || docForm.getCreateDate().trim().equals("")) {
538 			throw new WorkflowServiceErrorException("Document create date empty", new WorkflowServiceErrorImpl("Document create date empty", "docoperation.routeheader.createdate.empty"));
539 		} else {
540 			try {
541 				
542 //				String a_pat = "yyyy-MM-dd hh:mm:ss";
543 //				SimpleDateFormat fmt = new SimpleDateFormat(a_pat);
544 //				
545 //				System.out.println("**********************new*******************");
546 //				System.out.println(docForm.getCreateDate());
547 //				System.out.println("**********************old*******************");
548 //				System.out.println(docForm.getRouteHeader().getCreateDate());
549 //				System.out.println("********************************************");
550 //	
551 	//			docForm.getRouteHeader().setCreateDate(new Timestamp(fmt.parse(docForm.getCreateDate()).getTime()));
552 
553 				docForm.getRouteHeader().setCreateDate(new Timestamp(RiceConstants.getDefaultDateAndTimeFormat().parse(docForm.getCreateDate()).getTime()));
554 			} catch (ParseException pe) {
555 				throw new WorkflowServiceErrorException("RouteHeader create date parsing error", new WorkflowServiceErrorImpl("Date parsing error", "docoperation.routeheader.createdate.invalid"));
556 			}
557 		}
558 
559 		if (docForm.getDateModified() == null || docForm.getDateModified().trim().equals("")) {
560 			throw new WorkflowServiceErrorException("Document doc status mod date empty", new WorkflowServiceErrorImpl("Document doc status mod date empty", "docoperation.routeheader.statusmoddate.empty"));
561 		} else {
562 			try {
563 				docForm.getRouteHeader().setDateModified(new Timestamp(
564                         RiceConstants.getDefaultDateAndTimeFormat().parse(docForm.getDateModified()).getTime()));
565 			} catch (ParseException pe) {
566 				throw new WorkflowServiceErrorException("Document doc status date parsing error", new WorkflowServiceErrorImpl("Document doc status mod date parsing error", "docoperation.routeheader.statusmoddate.invalid"));
567 			}
568 		}
569 
570 		if (docForm.getApprovedDate() != null && !docForm.getApprovedDate().trim().equals("")) {
571 			try {
572 				docForm.getRouteHeader().setApprovedDate(new Timestamp(RiceConstants.getDefaultDateAndTimeFormat().parse(docForm.getApprovedDate()).getTime()));
573 			} catch (ParseException pe) {
574 				throw new WorkflowServiceErrorException("Document approved date parsing error", new WorkflowServiceErrorImpl("Document approved date parsing error", "docoperation.routeheader.approveddate.invalid"));
575 			}
576 
577 		}
578 
579 		if (docForm.getFinalizedDate() != null && !docForm.getFinalizedDate().trim().equals("")) {
580 			try {
581 				docForm.getRouteHeader().setFinalizedDate(new Timestamp(RiceConstants.getDefaultDateAndTimeFormat().parse(docForm.getFinalizedDate()).getTime()));
582 			} catch (ParseException pe) {
583 				throw new WorkflowServiceErrorException("Document finalized date parsing error", new WorkflowServiceErrorImpl("Document finalized date parsing error", "docoperation.routeheader.finalizeddate.invalid"));
584 			}
585 		}
586 
587 		if (docForm.getRouteStatusDate() != null && !docForm.getRouteStatusDate().trim().equals("")) {
588 			try {
589 				docForm.getRouteHeader().setRouteStatusDate(new Timestamp(RiceConstants.getDefaultDateAndTimeFormat().parse(docForm.getRouteStatusDate()).getTime()));
590 			} catch (ParseException pe) {
591 				throw new WorkflowServiceErrorException("Document route status date parsing error", new WorkflowServiceErrorImpl("Document route status date parsing error", "docoperation.routeheader.routestatusdate.invalid"));
592 			}
593 
594 		}
595 	}
596 
597 	private void setRouteHeaderTimestampsToString(DocumentOperationForm docForm) {
598 		try {
599 			docForm.setCreateDate(RiceConstants.getDefaultDateAndTimeFormat().format(
600                     docForm.getRouteHeader().getCreateDate()));
601 			docForm.setDateModified(RiceConstants.getDefaultDateAndTimeFormat().format(
602                     docForm.getRouteHeader().getDateModified()));
603 			docForm.setApprovedDate(RiceConstants.getDefaultDateAndTimeFormat().format(
604                     docForm.getRouteHeader().getApprovedDate()));
605 			docForm.setFinalizedDate(RiceConstants.getDefaultDateAndTimeFormat().format(
606                     docForm.getRouteHeader().getFinalizedDate()));
607 			docForm.setRouteStatusDate(RiceConstants.getDefaultDateAndTimeFormat().format(
608                     docForm.getRouteHeader().getRouteStatusDate()));
609 
610 		} catch (Exception e) {
611 			LOG.info("One or more of the dates in routeHeader may be null");
612 		}
613 	}
614 
615 	public ActionForward refresh(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
616 		DocumentOperationForm docForm = (DocumentOperationForm) form;
617 		docForm.getRouteHeader().setDocumentId(docForm.getDocumentId());
618 		return mapping.findForward("basic");
619 	}
620 
621 	public ActionForward queueDocument(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
622 		try {
623 			DocumentOperationForm docForm = (DocumentOperationForm) form;
624             DocumentRouteHeaderValue document = docForm.getRouteHeader();
625             String applicationId = document.getDocumentType().getApplicationId();
626             DocumentProcessingQueue documentProcessingQueue = KewApiServiceLocator.getDocumentProcessingQueue(document.getDocumentId(), applicationId);
627 			documentProcessingQueue.process(docForm.getDocumentId());
628 			ActionMessages messages = new ActionMessages();
629 			messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("general.message", "Document was successfully queued"));
630 			saveMessages(request, messages);
631 			return mapping.findForward("basic");
632 		} catch (Exception e) {
633 			throw new WorkflowRuntimeException(e);
634 		}
635 	}
636 
637 	public ActionForward indexSearchableAttributes(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
638 		DocumentOperationForm docForm = (DocumentOperationForm) form;
639         DocumentAttributeIndexingQueue queue = KewApiServiceLocator.getDocumentAttributeIndexingQueue(docForm.getRouteHeader().getDocumentType().getApplicationId());
640         queue.indexDocument(docForm.getRouteHeader().getDocumentId());
641 		ActionMessages messages = new ActionMessages();
642 		messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("general.message", "Searchable Attribute Indexing was successfully scheduled"));
643 		saveMessages(request, messages);
644 		return mapping.findForward("basic");
645 	}
646 
647 	public ActionForward queueDocumentRefresh(ActionMapping mapping, ActionForm form, HttpServletRequest request,
648             HttpServletResponse response) throws IOException, ServletException {
649 		DocumentOperationForm docForm = (DocumentOperationForm) form;
650 		DocumentRefreshQueue docRequeue = KewApiServiceLocator.getDocumentRequeuerService(
651 		    docForm.getRouteHeader().getDocumentType().getApplicationId(), docForm.getRouteHeader().getDocumentId(), 0);
652 		docRequeue.refreshDocument(docForm.getRouteHeader().getDocumentId());
653 		ActionMessages messages = new ActionMessages();
654 		messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("general.message", "Document Requeuer was successfully scheduled"));
655 		saveMessages(request, messages);
656 		return mapping.findForward("basic");
657 	}
658 
659 	public ActionForward blanketApproveDocument(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
660 		try {
661 			DocumentOperationForm docForm = (DocumentOperationForm) form;
662             String blanketApproverUser = docForm.getBlanketApproveUser();
663             if (StringUtils.isBlank(blanketApproverUser)) {
664                 throw new WorkflowServiceErrorException("No user was provided in the Blanket Approve User field", new WorkflowServiceErrorImpl("No user was provided in the Blanket Approve User field", "docoperation.operation.invalid"));
665             }
666 			String principalId = KimApiServiceLocator.getPersonService().getPersonByPrincipalName(docForm.getBlanketApproveUser()).getPrincipalId();
667 			Set<String> nodeNames = new HashSet<String>();
668 			if (!StringUtils.isBlank(docForm.getBlanketApproveNodes())) {
669 				String[] nodeNameArray = docForm.getBlanketApproveNodes().split(",");
670 				for (String nodeName : nodeNameArray) {
671 					nodeNames.add(nodeName.trim());
672 				}
673 			}
674 			DocumentRouteHeaderValue document = docForm.getRouteHeader();
675             String applicationId = document.getDocumentType().getApplicationId();
676             DocumentOrchestrationQueue blanketApprove = KewApiServiceLocator.getDocumentOrchestrationQueue(
677                     document.getDocumentId(), applicationId);
678             OrchestrationConfig orchestrationConfig = OrchestrationConfig.create(docForm.getBlanketApproveActionTakenId(), nodeNames);
679             DocumentProcessingOptions options = DocumentProcessingOptions.createDefault();
680 			blanketApprove.orchestrateDocument(docForm.getRouteHeader().getDocumentId(), principalId,
681                     orchestrationConfig, options);
682 			ActionMessages messages = new ActionMessages();
683 			messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("general.message", "Blanket Approve Processor was successfully scheduled"));
684 			saveMessages(request, messages);
685 			return mapping.findForward("basic");
686 		} catch (Exception e) {
687 			throw new WorkflowRuntimeException(e);
688 		}
689 	}
690 	
691 	public ActionForward moveDocument(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
692 		try {
693 			DocumentOperationForm docForm = (DocumentOperationForm) form;
694 			String principalId = KEWServiceLocator.getIdentityHelperService().getIdForPrincipalName(docForm.getBlanketApproveUser());
695 			Set<String> nodeNames = new HashSet<String>();
696 			if (!StringUtils.isBlank(docForm.getBlanketApproveNodes())) {
697 				String[] nodeNameArray = docForm.getBlanketApproveNodes().split(",");
698 				for (String nodeName : nodeNameArray) {
699 					nodeNames.add(nodeName.trim());
700 				}
701 			}
702             DocumentRouteHeaderValue document = docForm.getRouteHeader();
703             String applicationId = document.getDocumentType().getApplicationId();
704             DocumentOrchestrationQueue orchestrationQueue = KewApiServiceLocator.getDocumentOrchestrationQueue(
705                     document.getDocumentId(), applicationId);
706             OrchestrationConfig orchestrationConfig = OrchestrationConfig.create(docForm.getBlanketApproveActionTakenId(), nodeNames);
707             DocumentProcessingOptions options = DocumentProcessingOptions.create(true, true, false);
708             orchestrationQueue.orchestrateDocument(docForm.getDocumentId(), principalId, orchestrationConfig, options);
709 
710             ActionMessages messages = new ActionMessages();
711 			messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("general.message", "Move Document Processor was successfully scheduled"));
712 			saveMessages(request, messages);
713 			return mapping.findForward("basic");
714 		} catch (Exception e) {
715 			throw new WorkflowRuntimeException(e);
716 		}
717 	}
718 
719 	public ActionForward queueActionInvocation(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
720 		try {
721 			DocumentOperationForm docForm = (DocumentOperationForm) form;
722 			String principalId = KEWServiceLocator.getIdentityHelperService().getIdForPrincipalName(docForm.getActionInvocationUser());
723 			ActionInvocation invocation = ActionInvocation.create(ActionType.fromCode(
724                     docForm.getActionInvocationActionCode()), docForm.getActionInvocationActionItemId());
725             DocumentRouteHeaderValue document = docForm.getRouteHeader();
726             String applicationId = document.getDocumentType().getApplicationId();
727 			ActionInvocationQueue actionInvocationQueue = KewApiServiceLocator.getActionInvocationProcessorService(
728 			    document.getDocumentId(), applicationId);
729 			actionInvocationQueue.invokeAction(principalId, docForm.getRouteHeader().getDocumentId(), invocation);
730 			ActionMessages messages = new ActionMessages();
731 			messages.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("general.message", "Action Invocation Processor was successfully scheduled"));
732 			saveMessages(request, messages);
733 			return mapping.findForward("basic");
734 		} catch (Exception e) {
735 			throw new WorkflowRuntimeException(e);
736 		}
737 	}
738 
739 	private DocumentTypeService getDocumentTypeService() {
740 		return (DocumentTypeService) KEWServiceLocator.getService(KEWServiceLocator.DOCUMENT_TYPE_SERVICE);
741 	}
742 
743 	private BranchService getBranchService(){
744 		return (BranchService) KEWServiceLocator.getService(KEWServiceLocator.BRANCH_SERVICE);
745 	}
746 }