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}