001/** 002 * Copyright 2005-2015 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.kew.engine; 017 018import java.io.Serializable; 019import java.util.HashMap; 020import java.util.LinkedList; 021import java.util.List; 022import java.util.Map; 023 024import org.apache.commons.lang3.StringUtils; 025import org.kuali.rice.core.framework.util.ApplicationThreadLocal; 026import org.kuali.rice.kew.actionrequest.ActionRequestValue; 027import org.kuali.rice.kew.api.WorkflowRuntimeException; 028import org.kuali.rice.kew.engine.node.RouteNodeInstance; 029import org.kuali.rice.kew.routeheader.DocumentContent; 030import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue; 031import org.kuali.rice.kew.routeheader.StandardDocumentContent; 032 033 034/** 035 * Represents the current context of a Document being processed by the engine. 036 * 037 * @author Kuali Rice Team (rice.collab@kuali.org) 038 */ 039public class RouteContext implements Serializable { 040 041 private static final long serialVersionUID = -7125137491367944594L; 042 043 private String id; 044 045 private DocumentRouteHeaderValue routeHeader; 046 047 private DocumentContent documentContent; 048 049 private RouteNodeInstance nodeInstance; 050 051 private EngineState engineState; 052 053 private ActionRequestValue actionRequest; 054 055 private ActivationContext activationContext = new ActivationContext(!ActivationContext.CONTEXT_IS_SIMULATION); 056 057 private boolean doNotSendApproveNotificationEmails = false; 058 059 private Map parameters = new HashMap(); 060 061 private boolean searchIndexingRequestedForContext = false; 062 063 public RouteContext() { 064 id = new String(); 065 } 066 067 private static ThreadLocal<List<RouteContext>> ROUTE_CONTEXT_STACK = new ApplicationThreadLocal<List<RouteContext>>() { 068 protected List<RouteContext> initialValue() { 069 List<RouteContext> contextStack = new LinkedList<RouteContext>(); 070 contextStack.add(0, new RouteContext()); 071 return contextStack; 072 } 073 }; 074 075 public static RouteContext getCurrentRouteContext() { 076 return ROUTE_CONTEXT_STACK.get().get(0); 077 } 078 079 public static void clearRouteContextByDocumentId(String documentId) { 080 if(StringUtils.isNotBlank(documentId)) { 081 // Pop top stack element with matching document id and replace with empty 082 for(int i = 0; i < ROUTE_CONTEXT_STACK.get().size(); i++) { 083 if(ROUTE_CONTEXT_STACK.get().get(i).routeHeader.getDocumentId().equals(documentId)) { 084 ROUTE_CONTEXT_STACK.get().remove(i); 085 ROUTE_CONTEXT_STACK.get().add(i, new RouteContext()); 086 } 087 } 088 } 089 090 } 091 092 public static void clearCurrentRouteContext() { 093 ROUTE_CONTEXT_STACK.get().remove(0); 094 ROUTE_CONTEXT_STACK.get().add(0, new RouteContext()); 095 } 096 097 public static RouteContext createNewRouteContext() { 098 ROUTE_CONTEXT_STACK.get().add(0, new RouteContext()); 099 return getCurrentRouteContext(); 100 } 101 102 public static RouteContext releaseCurrentRouteContext() { 103 return ROUTE_CONTEXT_STACK.get().remove(0); 104 } 105 106 /** 107 * @deprecated use getDocument() instead 108 */ 109 public DocumentRouteHeaderValue getRouteHeader() { 110 return routeHeader; 111 } 112 113 /** 114 * @deprecated user setDocument() instead 115 */ 116 public void setRouteHeader(DocumentRouteHeaderValue routeHeader) { 117 this.routeHeader = routeHeader; 118 } 119 120 public DocumentRouteHeaderValue getDocument() { 121 return routeHeader; 122 } 123 124 public void setDocument(DocumentRouteHeaderValue routeHeader) { 125 this.routeHeader = routeHeader; 126 try { 127 setDocumentContent(new StandardDocumentContent(routeHeader.getDocContent(), this)); 128 } catch (Exception e) { 129 throw new WorkflowRuntimeException(e); 130 } 131 } 132 133 public DocumentContent getDocumentContent() { 134 return documentContent; 135 } 136 137 public void setDocumentContent(DocumentContent documentContent) { 138 this.documentContent = documentContent; 139 } 140 141 public RouteNodeInstance getNodeInstance() { 142 return nodeInstance; 143 } 144 145 public void setNodeInstance(RouteNodeInstance nodeInstance) { 146 this.nodeInstance = nodeInstance; 147 } 148 149 public EngineState getEngineState() { 150 return engineState; 151 } 152 153 public void setEngineState(EngineState engineState) { 154 this.engineState = engineState; 155 } 156 157 public ActionRequestValue getActionRequest() { 158 return actionRequest; 159 } 160 161 public void setActionRequest(ActionRequestValue actionRequest) { 162 this.actionRequest = actionRequest; 163 } 164 165 public boolean isSimulation() { 166 if (activationContext == null) { 167 return false; 168 } 169 return activationContext.isSimulation(); 170 } 171 172 public ActivationContext getActivationContext() { 173 return activationContext; 174 } 175 176 public void setActivationContext(ActivationContext activationContext) { 177 this.activationContext = activationContext; 178 } 179 180 public boolean isDoNotSendApproveNotificationEmails() { 181 return doNotSendApproveNotificationEmails; 182 } 183 184 public void setDoNotSendApproveNotificationEmails(boolean sendNotificationEmails) { 185 this.doNotSendApproveNotificationEmails = sendNotificationEmails; 186 } 187 188 public Map getParameters() { 189 return parameters; 190 } 191 192 public void setParameters(Map parameters) { 193 this.parameters = parameters; 194 } 195 196 /** 197 * Determines if search indexing has already been requested during this context 198 * @return the searchIndexingRequestedForContext: true if search indexing has been requested, false otherwise 199 */ 200 public boolean isSearchIndexingRequestedForContext() { 201 return this.searchIndexingRequestedForContext; 202 } 203 204 /** 205 * Sets the route context to let it know that search indexing has been requested 206 */ 207 public void requestSearchIndexingForContext() { 208 this.searchIndexingRequestedForContext = true; 209 } 210 211}