X-Git-Url: http://git.argeo.org/?a=blobdiff_plain;f=runtime%2Forg.argeo.slc.core%2Fsrc%2Fmain%2Fjava%2Forg%2Fargeo%2Fslc%2Fcore%2Fexecution%2FDefaultExecutionFlowDescriptorConverter.java;h=f610cedea8fec0ad5d14d0bd842247ab246a3aec;hb=31a8055cac622a55afd2668e77f00aba1d031f91;hp=2b540f3c8171a3351f9f27ca3cf42080cdf04537;hpb=1535eecc68ecbda4e67e158de6bcecd074db2545;p=gpl%2Fargeo-slc.git diff --git a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultExecutionFlowDescriptorConverter.java b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultExecutionFlowDescriptorConverter.java index 2b540f3c8..f610cedea 100644 --- a/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultExecutionFlowDescriptorConverter.java +++ b/runtime/org.argeo.slc.core/src/main/java/org/argeo/slc/core/execution/DefaultExecutionFlowDescriptorConverter.java @@ -1,14 +1,16 @@ package org.argeo.slc.core.execution; -import java.util.ArrayList; +import java.util.Comparator; import java.util.HashMap; -import java.util.List; import java.util.Map; +import java.util.SortedSet; import java.util.TreeMap; +import java.util.TreeSet; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.slc.SlcException; +import org.argeo.slc.UnsupportedException; import org.argeo.slc.execution.ExecutionFlow; import org.argeo.slc.execution.ExecutionFlowDescriptor; import org.argeo.slc.execution.ExecutionFlowDescriptorConverter; @@ -23,9 +25,15 @@ import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.util.Assert; +import org.springframework.util.StringUtils; public class DefaultExecutionFlowDescriptorConverter implements ExecutionFlowDescriptorConverter, ApplicationContextAware { + public final static String REF_VALUE_TYPE_BEAN_NAME = "beanName"; + + /** Workaround for https://www.spartadn.com/bugzilla/show_bug.cgi?id=206 */ + private final static String REF_VALUE_INTERNAL = "[internal]"; + private final static Log log = LogFactory .getLog(DefaultExecutionFlowDescriptorConverter.class); @@ -33,27 +41,75 @@ public class DefaultExecutionFlowDescriptorConverter implements public Map convertValues( ExecutionFlowDescriptor executionFlowDescriptor) { - // convert the values of flow.getFlowDescriptor() Map values = executionFlowDescriptor.getValues(); - Map convertedValues = new HashMap(); + ExecutionSpec executionSpec = executionFlowDescriptor + .getExecutionSpec(); + + if (executionSpec == null && log.isTraceEnabled()) + log.warn("Execution spec is null for " + executionFlowDescriptor); + + if (values != null && executionSpec != null) { + values: for (String key : values.keySet()) { + ExecutionSpecAttribute attribute = executionSpec + .getAttributes().get(key); + + if (attribute.getIsFrozen()) + continue values; - if (values != null) { - for (String key : values.keySet()) { Object value = values.get(key); if (value instanceof PrimitiveValue) { PrimitiveValue primitiveValue = (PrimitiveValue) value; - - // TODO: check that the class of the the - // primitiveValue.value - // matches - // the primitiveValue.type + // TODO: check class <=> type convertedValues.put(key, primitiveValue.getValue()); } else if (value instanceof RefValue) { - // not yet implemented - - // RefValue refValue = (RefValue) value; - // convertedValues.put(key, refValue.getLabel()); + RefValue refValue = (RefValue) value; + String type = refValue.getType(); + if (REF_VALUE_TYPE_BEAN_NAME.equals(type)) { + // FIXME: UI should send all information about spec + // - targetClass + // - name + // String executionSpecName = executionSpec.getName(); + // ExecutionSpec localSpec = (ExecutionSpec) + // applicationContext + // .getBean(executionSpecName); + // RefSpecAttribute localAttr = (RefSpecAttribute) + // localSpec + // .getAttributes().get(key); + // Class targetClass = localAttr.getTargetClass(); + // + // String primitiveType = PrimitiveUtils + // .classAsType(targetClass); + String primitiveType = null; + if (primitiveType != null) { + // not active + String ref = refValue.getRef(); + Object obj = PrimitiveUtils.convert(primitiveType, + ref); + convertedValues.put(key, obj); + } else { + String ref = refValue.getRef(); + if (ref != null && !ref.equals(REF_VALUE_INTERNAL)) { + Object obj = null; + if (applicationContext.containsBean(ref)) { + obj = applicationContext.getBean(ref); + } else { + // FIXME: hack in order to pass primitive + obj = ref; + } + convertedValues.put(key, obj); + } else { + log.warn("Cannot interpret " + refValue); + } + } + } else if (PrimitiveUtils.typeAsClass(type) != null) { + String ref = refValue.getRef(); + Object obj = PrimitiveUtils.convert(type, ref); + convertedValues.put(key, obj); + } else { + throw new UnsupportedException("Ref value type", + refValue.getType()); + } } } } @@ -62,6 +118,8 @@ public class DefaultExecutionFlowDescriptorConverter implements public void addFlowsToDescriptor(ExecutionModuleDescriptor md, Map executionFlows) { + SortedSet set = new TreeSet( + new ExecutionFlowDescriptorComparator()); for (String name : executionFlows.keySet()) { ExecutionFlow executionFlow = executionFlows.get(name); @@ -91,8 +149,12 @@ public class DefaultExecutionFlowDescriptorConverter implements // all necessary information is in the spec } } else if (attribute instanceof RefSpecAttribute) { - values.put(key, buildRefValue((RefSpecAttribute) attribute, - executionFlow, key)); + if (attribute.getIsFrozen()) { + values.put(key, new RefValue(REF_VALUE_INTERNAL)); + } else + values.put(key, buildRefValue( + (RefSpecAttribute) attribute, executionFlow, + key)); } else { throw new SlcException("Unkown spec attribute type " + attribute.getClass()); @@ -104,57 +166,93 @@ public class DefaultExecutionFlowDescriptorConverter implements values, executionSpec); if (executionFlow.getPath() != null) efd.setPath(executionFlow.getPath()); + else + efd.setPath(""); + + // Takes description from spring + BeanDefinition bd = getBeanFactory().getBeanDefinition(name); + efd.setDescription(bd.getDescription()); // Add execution spec if necessary if (!md.getExecutionSpecs().contains(executionSpec)) md.getExecutionSpecs().add(executionSpec); // Add execution flow - md.getExecutionFlows().add(efd); + set.add(efd); + // md.getExecutionFlows().add(efd); } + md.getExecutionFlows().addAll(set); } @SuppressWarnings(value = { "unchecked" }) protected RefValue buildRefValue(RefSpecAttribute rsa, ExecutionFlow executionFlow, String key) { RefValue refValue = new RefValue(); + // FIXME: UI should be able to deal with other types + refValue.setType(REF_VALUE_TYPE_BEAN_NAME); + Class targetClass = rsa.getTargetClass(); + String primitiveType = PrimitiveUtils.classAsType(targetClass); + if (primitiveType != null) { + if (executionFlow.isSetAsParameter(key)) { + Object value = executionFlow.getParameter(key); + refValue.setRef(value.toString()); + } + refValue.setType(primitiveType); + return refValue; + } else { - if (executionFlow.isSetAsParameter(key)) { - String ref = null; - Object value = executionFlow.getParameter(key); - if (applicationContext == null) { - log - .warn("No application context declared, cannot scan ref value."); - ref = value.toString(); - } else { + if (executionFlow.isSetAsParameter(key)) { + String ref = null; + Object value = executionFlow.getParameter(key); + if (applicationContext == null) { + log + .warn("No application context declared, cannot scan ref value."); + ref = value.toString(); + } else { - // look for a ref to the value - Map beans = getBeanFactory().getBeansOfType( - rsa.getTargetClass(), false, false); - // TODO: also check scoped beans - beans: for (String beanName : beans.keySet()) { - Object obj = beans.get(beanName); - if (value instanceof ScopedObject) { - // don't call methods of the target of the scope - if (obj instanceof ScopedObject) - if (value == obj) { + // look for a ref to the value + Map beans = getBeanFactory() + .getBeansOfType(targetClass, false, false); + // TODO: also check scoped beans + beans: for (String beanName : beans.keySet()) { + Object obj = beans.get(beanName); + if (value instanceof ScopedObject) { + // don't call methods of the target of the scope + if (obj instanceof ScopedObject) + if (value == obj) { + ref = beanName; + break beans; + } + } else { + if (obj.equals(value)) { ref = beanName; break beans; } - } else { - if (obj.equals(value)) { - ref = beanName; - break beans; } } } + if (ref == null) { + log + .warn("Cannot define reference for ref spec attribute " + + key + + " in " + + executionFlow + + " (" + + rsa + + ")." + + " If it is an inner bean consider put it frozen."); + ref = REF_VALUE_INTERNAL; + } else { + if (log.isDebugEnabled()) + log.debug(ref + + " is the reference for ref spec attribute " + + key + " in " + executionFlow + " (" + rsa + + ")"); + } + refValue.setRef(ref); } - if (ref == null) - log.warn("Cannot define reference for ref spec attribute " - + key); - refValue.setRef(ref); + return refValue; } - return refValue; } private ConfigurableListableBeanFactory getBeanFactory() { @@ -168,4 +266,34 @@ public class DefaultExecutionFlowDescriptorConverter implements this.applicationContext = applicationContext; } + private static class ExecutionFlowDescriptorComparator implements + Comparator { + public int compare(ExecutionFlowDescriptor o1, + ExecutionFlowDescriptor o2) { + // TODO: write unit tests for this + if (StringUtils.hasText(o1.getPath()) + && StringUtils.hasText(o2.getPath())) { + if (o1.getPath().equals(o2.getPath())) + return o1.getName().compareTo(o2.getName()); + else if (o1.getPath().startsWith(o2.getPath())) + return -1; + else if (o2.getPath().startsWith(o1.getPath())) + return 1; + else + return o1.getPath().compareTo(o2.getPath()); + } else if (!StringUtils.hasText(o1.getPath()) + && StringUtils.hasText(o2.getPath())) { + return 1; + } else if (StringUtils.hasText(o1.getPath()) + && !StringUtils.hasText(o2.getPath())) { + return -1; + } else if (!StringUtils.hasText(o1.getPath()) + && !StringUtils.hasText(o2.getPath())) { + return o1.getName().compareTo(o2.getName()); + } else { + return 0; + } + } + + } }