View Javadoc
1   /*
2    * Copyright (C) 2007-2012 Argeo GmbH
3    *
4    * Licensed under the Apache 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.apache.org/licenses/LICENSE-2.0
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.argeo.slc.core.execution;
17  
18  import java.util.Stack;
19  
20  import org.apache.commons.logging.Log;
21  import org.apache.commons.logging.LogFactory;
22  import org.argeo.slc.SlcException;
23  import org.argeo.slc.execution.ExecutionFlow;
24  import org.argeo.slc.execution.ExecutionSpecAttribute;
25  
26  /** Manage parameters that need to be set during the instantiation of a flow */
27  public class InstantiationManager {
28  
29  	private final static Log log = LogFactory
30  			.getLog(InstantiationManager.class);
31  
32  	private ThreadLocal<Stack<ExecutionFlow>> flowStack = new ThreadLocal<Stack<ExecutionFlow>>();
33  
34  	public Object createRef(String name) {
35  
36  		if ((flowStack.get() == null) || flowStack.get().empty()) {
37  			throw new SlcException("No flow is currently initializing."
38  					+ " Declare ParameterRef as inner beans or prototypes.");
39  		}
40  
41  		return getInitializingFlowParameter(name);
42  	}
43  
44  	public void flowInitializationStarted(ExecutionFlow flow, String flowName) {
45  		// set the flow name if it is DefaultExecutionFlow
46  		if (flow instanceof DefaultExecutionFlow) {
47  			((DefaultExecutionFlow) flow).setBeanName(flowName);
48  		}
49  
50  		if (log.isTraceEnabled())
51  			log.trace("Start initialization of " + flow.hashCode() + " ("
52  					+ flow + " - " + flow.getClass() + ")");
53  
54  		// log.info("# flowInitializationStarted " + flowName);
55  		// create a stack for this thread if there is none
56  		if (flowStack.get() == null) {
57  			flowStack.set(new Stack<ExecutionFlow>());
58  		}
59  		flowStack.get().push(flow);
60  	}
61  
62  	public void flowInitializationFinished(ExecutionFlow flow, String flowName) {
63  		if (log.isTraceEnabled())
64  			log.trace("Finish initialization of " + flow.hashCode() + " ("
65  					+ flow + " - " + flow.getClass() + ")");
66  
67  		if (flowStack.get() != null) {
68  			ExecutionFlow registeredFlow = flowStack.get().pop();
69  			if (registeredFlow != null) {
70  				if (!flow.getName().equals(registeredFlow.getName()))
71  					throw new SlcException("Current flow is " + flow);
72  				// log.info("# flowInitializationFinished " + flowName);
73  				// initializingFlow.set(null);
74  			}
75  		} else {
76  			// happens for flows imported as services
77  			log.warn("flowInitializationFinished - Flow Stack is null");
78  		}
79  	}
80  
81  	protected ExecutionFlow findInitializingFlowWithParameter(String key) {
82  		if ((flowStack.get() == null) || flowStack.get().empty())
83  			throw new SlcException("No initializing flow available.");
84  
85  		// first look in the outer flow (that may override parameters)
86  		for (int i = 0; i < flowStack.get().size(); i++) {
87  			if (flowStack.get().elementAt(i).isSetAsParameter(key)) {
88  				return flowStack.get().elementAt(i);
89  			}
90  		}
91  		throw new SlcException("Key " + key + " is not set as parameter in "
92  				+ flowStack.get().firstElement().toString() + " (stack size="
93  				+ flowStack.get().size() + ")");
94  
95  	}
96  
97  	public Object getInitializingFlowParameter(String key) {
98  		return findInitializingFlowWithParameter(key).getParameter(key);
99  	}
100 
101 	public Class<?> getInitializingFlowParameterClass(String key) {
102 		ExecutionSpecAttribute attr = findInitializingFlowWithParameter(key)
103 				.getExecutionSpec().getAttributes().get(key);
104 		if (attr instanceof RefSpecAttribute)
105 			return ((RefSpecAttribute) attr).getTargetClass();
106 		else if (attr instanceof PrimitiveSpecAttribute) {
107 			String type = ((PrimitiveSpecAttribute) attr).getType();
108 			Class<?> clss = PrimitiveUtils.typeAsClass(type);
109 			if (clss == null)
110 				throw new SlcException("Cannot convert type " + type
111 						+ " to class.");
112 			return clss;
113 		} else
114 			return null;
115 	}
116 
117 	public Boolean isInFlowInitialization() {
118 		return (flowStack.get() != null) && !flowStack.get().empty();
119 	}
120 }