]> git.argeo.org Git - gpl/argeo-slc.git/blobdiff - runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/MapExecutionContext.java
Support direct access to bean properties
[gpl/argeo-slc.git] / runtime / org.argeo.slc.core / src / main / java / org / argeo / slc / core / execution / MapExecutionContext.java
index 2dc9b867c01595d5aa90b69dce60f3a48b3bead2..97f4d91c2c0307ea7cbfc431e3e1cffee96400ee 100644 (file)
 package org.argeo.slc.core.execution;
 
+import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
-import java.util.Stack;
 import java.util.UUID;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
 import org.argeo.slc.SlcException;
 import org.argeo.slc.execution.ExecutionContext;
-import org.argeo.slc.execution.ExecutionFlow;
-import org.argeo.slc.execution.ExecutionSpecAttribute;
+import org.springframework.beans.BeanWrapper;
+import org.springframework.beans.BeanWrapperImpl;
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
 
-public class MapExecutionContext implements ExecutionContext {
-
-       private final static Log log = LogFactory.getLog(MapExecutionContext.class);
-
-       private final Stack<ExecutionFlowRuntime> stack = new Stack<ExecutionFlowRuntime>();
-
-       // TODO: make it thread safe?
-       private final Map<String, Object> variables = new HashMap<String, Object>();
+public class MapExecutionContext implements ExecutionContext,
+               ApplicationContextAware {
+       private final Map<String, Object> variables = Collections
+                       .synchronizedMap(new HashMap<String, Object>());
 
        private final String uuid;
 
-       private final Date creationDate = new Date();
+       private ApplicationContext applicationContext;
 
        public MapExecutionContext() {
                uuid = UUID.randomUUID().toString();
                variables.put(VAR_EXECUTION_CONTEXT_ID, uuid);
+               variables.put(VAR_EXECUTION_CONTEXT_CREATION_DATE, new Date());
        }
 
-       public void addVariables(
-                       Map<? extends String, ? extends Object> variablesToAdd) {
-               variables.putAll(variablesToAdd);
-       }
-
-       public void enterFlow(ExecutionFlow executionFlow) {
-               ExecutionFlowRuntime runtime = new ExecutionFlowRuntime(executionFlow);
-               stack.push(runtime);
-               variables.put(VAR_FLOW_ID, runtime.getUuid());
-               variables.put(VAR_FLOW_NAME, runtime.getExecutionFlow().getName());
-
-               if (log.isDebugEnabled())
-                       log.debug(depthSpaces(stack.size()) + "=> " + executionFlow + " #"
-                                       + uuid + ", depth=" + stack.size());
-
-               Map<String, ExecutionSpecAttribute> specAttrs = executionFlow
-                               .getExecutionSpec().getAttributes();
-               for (String key : specAttrs.keySet()) {
-                       // ExecutionSpecAttribute esa = specAttrs.get(key);
-                       if (executionFlow.isSetAsParameter(key)) {
-                               runtime.getLocalVariables().put(key,
-                                               executionFlow.getParameter(key));
-                               if (log.isTraceEnabled())
-                                       log.trace(depthSpaces(stack.size()) + "Add '" + key
-                                                       + "' as local variable.");
+       public void setVariable(String key, Object value) {
+               // check if we do not refer to a bean
+               int lastInd = key.lastIndexOf('.');
+               if (applicationContext != null && lastInd > 0) {
+                       String beanName = key.substring(0, lastInd);
+                       String propertyName = key.substring(lastInd + 1);
+                       if (applicationContext.containsBean(beanName)) {
+                               BeanWrapper beanWrapper = new BeanWrapperImpl(
+                                               applicationContext.getBean(beanName));
+                               if (!beanWrapper.isWritableProperty(propertyName))
+                                       throw new SlcException("No writable property "
+                                                       + propertyName + " in bean " + beanName);
+                               beanWrapper.setPropertyValue(propertyName, value);
                        }
                }
 
+               variables.put(key, value);
        }
 
        public Object getVariable(String key) {
-               Object obj = findVariable(key);
-               if (obj == null)
-                       throw new SlcException("Variable '" + key + "' not found.");
-               return obj;
-       }
-
-       public Object findVariable(String key) {
-               Object obj = null;
-
-               // Look if the variable is set in the global execution variables
-               // (i.e. the variable was overridden)
-               if (variables.containsKey(key))
-                       obj = variables.get(key);
-
-               // if the variable was not found, look in the stack starting at the
-               // upper flows
-               if (obj == null) {
-                       for (int i = 0; i < stack.size(); i++) {
-                               if (stack.get(i).getLocalVariables().containsKey(key)) {
-                                       obj = stack.get(i).getLocalVariables().get(key);
-                                       break;
-                               }
+               // check if we do not refer to a bean
+               int lastInd = key.lastIndexOf('.');
+               if (applicationContext != null && lastInd > 0) {
+                       String beanName = key.substring(0, lastInd);
+                       String propertyName = key.substring(lastInd + 1);
+                       if (applicationContext.containsBean(beanName)) {
+                               BeanWrapper beanWrapper = new BeanWrapperImpl(
+                                               applicationContext.getBean(beanName));
+                               if (!beanWrapper.isReadableProperty(propertyName))
+                                       throw new SlcException("No readable property "
+                                                       + propertyName + " in bean " + beanName);
+                               Object obj = beanWrapper.getPropertyValue(propertyName);
+                               return obj;
                        }
                }
 
-               return obj;
-       }
-
-       private static String depthSpaces(int depth) {
-               StringBuffer buf = new StringBuffer(depth * 2);
-               for (int i = 0; i < depth; i++)
-                       buf.append("  ");
-               return buf.toString();
-       }
-
-       public void leaveFlow(ExecutionFlow executionFlow) {
-               if (log.isDebugEnabled())
-                       log.debug(depthSpaces(stack.size()) + "<= " + executionFlow + " #"
-                                       + uuid + ", depth=" + stack.size());
-
-               ExecutionFlowRuntime leftEf = stack.pop();
-               if (!leftEf.getExecutionFlow().getName()
-                               .equals(executionFlow.getName()))
-                       throw new SlcException("Asked to leave " + executionFlow
-                                       + " but last is " + leftEf);
-
-               leftEf.getScopedObjects().clear();
-               leftEf.getLocalVariables().clear();
-
-       }
-
-       public void addScopedObject(String name, Object obj) {
-               // TODO: check that the object is not set yet ?
-               stack.peek().getScopedObjects().put(name, obj);
-       }
-
-       /** return null if not found */
-       public Object findScopedObject(String name) {
-               Object obj = null;
-               for (int i = stack.size() - 1; i >= 0; i--) {
-                       if (stack.get(i).getScopedObjects().containsKey(name)) {
-                               obj = stack.get(i).getScopedObjects().get(name);
-                               break;
-                       }
-               }
-               return obj;
+               return variables.get(key);
        }
 
        public String getUuid() {
                return uuid;
        }
 
-       public Date getCreationDate() {
-               return creationDate;
+       @Override
+       public boolean equals(Object obj) {
+               if (obj instanceof ExecutionContext)
+                       return uuid.equals(((ExecutionContext) obj).getUuid());
+               return false;
        }
 
-       private static class ExecutionFlowRuntime {
-               private final ExecutionFlow executionFlow;
-               private final Map<String, Object> scopedObjects = new HashMap<String, Object>();
-               private final Map<String, Object> localVariables = new HashMap<String, Object>();
-               private final String uuid = UUID.randomUUID().toString();
-
-               public ExecutionFlowRuntime(ExecutionFlow executionFlow) {
-                       this.executionFlow = executionFlow;
-               }
-
-               public ExecutionFlow getExecutionFlow() {
-                       return executionFlow;
-               }
-
-               public Map<String, Object> getScopedObjects() {
-                       return scopedObjects;
-               }
-
-               public String getUuid() {
-                       return uuid;
-               }
-
-               public Map<String, Object> getLocalVariables() {
-                       return localVariables;
-               }
+       @Override
+       public String toString() {
+               return getClass().getSimpleName() + "#" + uuid;
+       }
 
+       public void setApplicationContext(ApplicationContext applicationContext)
+                       throws BeansException {
+               this.applicationContext = applicationContext;
        }
+
 }