1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  package org.argeo.slc.core.execution;
17  
18  import java.util.HashMap;
19  import java.util.Map;
20  import java.util.Stack;
21  import java.util.UUID;
22  
23  import org.apache.commons.logging.Log;
24  import org.apache.commons.logging.LogFactory;
25  import org.argeo.slc.SlcException;
26  import org.argeo.slc.execution.ExecutionFlow;
27  import org.argeo.slc.execution.ExecutionSpecAttribute;
28  import org.argeo.slc.execution.ExecutionStack;
29  
30  
31  public class DefaultExecutionStack implements ExecutionStack {
32  
33  	private final static Log log = LogFactory
34  			.getLog(DefaultExecutionStack.class);
35  
36  	private final Stack<ExecutionFlowRuntime> stack = new Stack<ExecutionFlowRuntime>();
37  
38  	public synchronized void enterFlow(ExecutionFlow executionFlow) {
39  		ExecutionFlowRuntime runtime = new ExecutionFlowRuntime(executionFlow);
40  		stack.push(runtime);
41  
42  		Map<String, ExecutionSpecAttribute> specAttrs = executionFlow
43  				.getExecutionSpec().getAttributes();
44  		for (String key : specAttrs.keySet()) {
45  			if (executionFlow.isSetAsParameter(key)) {
46  				runtime.getLocalVariables().put(key,
47  						executionFlow.getParameter(key));
48  			}
49  		}
50  	}
51  
52  	public synchronized String getCurrentStackLevelUuid() {
53  		return stack.peek().getUuid();
54  	}
55  
56  	public synchronized Integer getStackSize() {
57  		return stack.size();
58  	}
59  
60  	
61  
62  
63  
64  
65  	public synchronized Object findLocalVariable(String key) {
66  		Object obj = null;
67  		for (int i = 0; i < stack.size(); i++) {
68  			if (stack.get(i).getLocalVariables().containsKey(key)) {
69  				obj = stack.get(i).getLocalVariables().get(key);
70  				break;
71  			}
72  		}
73  		return obj;
74  	}
75  
76  	public synchronized void leaveFlow(ExecutionFlow executionFlow) {
77  		ExecutionFlowRuntime leftEf = stack.pop();
78  
79  		if (!leftEf.getExecutionFlow().getName()
80  				.equals(executionFlow.getName()))
81  			throw new SlcException("Asked to leave " + executionFlow
82  					+ " but last is " + leftEf);
83  
84  		leftEf.getScopedObjects().clear();
85  		leftEf.getLocalVariables().clear();
86  	}
87  
88  	public synchronized void addScopedObject(String name, Object obj) {
89  		ExecutionFlowRuntime runtime = stack.peek();
90  		
91  		if (log.isDebugEnabled()) {
92  			Object existing = findScopedObject(name);
93  			if (existing != null)
94  				log.warn("Scoped object " + name + " of type " + obj.getClass()
95  						+ " already registered in " + runtime);
96  		}
97  		runtime.getScopedObjects().put(name, obj);
98  	}
99  
100 	
101 	public synchronized Object findScopedObject(String name) {
102 		Object obj = null;
103 		for (int i = stack.size() - 1; i >= 0; i--) {
104 			if (stack.get(i).getScopedObjects().containsKey(name)) {
105 				obj = stack.get(i).getScopedObjects().get(name);
106 				break;
107 			}
108 		}
109 		return obj;
110 	}
111 
112 	protected static class ExecutionFlowRuntime {
113 		private final ExecutionFlow executionFlow;
114 		private final Map<String, Object> scopedObjects = new HashMap<String, Object>();
115 		private final Map<String, Object> localVariables = new HashMap<String, Object>();
116 		private final String uuid = UUID.randomUUID().toString();
117 
118 		public ExecutionFlowRuntime(ExecutionFlow executionFlow) {
119 			this.executionFlow = executionFlow;
120 		}
121 
122 		public ExecutionFlow getExecutionFlow() {
123 			return executionFlow;
124 		}
125 
126 		public Map<String, Object> getScopedObjects() {
127 			return scopedObjects;
128 		}
129 
130 		public String getUuid() {
131 			return uuid;
132 		}
133 
134 		public Map<String, Object> getLocalVariables() {
135 			return localVariables;
136 		}
137 
138 		@Override
139 		public String toString() {
140 			return "Stack Level #" + uuid;
141 		}
142 
143 	}
144 }