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