You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ofbiz.apache.org by ad...@apache.org on 2012/07/10 14:06:00 UTC

svn commit: r1359626 [5/12] - in /ofbiz/branches/release12.04: ./ framework/base/ framework/base/src/org/ofbiz/base/util/collections/ framework/base/src/org/ofbiz/base/util/collections/test/ framework/base/src/org/ofbiz/base/util/string/ framework/enti...

Modified: ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/callops/CallServiceAsynch.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/callops/CallServiceAsynch.java?rev=1359626&r1=1359625&r2=1359626&view=diff
==============================================================================
--- ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/callops/CallServiceAsynch.java (original)
+++ ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/callops/CallServiceAsynch.java Tue Jul 10 12:05:55 2012
@@ -24,99 +24,120 @@ import java.util.Map;
 import javolution.util.FastMap;
 
 import org.ofbiz.base.util.Debug;
+import org.ofbiz.base.util.collections.FlexibleMapAccessor;
+import org.ofbiz.base.util.string.FlexibleStringExpander;
 import org.ofbiz.entity.GenericValue;
 import org.ofbiz.minilang.MiniLangException;
+import org.ofbiz.minilang.MiniLangValidate;
 import org.ofbiz.minilang.SimpleMethod;
-import org.ofbiz.minilang.method.ContextAccessor;
+import org.ofbiz.minilang.artifact.ArtifactInfoContext;
 import org.ofbiz.minilang.method.MethodContext;
 import org.ofbiz.minilang.method.MethodOperation;
 import org.ofbiz.service.GenericServiceException;
 import org.w3c.dom.Element;
 
 /**
- * Calls a service using the given parameters
+ * Implements the <call-service-asynch> element.
+ * 
+ * @see <a href="https://cwiki.apache.org/OFBADMIN/mini-language-reference.html#Mini-languageReference-{{%3Ccallserviceasynch%3E}}">Mini-language Reference</a>
  */
-public class CallServiceAsynch extends MethodOperation {
+public final class CallServiceAsynch extends MethodOperation {
 
     public static final String module = CallServiceAsynch.class.getName();
 
-    protected String includeUserLoginStr;
-    protected ContextAccessor<Map<String, Object>> inMapAcsr;
-    protected String serviceName;
+    private final boolean includeUserLogin;
+    private final FlexibleMapAccessor<Map<String, Object>> inMapFma;
+    private final FlexibleStringExpander serviceNameFse;
 
     public CallServiceAsynch(Element element, SimpleMethod simpleMethod) throws MiniLangException {
         super(element, simpleMethod);
-        serviceName = element.getAttribute("service-name");
-        inMapAcsr = new ContextAccessor<Map<String, Object>>(element.getAttribute("in-map-name"));
-        includeUserLoginStr = element.getAttribute("include-user-login");
+        if (MiniLangValidate.validationOn()) {
+            MiniLangValidate.attributeNames(simpleMethod, element, "serviceName", "in-map-name", "include-user-login");
+            MiniLangValidate.constantAttributes(simpleMethod, element, "include-user-login");
+            MiniLangValidate.expressionAttributes(simpleMethod, element, "service-name", "in-map-name");
+            MiniLangValidate.requiredAttributes(simpleMethod, element, "service-name");
+            MiniLangValidate.noChildElements(simpleMethod, element);
+        }
+        serviceNameFse = FlexibleStringExpander.getInstance(element.getAttribute("service-name"));
+        inMapFma = FlexibleMapAccessor.getInstance(element.getAttribute("in-map-name"));
+        includeUserLogin = !"false".equals(element.getAttribute("include-user-login"));
     }
 
     @Override
     public boolean exec(MethodContext methodContext) throws MiniLangException {
-        String serviceName = methodContext.expandString(this.serviceName);
-        boolean includeUserLogin = !"false".equals(methodContext.expandString(includeUserLoginStr));
-        Map<String, Object> inMap = null;
-        if (inMapAcsr.isEmpty()) {
+        if (methodContext.isTraceOn()) {
+            outputTraceMessage(methodContext, "Begin call-service-asynch.");
+        }
+        String serviceName = serviceNameFse.expandString(methodContext.getEnvMap());
+        Map<String, Object> inMap = inMapFma.get(methodContext.getEnvMap());
+        if (inMap == null) {
             inMap = FastMap.newInstance();
-        } else {
-            inMap = inMapAcsr.get(methodContext);
-            if (inMap == null) {
-                inMap = FastMap.newInstance();
-                inMapAcsr.put(methodContext, inMap);
-            }
         }
-        // add UserLogin to context if expected
         if (includeUserLogin) {
             GenericValue userLogin = methodContext.getUserLogin();
-
             if (userLogin != null && inMap.get("userLogin") == null) {
                 inMap.put("userLogin", userLogin);
             }
         }
-        // always add Locale to context unless null
         Locale locale = methodContext.getLocale();
         if (locale != null) {
             inMap.put("locale", locale);
         }
-        // invoke the service
         try {
+            if (methodContext.isTraceOn()) {
+                outputTraceMessage(methodContext, "Invoking service \"" + serviceName + "\", IN attributes:", inMap.toString());
+            }
             methodContext.getDispatcher().runAsync(serviceName, inMap);
         } catch (GenericServiceException e) {
+            if (methodContext.isTraceOn()) {
+                outputTraceMessage(methodContext, "Service engine threw an exception: " + e.getMessage() + ", halting script execution. End call-service-asynch.");
+            }
             Debug.logError(e, module);
             String errMsg = "ERROR: Could not complete the " + simpleMethod.getShortDescription() + " process [problem invoking the " + serviceName + " service: " + e.getMessage() + "]";
             if (methodContext.getMethodType() == MethodContext.EVENT) {
                 methodContext.putEnv(simpleMethod.getEventErrorMessageName(), errMsg);
                 methodContext.putEnv(simpleMethod.getEventResponseCodeName(), simpleMethod.getDefaultErrorCode());
-            } else if (methodContext.getMethodType() == MethodContext.SERVICE) {
+            } else {
                 methodContext.putEnv(simpleMethod.getServiceErrorMessageName(), errMsg);
                 methodContext.putEnv(simpleMethod.getServiceResponseMessageName(), simpleMethod.getDefaultErrorCode());
             }
             return false;
         }
+        if (methodContext.isTraceOn()) {
+            outputTraceMessage(methodContext, "End call-service-asynch.");
+        }
         return true;
     }
 
     @Override
-    public String expandedString(MethodContext methodContext) {
-        // TODO: something more than a stub/dummy
-        return this.rawString();
-    }
-
-    public String getServiceName() {
-        return this.serviceName;
+    public void gatherArtifactInfo(ArtifactInfoContext aic) {
+        aic.addServiceName(this.serviceNameFse.toString());
     }
 
     @Override
-    public String rawString() {
-        // TODO: something more than the empty tag
-        return "<call-service-asynch/>";
-    }
-
+    public String toString() {
+        StringBuilder sb = new StringBuilder("<call-service-asynch ");
+        sb.append("service-name=\"").append(this.serviceNameFse).append("\" ");
+        if (!this.inMapFma.isEmpty()) {
+            sb.append("in-map-name=\"").append(this.inMapFma).append("\" ");
+        }
+        if (!this.includeUserLogin) {
+            sb.append("include-user-login=\"false\" ");
+        }
+        sb.append("/>");
+        return sb.toString();
+    }
+
+    /**
+     * A factory for the &lt;call-service-asynch&gt; element.
+     */
     public static final class CallServiceAsynchFactory implements Factory<CallServiceAsynch> {
+        @Override
         public CallServiceAsynch createMethodOperation(Element element, SimpleMethod simpleMethod) throws MiniLangException {
             return new CallServiceAsynch(element, simpleMethod);
         }
 
+        @Override
         public String getName() {
             return "call-service-asynch";
         }

Modified: ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/callops/CallSimpleMapProcessor.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/callops/CallSimpleMapProcessor.java?rev=1359626&r1=1359625&r2=1359626&view=diff
==============================================================================
--- ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/callops/CallSimpleMapProcessor.java (original)
+++ ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/callops/CallSimpleMapProcessor.java Tue Jul 10 12:05:55 2012
@@ -24,69 +24,78 @@ import java.util.Map;
 import javolution.util.FastList;
 import javolution.util.FastMap;
 
-import org.ofbiz.base.util.UtilValidate;
 import org.ofbiz.base.util.UtilXml;
+import org.ofbiz.base.util.collections.FlexibleMapAccessor;
 import org.ofbiz.minilang.MiniLangException;
+import org.ofbiz.minilang.MiniLangValidate;
+import org.ofbiz.minilang.SimpleMapProcessor;
 import org.ofbiz.minilang.SimpleMethod;
-import org.ofbiz.minilang.method.ContextAccessor;
 import org.ofbiz.minilang.method.MethodContext;
 import org.ofbiz.minilang.method.MethodOperation;
 import org.ofbiz.minilang.operation.MapProcessor;
 import org.w3c.dom.Element;
 
 /**
- * An event operation that calls a simple map processor inlined or from a separate file
+ * Implements the &lt;call-map-processor&gt; element.
+ * 
+ * @see <a href="https://cwiki.apache.org/OFBADMIN/mini-language-reference.html#Mini-languageReference-{{%3Ccallmapprocessor%3E}}">Mini-language Reference</a>
  */
-public class CallSimpleMapProcessor extends MethodOperation {
+public final class CallSimpleMapProcessor extends MethodOperation {
 
-    ContextAccessor<List<Object>> errorListAcsr;
-    MapProcessor inlineMapProcessor = null;
-    ContextAccessor<Map<String, Object>> inMapAcsr;
-    ContextAccessor<Map<String, Object>> outMapAcsr;
-    String processorName;
-    String xmlResource;
+    private final FlexibleMapAccessor<List<Object>> errorListFma;
+    private final MapProcessor inlineMapProcessor;
+    private final FlexibleMapAccessor<Map<String, Object>> inMapFma;
+    private final FlexibleMapAccessor<Map<String, Object>> outMapFma;
+    private final String processorName;
+    private final String xmlResource;
 
     public CallSimpleMapProcessor(Element element, SimpleMethod simpleMethod) throws MiniLangException {
         super(element, simpleMethod);
-        xmlResource = element.getAttribute("xml-resource");
+        if (MiniLangValidate.validationOn()) {
+            MiniLangValidate.attributeNames(simpleMethod, element, "processor-name", "xml-resource", "in-map-name", "out-map-name", "error-list-name");
+            MiniLangValidate.constantAttributes(simpleMethod, element, "processor-name", "xml-resource", "error-list-name");
+            MiniLangValidate.expressionAttributes(simpleMethod, element, "in-map-name", "out-map-name");
+            MiniLangValidate.requiredAttributes(simpleMethod, element, "in-map-name", "out-map-name");
+            MiniLangValidate.childElements(simpleMethod, element, "simple-map-processor");
+        }
         processorName = element.getAttribute("processor-name");
-        inMapAcsr = new ContextAccessor<Map<String, Object>>(element.getAttribute("in-map-name"));
-        outMapAcsr = new ContextAccessor<Map<String, Object>>(element.getAttribute("out-map-name"));
-        errorListAcsr = new ContextAccessor<List<Object>>(element.getAttribute("error-list-name"), "error_list");
+        xmlResource = element.getAttribute("xml-resource");
+        errorListFma = FlexibleMapAccessor.getInstance(MiniLangValidate.checkAttribute(element.getAttribute("error-list-name"), "error_list"));
+        inMapFma = FlexibleMapAccessor.getInstance(element.getAttribute("in-map-name"));
+        outMapFma = FlexibleMapAccessor.getInstance(element.getAttribute("out-map-name"));
         Element simpleMapProcessorElement = UtilXml.firstChildElement(element, "simple-map-processor");
         if (simpleMapProcessorElement != null) {
             inlineMapProcessor = new MapProcessor(simpleMapProcessorElement);
+        } else {
+            inlineMapProcessor = null;
         }
     }
 
     @Override
     public boolean exec(MethodContext methodContext) throws MiniLangException {
-        List<Object> messages = errorListAcsr.get(methodContext);
+        List<Object> messages = errorListFma.get(methodContext.getEnvMap());
         if (messages == null) {
             messages = FastList.newInstance();
-            errorListAcsr.put(methodContext, messages);
+            errorListFma.put(methodContext.getEnvMap(), messages);
         }
-        Map<String, Object> inMap = inMapAcsr.get(methodContext);
+        Map<String, Object> inMap = inMapFma.get(methodContext.getEnvMap());
         if (inMap == null) {
             inMap = FastMap.newInstance();
-            inMapAcsr.put(methodContext, inMap);
         }
-        Map<String, Object> outMap = outMapAcsr.get(methodContext);
+        Map<String, Object> outMap = outMapFma.get(methodContext.getEnvMap());
         if (outMap == null) {
             outMap = FastMap.newInstance();
-            outMapAcsr.put(methodContext, outMap);
+            outMapFma.put(methodContext.getEnvMap(), outMap);
         }
         // run external map processor first
-        if (UtilValidate.isNotEmpty(this.xmlResource) && UtilValidate.isNotEmpty(this.processorName)) {
-            String xmlResource = methodContext.expandString(this.xmlResource);
-            String processorName = methodContext.expandString(this.processorName);
+        if (!this.xmlResource.isEmpty() && !this.processorName.isEmpty()) {
             try {
-                org.ofbiz.minilang.SimpleMapProcessor.runSimpleMapProcessor(xmlResource, processorName, inMap, outMap, messages, methodContext.getLocale(), methodContext.getLoader());
+                SimpleMapProcessor.runSimpleMapProcessor(xmlResource, processorName, inMap, outMap, messages, methodContext.getLocale(), methodContext.getLoader());
             } catch (MiniLangException e) {
                 messages.add("Error running SimpleMapProcessor in XML file \"" + xmlResource + "\": " + e.toString());
             }
         }
-        // run inlined map processor last so it can override the external map processor
+        // run inline map processor last so it can override the external map processor
         if (inlineMapProcessor != null) {
             inlineMapProcessor.exec(inMap, outMap, messages, methodContext.getLocale(), methodContext.getLoader());
         }
@@ -94,22 +103,37 @@ public class CallSimpleMapProcessor exte
     }
 
     @Override
-    public String expandedString(MethodContext methodContext) {
-        // TODO: something more than a stub/dummy
-        return this.rawString();
-    }
-
-    @Override
-    public String rawString() {
-        // TODO: something more than the empty tag
-        return "<call-simple-map-processor/>";
+    public String toString() {
+        StringBuilder sb = new StringBuilder("<call-map-processor ");
+        if (!this.processorName.isEmpty()) {
+            sb.append("processor-name=\"").append(this.processorName).append("\" ");
+        }
+        if (!this.xmlResource.isEmpty()) {
+            sb.append("xml-resource=\"").append(this.xmlResource).append("\" ");
+        }
+        if (!this.inMapFma.isEmpty()) {
+            sb.append("in-map-name=\"").append(this.inMapFma).append("\" ");
+        }
+        if (!this.outMapFma.isEmpty()) {
+            sb.append("out-map-name=\"").append(this.outMapFma).append("\" ");
+        }
+        if (!"error_list".equals(errorListFma.toString())) {
+            sb.append("error-list-name=\"").append(errorListFma).append("\" ");
+        }
+        sb.append("/>");
+        return sb.toString();
     }
 
+    /**
+     * A factory for the &lt;call-map-processor&gt; element.
+     */
     public static final class CallSimpleMapProcessorFactory implements Factory<CallSimpleMapProcessor> {
+        @Override
         public CallSimpleMapProcessor createMethodOperation(Element element, SimpleMethod simpleMethod) throws MiniLangException {
             return new CallSimpleMapProcessor(element, simpleMethod);
         }
 
+        @Override
         public String getName() {
             return "call-map-processor";
         }

Modified: ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/callops/CallSimpleMethod.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/callops/CallSimpleMethod.java?rev=1359626&r1=1359625&r2=1359626&view=diff
==============================================================================
--- ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/callops/CallSimpleMethod.java (original)
+++ ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/callops/CallSimpleMethod.java Tue Jul 10 12:05:55 2012
@@ -18,28 +18,33 @@
  *******************************************************************************/
 package org.ofbiz.minilang.method.callops;
 
+import java.net.MalformedURLException;
+import java.net.URL;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
 import javolution.util.FastMap;
 
+import org.ofbiz.base.location.FlexibleLocation;
 import org.ofbiz.base.util.Debug;
 import org.ofbiz.base.util.UtilValidate;
 import org.ofbiz.base.util.UtilXml;
 import org.ofbiz.base.util.collections.FlexibleMapAccessor;
-import org.ofbiz.base.util.string.FlexibleStringExpander;
 import org.ofbiz.minilang.MiniLangException;
 import org.ofbiz.minilang.MiniLangRuntimeException;
 import org.ofbiz.minilang.MiniLangValidate;
 import org.ofbiz.minilang.SimpleMethod;
 import org.ofbiz.minilang.ValidationException;
+import org.ofbiz.minilang.artifact.ArtifactInfoContext;
 import org.ofbiz.minilang.method.MethodContext;
 import org.ofbiz.minilang.method.MethodOperation;
 import org.w3c.dom.Element;
 
 /**
- * Invokes a Mini-language simple method.
+ * Implements the &lt;call-simple-method&gt; element.
+ * 
+ * @see <a href="https://cwiki.apache.org/OFBADMIN/mini-language-reference.html#Mini-languageReference-{{%3Ccallsimplemethod%3E}}">Mini-language Reference</a>
  */
 public final class CallSimpleMethod extends MethodOperation {
 
@@ -47,6 +52,7 @@ public final class CallSimpleMethod exte
 
     private final String methodName;
     private final String xmlResource;
+    private final URL xmlURL;
     private final String scope;
     private final List<ResultToField> resultToFieldList;
 
@@ -59,7 +65,18 @@ public final class CallSimpleMethod exte
             MiniLangValidate.childElements(simpleMethod, element, "result-to-field");
         }
         this.methodName = element.getAttribute("method-name");
-        this.xmlResource = element.getAttribute("xml-resource");
+        String xmlResourceAttribute = element.getAttribute("xml-resource");
+        if (xmlResourceAttribute.isEmpty()) {
+            xmlResourceAttribute = simpleMethod.getFromLocation();
+        }
+        this.xmlResource = xmlResourceAttribute;
+        URL xmlURL = null;
+        try {
+            xmlURL = FlexibleLocation.resolveLocation(this.xmlResource);
+        } catch (MalformedURLException e) {
+            MiniLangValidate.handleError("Could not find SimpleMethod XML document in resource: " + this.xmlResource + "; error was: " + e.toString(), simpleMethod, element);
+        }
+        this.xmlURL = xmlURL;
         this.scope = element.getAttribute("scope");
         List<? extends Element> resultToFieldElements = UtilXml.childElementList(element, "result-to-field");
         if (UtilValidate.isNotEmpty(resultToFieldElements)) {
@@ -81,13 +98,7 @@ public final class CallSimpleMethod exte
         if (UtilValidate.isEmpty(this.methodName)) {
             throw new MiniLangRuntimeException("method-name attribute is empty", this);
         }
-        SimpleMethod simpleMethodToCall = null;
-        if (UtilValidate.isEmpty(this.xmlResource)) {
-            simpleMethodToCall = this.simpleMethod.getSimpleMethodInSameFile(methodName);
-        } else {
-            Map<String, SimpleMethod> simpleMethods = SimpleMethod.getSimpleMethods(this.xmlResource, methodContext.getLoader());
-            simpleMethodToCall = simpleMethods.get(this.methodName);
-        }
+        SimpleMethod simpleMethodToCall = SimpleMethod.getSimpleMethod(this.xmlURL, this.methodName);
         if (simpleMethodToCall == null) {
             throw new MiniLangRuntimeException("Could not find <simple-method name=\"" + this.methodName + "\"> in XML document " + this.xmlResource, this);
         }
@@ -140,8 +151,19 @@ public final class CallSimpleMethod exte
     }
 
     @Override
-    public String expandedString(MethodContext methodContext) {
-        return FlexibleStringExpander.expandString(toString(), methodContext.getEnvMap());
+    public void gatherArtifactInfo(ArtifactInfoContext aic) {
+        SimpleMethod simpleMethodToCall;
+        try {
+            simpleMethodToCall = SimpleMethod.getSimpleMethod(this.xmlURL, this.methodName);
+            if (simpleMethodToCall != null) {
+                if (!aic.hasVisited(simpleMethodToCall)) {
+                    aic.addSimpleMethod(simpleMethodToCall);
+                    simpleMethodToCall.gatherArtifactInfo(aic);
+                }
+            }
+        } catch (MiniLangException e) {
+            Debug.logWarning("Could not find <simple-method name=\"" + this.methodName + "\"> in XML document " + this.xmlResource + ": " + e.toString(), module);
+        }
     }
 
     public String getMethodName() {
@@ -149,14 +171,7 @@ public final class CallSimpleMethod exte
     }
 
     public SimpleMethod getSimpleMethodToCall(ClassLoader loader) throws MiniLangException {
-        SimpleMethod simpleMethodToCall = null;
-        if (UtilValidate.isEmpty(xmlResource)) {
-            simpleMethodToCall = this.simpleMethod.getSimpleMethodInSameFile(methodName);
-        } else {
-            Map<String, SimpleMethod> simpleMethods = SimpleMethod.getSimpleMethods(xmlResource, loader);
-            simpleMethodToCall = simpleMethods.get(methodName);
-        }
-        return simpleMethodToCall;
+        return SimpleMethod.getSimpleMethod(xmlResource, methodName, loader);
     }
 
     public String getXmlResource() {
@@ -164,11 +179,6 @@ public final class CallSimpleMethod exte
     }
 
     @Override
-    public String rawString() {
-        return toString();
-    }
-
-    @Override
     public String toString() {
         StringBuilder sb = new StringBuilder("<call-simple-method ");
         if (this.methodName.length() > 0) {
@@ -184,11 +194,16 @@ public final class CallSimpleMethod exte
         return sb.toString();
     }
 
+    /**
+     * A factory for the &lt;call-simple-method&gt; element.
+     */
     public static final class CallSimpleMethodFactory implements Factory<CallSimpleMethod> {
+        @Override
         public CallSimpleMethod createMethodOperation(Element element, SimpleMethod simpleMethod) throws MiniLangException {
             return new CallSimpleMethod(element, simpleMethod);
         }
 
+        @Override
         public String getName() {
             return "call-simple-method";
         }

Modified: ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/callops/FlexibleMessage.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/callops/FlexibleMessage.java?rev=1359626&r1=1359625&r2=1359626&view=diff
==============================================================================
--- ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/callops/FlexibleMessage.java (original)
+++ ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/callops/FlexibleMessage.java Tue Jul 10 12:05:55 2012
@@ -20,10 +20,10 @@ package org.ofbiz.minilang.method.callop
 
 import java.io.Serializable;
 
-import org.ofbiz.base.util.Debug;
 import org.ofbiz.base.util.UtilProperties;
-import org.ofbiz.base.util.UtilValidate;
 import org.ofbiz.base.util.UtilXml;
+import org.ofbiz.base.util.string.FlexibleStringExpander;
+import org.ofbiz.minilang.MiniLangValidate;
 import org.ofbiz.minilang.method.MethodContext;
 import org.w3c.dom.Element;
 
@@ -31,53 +31,36 @@ import org.w3c.dom.Element;
  * Simple class to wrap messages that come either from a straight string or a properties file
  */
 @SuppressWarnings("serial")
-public class FlexibleMessage implements Serializable {
+public final class FlexibleMessage implements Serializable {
 
-    public static final String module = FlexibleMessage.class.getName();
-
-    boolean isProperty = false;
-    String message = null;
-    String propertyResource = null;
+    private final FlexibleStringExpander messageFse;
+    private final String propertykey;
+    private final String propertyResource;
 
     public FlexibleMessage(Element element, String defaultProperty) {
-        String resAttr = null;
-        String propAttr = null;
-        String elVal = null;
         if (element != null) {
-            resAttr = element.getAttribute("resource");
-            propAttr = element.getAttribute("property");
-            elVal = UtilXml.elementValue(element);
-        }
-        if (UtilValidate.isNotEmpty(resAttr)) {
-            propertyResource = resAttr;
-            message = propAttr;
-            isProperty = true;
-        } else if (UtilValidate.isNotEmpty(elVal)) {
-            message = elVal;
-            isProperty = false;
+            String message = UtilXml.elementValue(element);
+            if (message != null) {
+                messageFse = FlexibleStringExpander.getInstance(message);
+                propertykey = null;
+                propertyResource = null;
+            } else {
+                messageFse = null;
+                propertykey = MiniLangValidate.checkAttribute(element.getAttribute("property"), defaultProperty);
+                propertyResource = MiniLangValidate.checkAttribute(element.getAttribute("resource"), "DefaultMessages");
+            }
         } else {
-            // put in default property
+            messageFse = null;
+            propertykey = defaultProperty;
             propertyResource = "DefaultMessages";
-            message = defaultProperty;
-            isProperty = true;
         }
     }
 
     public String getMessage(ClassLoader loader, MethodContext methodContext) {
-        String message = methodContext.expandString(this.message);
-        String propertyResource = methodContext.expandString(this.propertyResource);
-        if (!isProperty && message != null) {
-            return message;
-        } else if (isProperty && propertyResource != null && message != null) {
-            String propMsg = UtilProperties.getMessage(propertyResource, message, methodContext.getEnvMap(), methodContext.getLocale());
-            if (propMsg == null) {
-                return "In Simple Map Processing property message could not be found in resource [" + propertyResource + "] with name [" + message + "]. ";
-            } else {
-                return propMsg;
-            }
+        if (messageFse != null) {
+            return messageFse.expandString(methodContext.getEnvMap());
         } else {
-            Debug.logInfo("[FlexibleMessage.getMessage] No message found, returning empty string", module);
-            return "";
+            return UtilProperties.getMessage(propertyResource, propertykey, methodContext.getEnvMap(), methodContext.getLocale());
         }
     }
 }

Modified: ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/callops/Return.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/callops/Return.java?rev=1359626&r1=1359625&r2=1359626&view=diff
==============================================================================
--- ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/callops/Return.java (original)
+++ ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/callops/Return.java Tue Jul 10 12:05:55 2012
@@ -18,58 +18,66 @@
  *******************************************************************************/
 package org.ofbiz.minilang.method.callops;
 
-import org.ofbiz.base.util.UtilValidate;
+import org.ofbiz.base.util.string.FlexibleStringExpander;
 import org.ofbiz.minilang.MiniLangException;
+import org.ofbiz.minilang.MiniLangValidate;
 import org.ofbiz.minilang.SimpleMethod;
 import org.ofbiz.minilang.method.MethodContext;
 import org.ofbiz.minilang.method.MethodOperation;
 import org.w3c.dom.Element;
 
 /**
- * An event operation that returns the given response code
+ * Implements the &lt;return&gt; element.
+ * 
+ * @see <a href="https://cwiki.apache.org/OFBADMIN/mini-language-reference.html#Mini-languageReference-{{%3Creturn%3E}}">Mini-language Reference</a>
  */
-public class Return extends MethodOperation {
+public final class Return extends MethodOperation {
 
-    String responseCode;
+    private final FlexibleStringExpander responseCodeFse;
 
     public Return(Element element, SimpleMethod simpleMethod) throws MiniLangException {
         super(element, simpleMethod);
-        responseCode = element.getAttribute("response-code");
-        if (UtilValidate.isEmpty(responseCode))
-            responseCode = "success";
+        if (MiniLangValidate.validationOn()) {
+            MiniLangValidate.attributeNames(simpleMethod, element, "response-code");
+            MiniLangValidate.noChildElements(simpleMethod, element);
+        }
+        responseCodeFse = FlexibleStringExpander.getInstance(element.getAttribute("response-code"));
     }
 
     @Override
     public boolean exec(MethodContext methodContext) throws MiniLangException {
-        String responseCode = methodContext.expandString(this.responseCode);
+        String responseCode = responseCodeFse.expandString(methodContext.getEnvMap());
+        if (responseCode.isEmpty()) {
+            responseCode = simpleMethod.getDefaultSuccessCode();
+        }
         if (methodContext.getMethodType() == MethodContext.EVENT) {
             methodContext.putEnv(simpleMethod.getEventResponseCodeName(), responseCode);
-            return false;
-        } else if (methodContext.getMethodType() == MethodContext.SERVICE) {
-            methodContext.putEnv(simpleMethod.getServiceResponseMessageName(), responseCode);
-            return false;
         } else {
-            return false;
+            methodContext.putEnv(simpleMethod.getServiceResponseMessageName(), responseCode);
         }
+        return false;
     }
 
     @Override
-    public String expandedString(MethodContext methodContext) {
-        // TODO: something more than a stub/dummy
-        return this.rawString();
-    }
-
-    @Override
-    public String rawString() {
-        // TODO: something more than the empty tag
-        return "<return/>";
+    public String toString() {
+        StringBuilder sb = new StringBuilder("<return ");
+        if (!"success".equals(responseCodeFse.getOriginal())) {
+            sb.append("response-code=\"").append(responseCodeFse).append("\" ");
+        }
+        sb.append("/>");
+        return sb.toString();
     }
 
+    /**
+     * A factory for the &lt;return&gt; element.
+     */
     public static final class ReturnFactory implements Factory<Return> {
+        @Override
         public Return createMethodOperation(Element element, SimpleMethod simpleMethod) throws MiniLangException {
             return new Return(element, simpleMethod);
         }
 
+        @Override
         public String getName() {
             return "return";
         }

Modified: ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/callops/SetServiceFields.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/callops/SetServiceFields.java?rev=1359626&r1=1359625&r2=1359626&view=diff
==============================================================================
--- ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/callops/SetServiceFields.java (original)
+++ ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/callops/SetServiceFields.java Tue Jul 10 12:05:55 2012
@@ -25,89 +25,125 @@ import javolution.util.FastList;
 import javolution.util.FastMap;
 
 import org.ofbiz.base.util.Debug;
+import org.ofbiz.base.util.collections.FlexibleMapAccessor;
+import org.ofbiz.base.util.string.FlexibleStringExpander;
 import org.ofbiz.minilang.MiniLangException;
+import org.ofbiz.minilang.MiniLangRuntimeException;
+import org.ofbiz.minilang.MiniLangUtil;
+import org.ofbiz.minilang.MiniLangValidate;
 import org.ofbiz.minilang.SimpleMethod;
-import org.ofbiz.minilang.method.ContextAccessor;
+import org.ofbiz.minilang.artifact.ArtifactInfoContext;
 import org.ofbiz.minilang.method.MethodContext;
 import org.ofbiz.minilang.method.MethodOperation;
 import org.ofbiz.service.GenericServiceException;
-import org.ofbiz.service.LocalDispatcher;
 import org.ofbiz.service.ModelService;
 import org.w3c.dom.Element;
 
 /**
- * Sets all Service parameters/attributes in the to-map using the map as a source
+ * Implements the &lt;set-service-fields&gt; element.
+ * 
+ * @see <a href="https://cwiki.apache.org/OFBADMIN/mini-language-reference.html#Mini-languageReference-{{%3Csetservicefields%3E}}">Mini-language Reference</a>
  */
-public class SetServiceFields extends MethodOperation {
+public final class SetServiceFields extends MethodOperation {
 
     public static final String module = SetServiceFields.class.getName();
 
-    ContextAccessor<List<Object>> errorListAcsr;
-    ContextAccessor<Map<String, ? extends Object>> mapAcsr;
-    String serviceName;
-    ContextAccessor<Map<String, Object>> toMapAcsr;
+    // This method is needed only during the v1 to v2 transition
+    private static boolean autoCorrect(Element element) {
+        String errorListAttr = element.getAttribute("error-list-name");
+        if (!errorListAttr.isEmpty()) {
+            element.removeAttribute("error-list-name");
+            return true;
+        }
+        return false;
+    }
+
+    private final FlexibleMapAccessor<Map<String, ? extends Object>> mapFma;
+    private final FlexibleStringExpander serviceNameFse;
+    private final FlexibleMapAccessor<Map<String, Object>> toMapFma;
 
     public SetServiceFields(Element element, SimpleMethod simpleMethod) throws MiniLangException {
         super(element, simpleMethod);
-        serviceName = element.getAttribute("service-name");
-        mapAcsr = new ContextAccessor<Map<String, ? extends Object>>(element.getAttribute("map"), element.getAttribute("map-name"));
-        toMapAcsr = new ContextAccessor<Map<String, Object>>(element.getAttribute("to-map"), element.getAttribute("to-map-name"));
-        errorListAcsr = new ContextAccessor<List<Object>>(element.getAttribute("error-list-name"), "error_list");
+        if (MiniLangValidate.validationOn()) {
+            MiniLangValidate.attributeNames(simpleMethod, element, "service-name", "map", "to-map");
+            MiniLangValidate.requiredAttributes(simpleMethod, element, "service-name", "map", "to-map");
+            MiniLangValidate.constantPlusExpressionAttributes(simpleMethod, element, "service-name");
+            MiniLangValidate.expressionAttributes(simpleMethod, element, "map", "to-map");
+            MiniLangValidate.noChildElements(simpleMethod, element);
+        }
+        boolean elementModified = autoCorrect(element);
+        if (elementModified && MiniLangUtil.autoCorrectOn()) {
+            MiniLangUtil.flagDocumentAsCorrected(element);
+        }
+        serviceNameFse = FlexibleStringExpander.getInstance(element.getAttribute("service-name"));
+        mapFma = FlexibleMapAccessor.getInstance(element.getAttribute("map"));
+        toMapFma = FlexibleMapAccessor.getInstance(element.getAttribute("to-map"));
     }
 
     @Override
     public boolean exec(MethodContext methodContext) throws MiniLangException {
-        List<Object> messages = errorListAcsr.get(methodContext);
-        if (messages == null) {
-            messages = FastList.newInstance();
-            errorListAcsr.put(methodContext, messages);
-        }
-        String serviceName = methodContext.expandString(this.serviceName);
-        Map<String, ? extends Object> fromMap = mapAcsr.get(methodContext);
+        Map<String, ? extends Object> fromMap = mapFma.get(methodContext.getEnvMap());
         if (fromMap == null) {
-            Debug.logWarning("The from map in set-service-field was not found with name: " + mapAcsr, module);
+            if (Debug.verboseOn()) {
+                Debug.logVerbose("The from map in set-service-field was not found with name: " + mapFma, module);
+            }
             return true;
         }
-        Map<String, Object> toMap = toMapAcsr.get(methodContext);
-        if (toMap == null) {
-            toMap = FastMap.newInstance();
-            toMapAcsr.put(methodContext, toMap);
-        }
-        LocalDispatcher dispatcher = methodContext.getDispatcher();
+        String serviceName = serviceNameFse.expandString(methodContext.getEnvMap());
         ModelService modelService = null;
         try {
-            modelService = dispatcher.getDispatchContext().getModelService(serviceName);
+            modelService = methodContext.getDispatcher().getDispatchContext().getModelService(serviceName);
         } catch (GenericServiceException e) {
-            String errMsg = "In set-service-fields could not get service definition for service name [" + serviceName + "]: " + e.toString();
-            Debug.logError(e, errMsg, module);
-            methodContext.setErrorReturn(errMsg, simpleMethod);
-            return false;
+            throw new MiniLangRuntimeException("Could not get service definition for service name \"" + serviceName + "\": " + e.getMessage(), this);
         }
-        toMap.putAll(modelService.makeValid(fromMap, "IN", true, messages, methodContext.getTimeZone(), methodContext.getLocale()));
+        Map<String, Object> toMap = toMapFma.get(methodContext.getEnvMap());
+        if (toMap == null) {
+            toMap = FastMap.newInstance();
+            toMapFma.put(methodContext.getEnvMap(), toMap);
+        }
+        List<Object> errorMessages = FastList.newInstance();
+        Map<String, Object> validAttributes = modelService.makeValid(fromMap, "IN", true, errorMessages, methodContext.getTimeZone(), methodContext.getLocale());
+        if (errorMessages.size() > 0) {
+            for (Object obj : errorMessages) {
+                simpleMethod.addErrorMessage(methodContext, (String) obj);
+            }
+            throw new MiniLangRuntimeException("Errors encountered while setting service attributes for service name \"" + serviceName + "\"", this);
+        }
+        toMap.putAll(validAttributes);
         return true;
     }
 
     @Override
-    public String expandedString(MethodContext methodContext) {
-        // TODO: something more than a stub/dummy
-        return this.rawString();
-    }
-
-    public String getServiceName() {
-        return this.serviceName;
+    public void gatherArtifactInfo(ArtifactInfoContext aic) {
+        aic.addServiceName(this.serviceNameFse.toString());
     }
 
     @Override
-    public String rawString() {
-        // TODO: something more than the empty tag
-        return "<set-service-fields/>";
+    public String toString() {
+        StringBuilder sb = new StringBuilder("<set-service-fields ");
+        if (!this.serviceNameFse.isEmpty()) {
+            sb.append("service-name=\"").append(this.serviceNameFse).append("\" ");
+        }
+        if (!this.mapFma.isEmpty()) {
+            sb.append("map=\"").append(this.mapFma).append("\" ");
+        }
+        if (!this.toMapFma.isEmpty()) {
+            sb.append("to-map=\"").append(this.toMapFma).append("\" ");
+        }
+        sb.append("/>");
+        return sb.toString();
     }
 
+    /**
+     * A factory for the &lt;set-service-fields&gt; element.
+     */
     public static final class SetServiceFieldsFactory implements Factory<SetServiceFields> {
+        @Override
         public SetServiceFields createMethodOperation(Element element, SimpleMethod simpleMethod) throws MiniLangException {
             return new SetServiceFields(element, simpleMethod);
         }
 
+        @Override
         public String getName() {
             return "set-service-fields";
         }

Modified: ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/conditional/CombinedCondition.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/conditional/CombinedCondition.java?rev=1359626&r1=1359625&r2=1359626&view=diff
==============================================================================
--- ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/conditional/CombinedCondition.java (original)
+++ ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/conditional/CombinedCondition.java Tue Jul 10 12:05:55 2012
@@ -18,112 +18,72 @@
  *******************************************************************************/
 package org.ofbiz.minilang.method.conditional;
 
-import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 
-import javolution.util.FastList;
-
 import org.ofbiz.base.util.UtilXml;
+import org.ofbiz.minilang.MiniLangElement;
+import org.ofbiz.minilang.MiniLangException;
+import org.ofbiz.minilang.MiniLangValidate;
 import org.ofbiz.minilang.SimpleMethod;
 import org.ofbiz.minilang.method.MethodContext;
 import org.w3c.dom.Element;
 
 /**
- * Implements generic combining conditions such as or, and, etc.
+ * Implements the &lt;and&gt;, &lt;or&gt;, &lt;not&gt;, and &lt;xor&gt; elements.
+ * 
+ * @see <a href="https://cwiki.apache.org/OFBADMIN/mini-language-reference.html#Mini-languageReference-Conditional%2FLoopingStatements">Mini-language Reference</a>
  */
-public class CombinedCondition implements Conditional {
+public abstract class CombinedCondition extends MiniLangElement implements Conditional {
 
-    public static final int OR = 1;
-    public static final int XOR = 2;
-    public static final int AND = 3;
-    public static final int NOT = 4;
-
-    int conditionType;
-    SimpleMethod simpleMethod;
-    List<Conditional> subConditions = FastList.newInstance();
-
-    public CombinedCondition(Element element, int conditionType, SimpleMethod simpleMethod) {
-        this.simpleMethod = simpleMethod;
-        this.conditionType = conditionType;
-        for (Element subElement : UtilXml.childElementList(element)) {
-            subConditions.add(ConditionalFactory.makeConditional(subElement, simpleMethod));
-        }
-    }
+    protected final List<Conditional> subConditions;
 
-    public boolean checkCondition(MethodContext methodContext) {
-        if (subConditions.size() == 0)
-            return true;
-        Iterator<Conditional> subCondIter = subConditions.iterator();
-        switch (this.conditionType) {
-            case OR:
-                while (subCondIter.hasNext()) {
-                    Conditional subCond = subCondIter.next();
-                    if (subCond.checkCondition(methodContext)) {
-                        return true;
-                    }
-                }
-                return false;
-            case XOR:
-                boolean trueFound = false;
-                while (subCondIter.hasNext()) {
-                    Conditional subCond = subCondIter.next();
-                    if (subCond.checkCondition(methodContext)) {
-                        if (trueFound) {
-                            return false;
-                        } else {
-                            trueFound = true;
-                        }
-                    }
-                }
-                return trueFound;
-            case AND:
-                while (subCondIter.hasNext()) {
-                    Conditional subCond = subCondIter.next();
-                    if (!subCond.checkCondition(methodContext)) {
-                        return false;
-                    }
-                }
-                return true;
-            case NOT:
-                Conditional subCond = subCondIter.next();
-                return !subCond.checkCondition(methodContext);
-            default:
-                return false;
+    public CombinedCondition(Element element, SimpleMethod simpleMethod) throws MiniLangException {
+        super(element, simpleMethod);
+        List<? extends Element> childElements = UtilXml.childElementList(element);
+        if (MiniLangValidate.validationOn() && childElements.isEmpty()) {
+            MiniLangValidate.handleError("No conditional elements.", simpleMethod, element);
+        }
+        List<Conditional> conditionalList = new ArrayList<Conditional>(childElements.size());
+        for (Element conditionalElement : UtilXml.childElementList(element)) {
+            conditionalList.add(ConditionalFactory.makeConditional(conditionalElement, simpleMethod));
         }
+        this.subConditions = Collections.unmodifiableList(conditionalList);
     }
 
-    public void prettyPrint(StringBuilder messageBuffer, MethodContext methodContext) {
+    protected void prettyPrint(StringBuilder messageBuffer, MethodContext methodContext, String combineText) {
         messageBuffer.append("(");
-        Iterator<Conditional> subCondIter = subConditions.iterator();
-        while (subCondIter.hasNext()) {
-            Conditional subCond = subCondIter.next();
+        for (Conditional subCond : subConditions) {
             subCond.prettyPrint(messageBuffer, methodContext);
-            if (subCondIter.hasNext()) {
-                switch (this.conditionType) {
-                    case OR:
-                        messageBuffer.append(" OR ");
-                        break;
-                    case XOR:
-                        messageBuffer.append(" XOR ");
-                        break;
-                    case AND:
-                        messageBuffer.append(" AND ");
-                        break;
-                    case NOT:
-                        messageBuffer.append(" NOT ");
-                        break;
-                    default:
-                        messageBuffer.append("?");
-                }
-            }
+            messageBuffer.append(combineText);
         }
         messageBuffer.append(")");
     }
 
+    /**
+     * A &lt;and&gt; element factory. 
+     */
     public static final class AndConditionFactory extends ConditionalFactory<CombinedCondition> {
         @Override
-        public CombinedCondition createCondition(Element element, SimpleMethod simpleMethod) {
-            return new CombinedCondition(element, AND, simpleMethod);
+        public CombinedCondition createCondition(Element element, SimpleMethod simpleMethod) throws MiniLangException {
+            return new CombinedCondition(element, simpleMethod) {
+                @Override
+                public boolean checkCondition(MethodContext methodContext) throws MiniLangException {
+                    if (subConditions.size() == 0)
+                        return true;
+                    for (Conditional subCond : subConditions) {
+                        if (!subCond.checkCondition(methodContext)) {
+                            return false;
+                        }
+                    }
+                    return true;
+                }
+                @Override
+                public void prettyPrint(StringBuilder messageBuffer, MethodContext methodContext) {
+                    prettyPrint(messageBuffer, methodContext, " AND ");
+                }
+            };
         }
 
         @Override
@@ -132,10 +92,30 @@ public class CombinedCondition implement
         }
     }
 
+    /**
+     * A &lt;not&gt; element factory. 
+     */
     public static final class NotConditionFactory extends ConditionalFactory<CombinedCondition> {
         @Override
-        public CombinedCondition createCondition(Element element, SimpleMethod simpleMethod) {
-            return new CombinedCondition(element, NOT, simpleMethod);
+        public CombinedCondition createCondition(Element element, SimpleMethod simpleMethod) throws MiniLangException {
+            return new CombinedCondition(element, simpleMethod) {
+                @Override
+                public boolean checkCondition(MethodContext methodContext) throws MiniLangException {
+                    if (subConditions.size() == 0)
+                        return true;
+                    Conditional subCond = subConditions.get(0);
+                    return !subCond.checkCondition(methodContext);
+                }
+                @Override
+                public void prettyPrint(StringBuilder messageBuffer, MethodContext methodContext) {
+                    messageBuffer.append("( NOT ");
+                    if (subConditions.size() > 0) {
+                        Conditional subCond = subConditions.get(0);
+                        subCond.prettyPrint(messageBuffer, methodContext);
+                    }
+                    messageBuffer.append(")");
+                }
+            };
         }
 
         @Override
@@ -144,10 +124,29 @@ public class CombinedCondition implement
         }
     }
 
+    /**
+     * A &lt;or&gt; element factory. 
+     */
     public static final class OrConditionFactory extends ConditionalFactory<CombinedCondition> {
         @Override
-        public CombinedCondition createCondition(Element element, SimpleMethod simpleMethod) {
-            return new CombinedCondition(element, OR, simpleMethod);
+        public CombinedCondition createCondition(Element element, SimpleMethod simpleMethod) throws MiniLangException {
+            return new CombinedCondition(element, simpleMethod) {
+                @Override
+                public boolean checkCondition(MethodContext methodContext) throws MiniLangException {
+                    if (subConditions.size() == 0)
+                        return true;
+                    for (Conditional subCond : subConditions) {
+                        if (subCond.checkCondition(methodContext)) {
+                            return true;
+                        }
+                    }
+                    return false;
+                }
+                @Override
+                public void prettyPrint(StringBuilder messageBuffer, MethodContext methodContext) {
+                    prettyPrint(messageBuffer, methodContext, " OR ");
+                }
+            };
         }
 
         @Override
@@ -156,10 +155,34 @@ public class CombinedCondition implement
         }
     }
 
+    /**
+     * A &lt;xor&gt; element factory. 
+     */
     public static final class XorConditionFactory extends ConditionalFactory<CombinedCondition> {
         @Override
-        public CombinedCondition createCondition(Element element, SimpleMethod simpleMethod) {
-            return new CombinedCondition(element, XOR, simpleMethod);
+        public CombinedCondition createCondition(Element element, SimpleMethod simpleMethod) throws MiniLangException {
+            return new CombinedCondition(element, simpleMethod) {
+                @Override
+                public boolean checkCondition(MethodContext methodContext) throws MiniLangException {
+                    if (subConditions.size() == 0)
+                        return true;
+                    boolean trueFound = false;
+                    for (Conditional subCond : subConditions) {
+                        if (subCond.checkCondition(methodContext)) {
+                            if (trueFound) {
+                                return false;
+                            } else {
+                                trueFound = true;
+                            }
+                        }
+                    }
+                    return trueFound;
+                }
+                @Override
+                public void prettyPrint(StringBuilder messageBuffer, MethodContext methodContext) {
+                    prettyPrint(messageBuffer, methodContext, " XOR ");
+                }
+            };
         }
 
         @Override

Copied: ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/conditional/Compare.java (from r1338212, ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/conditional/Compare.java)
URL: http://svn.apache.org/viewvc/ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/conditional/Compare.java?p2=ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/conditional/Compare.java&p1=ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/conditional/Compare.java&r1=1338212&r2=1359626&rev=1359626&view=diff
==============================================================================
--- ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/conditional/Compare.java (original)
+++ ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/conditional/Compare.java Tue Jul 10 12:05:55 2012
@@ -28,7 +28,7 @@ import java.util.Map;
 import java.util.TimeZone;
 
 import org.ofbiz.base.util.Assert;
-import org.ofbiz.base.util.UtilValidate;
+import org.ofbiz.base.util.ObjectType;
 import org.ofbiz.entity.GenericEntity;
 import org.ofbiz.minilang.MiniLangUtil;
 
@@ -79,7 +79,7 @@ public abstract class Compare {
      * Returns a <code>Compare</code> instance for the specified operator.
      * 
      * @param operator
-     * @return
+     * @return A <code>Compare</code> instance for the specified operator
      */
     public static Compare getInstance(String operator) {
         Assert.notNull("operator", operator);
@@ -95,7 +95,7 @@ public abstract class Compare {
      * @param format Optional format to be used in object type conversions
      * @param locale Optional locale to be used in object type conversions
      * @param timeZone Optional time zone to be used in object type conversions
-     * @return
+     * @return The result of this comparison
      * @throws Exception
      */
     public abstract boolean doCompare(Object lValue, Object rValue, Class<?> type, Locale locale, TimeZone timeZone, String format) throws Exception;
@@ -200,7 +200,7 @@ public abstract class Compare {
         @Override
         public boolean doCompare(Object lValue, Object rValue, Class<?> type, Locale locale, TimeZone timeZone, String format) throws Exception {
             Object convertedLvalue = MiniLangUtil.convertType(lValue, type, locale, timeZone, format);
-            return UtilValidate.isEmpty(convertedLvalue);
+            return ObjectType.isEmpty(convertedLvalue);
         }
     }
 

Modified: ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/conditional/CompareCondition.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/conditional/CompareCondition.java?rev=1359626&r1=1359625&r2=1359626&view=diff
==============================================================================
--- ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/conditional/CompareCondition.java (original)
+++ ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/conditional/CompareCondition.java Tue Jul 10 12:05:55 2012
@@ -18,112 +18,142 @@
  *******************************************************************************/
 package org.ofbiz.minilang.method.conditional;
 
+import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 
-import javolution.util.FastList;
-
-import org.ofbiz.base.util.Debug;
+import org.ofbiz.base.util.ObjectType;
 import org.ofbiz.base.util.UtilValidate;
+import org.ofbiz.base.util.UtilXml;
+import org.ofbiz.base.util.collections.FlexibleMapAccessor;
+import org.ofbiz.base.util.string.FlexibleStringExpander;
+import org.ofbiz.minilang.MiniLangException;
+import org.ofbiz.minilang.MiniLangRuntimeException;
+import org.ofbiz.minilang.MiniLangUtil;
+import org.ofbiz.minilang.MiniLangValidate;
 import org.ofbiz.minilang.SimpleMethod;
-import org.ofbiz.minilang.method.ContextAccessor;
+import org.ofbiz.minilang.artifact.ArtifactInfoContext;
 import org.ofbiz.minilang.method.MethodContext;
-import org.ofbiz.minilang.operation.BaseCompare;
+import org.ofbiz.minilang.method.MethodOperation;
 import org.w3c.dom.Element;
 
 /**
- * Implements compare to a constant condition.
+ * Implements the &lt;if-compare&gt; element.
+ * 
+ * @see <a href="https://cwiki.apache.org/OFBADMIN/mini-language-reference.html#Mini-languageReference-{{%3Cifcompare%3E}}">Mini-language Reference</a>
  */
-public class CompareCondition implements Conditional {
-
-    public static final String module = CompareCondition.class.getName();
+public final class CompareCondition extends MethodOperation implements Conditional {
 
-    ContextAccessor<Object> fieldAcsr;
-    String format;
-    ContextAccessor<Map<String, ? extends Object>> mapAcsr;
-    String operator;
-    SimpleMethod simpleMethod;
-    String type;
-    String value;
-
-    public CompareCondition(Element element, SimpleMethod simpleMethod) {
-        this.simpleMethod = simpleMethod;
-        // NOTE: this is still supported, but is deprecated
-        this.mapAcsr = new ContextAccessor<Map<String, ? extends Object>>(element.getAttribute("map-name"));
-        this.fieldAcsr = new ContextAccessor<Object>(element.getAttribute("field"));
-        if (this.fieldAcsr.isEmpty()) {
-            // NOTE: this is still supported, but is deprecated
-            this.fieldAcsr = new ContextAccessor<Object>(element.getAttribute("field-name"));
+    private final Compare compare;
+    private final FlexibleMapAccessor<Object> fieldFma;
+    private final FlexibleStringExpander formatFse;
+    private final String operator;
+    private final Class<?> targetClass;
+    private final String type;
+    private final FlexibleStringExpander valueFse;
+    // Sub-operations are used only when this is a method operation.
+    private final List<MethodOperation> elseSubOps;
+    private final List<MethodOperation> subOps;
+
+    public CompareCondition(Element element, SimpleMethod simpleMethod) throws MiniLangException {
+        super(element, simpleMethod);
+        if (MiniLangValidate.validationOn()) {
+            MiniLangValidate.attributeNames(simpleMethod, element, "field", "format", "operator", "type", "value");
+            MiniLangValidate.requiredAttributes(simpleMethod, element, "field", "operator", "value");
+            MiniLangValidate.constantAttributes(simpleMethod, element, "operator", "type");
+            MiniLangValidate.constantPlusExpressionAttributes(simpleMethod, element, "value");
+            MiniLangValidate.expressionAttributes(simpleMethod, element, "field");
         }
-        this.value = element.getAttribute("value");
+        this.fieldFma = FlexibleMapAccessor.getInstance(element.getAttribute("field"));
+        this.formatFse = FlexibleStringExpander.getInstance(element.getAttribute("format"));
         this.operator = element.getAttribute("operator");
+        this.compare = Compare.getInstance(this.operator);
+        if (this.compare == null) {
+            MiniLangValidate.handleError("Invalid operator " + this.operator, simpleMethod, element);
+        }
         this.type = element.getAttribute("type");
-        this.format = element.getAttribute("format");
-    }
-
-    public boolean checkCondition(MethodContext methodContext) {
-        String value = methodContext.expandString(this.value);
-        String operator = methodContext.expandString(this.operator);
-        String type = methodContext.expandString(this.type);
-        String format = methodContext.expandString(this.format);
-        Object fieldVal = getFieldVal(methodContext);
-        List<Object> messages = FastList.newInstance();
-        Boolean resultBool = BaseCompare.doRealCompare(fieldVal, value, operator, type, format, messages, null, methodContext.getLoader(), true);
-        if (messages.size() > 0) {
-            messages.add(0, "Error with comparison in if-compare between field [" + mapAcsr.toString() + "." + fieldAcsr.toString() + "] with value [" + fieldVal + "] and value [" + value + "] with operator [" + operator + "] and type [" + type + "]: ");
-            if (methodContext.getMethodType() == MethodContext.EVENT) {
-                StringBuilder fullString = new StringBuilder();
-
-                for (Object message : messages) {
-                    fullString.append(message);
+        Class<?> targetClass = null;
+        if (!this.type.isEmpty()) {
+            if ("contains".equals(this.operator)) {
+                MiniLangValidate.handleError("Operator \"contains\" does not support type conversions (remove the type attribute).", simpleMethod, element);
+                targetClass = Object.class;
+            } else {
+                try {
+                    targetClass = ObjectType.loadClass(this.type);
+                } catch (ClassNotFoundException e) {
+                    MiniLangValidate.handleError("Invalid type " + this.type, simpleMethod, element);
                 }
-                Debug.logWarning(fullString.toString(), module);
-                methodContext.putEnv(simpleMethod.getEventErrorMessageName(), fullString.toString());
-                methodContext.putEnv(simpleMethod.getEventResponseCodeName(), simpleMethod.getDefaultErrorCode());
-            } else if (methodContext.getMethodType() == MethodContext.SERVICE) {
-                methodContext.putEnv(simpleMethod.getServiceErrorMessageListName(), messages);
-                methodContext.putEnv(simpleMethod.getServiceResponseMessageName(), simpleMethod.getDefaultErrorCode());
             }
-            return false;
         }
-        if (resultBool != null)
-            return resultBool.booleanValue();
+        this.targetClass = targetClass;
+        this.valueFse = FlexibleStringExpander.getInstance(element.getAttribute("value"));
+        Element childElement = UtilXml.firstChildElement(element);
+        if (childElement != null && !"else".equals(childElement.getTagName())) {
+            this.subOps = Collections.unmodifiableList(SimpleMethod.readOperations(element, simpleMethod));
+        } else {
+            this.subOps = null;
+        }
+        Element elseElement = UtilXml.firstChildElement(element, "else");
+        if (elseElement != null) {
+            this.elseSubOps = Collections.unmodifiableList(SimpleMethod.readOperations(elseElement, simpleMethod));
+        } else {
+            this.elseSubOps = null;
+        }
+    }
+
+    @Override
+    public boolean checkCondition(MethodContext methodContext) throws MiniLangException {
+        if (this.compare == null) {
+            throw new MiniLangRuntimeException("Invalid operator \"" + this.operator + "\"", this);
+        }
+        Object fieldVal = fieldFma.get(methodContext.getEnvMap());
+        Class<?> targetClass = this.targetClass;
+        if (targetClass == null) {
+            targetClass = MiniLangUtil.getObjectClassForConversion(fieldVal);
+        }
+        String value = valueFse.expandString(methodContext.getEnvMap());
+        String format = formatFse.expandString(methodContext.getEnvMap());
+        try {
+            return this.compare.doCompare(fieldVal, value, targetClass, methodContext.getLocale(), methodContext.getTimeZone(), format);
+        } catch (Exception e) {
+            simpleMethod.addErrorMessage(methodContext, e.getMessage());
+        }
         return false;
     }
 
-    protected Object getFieldVal(MethodContext methodContext) {
-        Object fieldVal = null;
-        if (!mapAcsr.isEmpty()) {
-            Map<String, ? extends Object> fromMap = mapAcsr.get(methodContext);
-            if (fromMap == null) {
-                if (Debug.infoOn())
-                    Debug.logInfo("Map not found with name " + mapAcsr + ", using empty string for comparison", module);
-            } else {
-                fieldVal = fieldAcsr.get(fromMap, methodContext);
+    @Override
+    public boolean exec(MethodContext methodContext) throws MiniLangException {
+        if (checkCondition(methodContext)) {
+            if (this.subOps != null) {
+                return SimpleMethod.runSubOps(subOps, methodContext);
             }
         } else {
-            // no map name, try the env
-            fieldVal = fieldAcsr.get(methodContext);
+            if (elseSubOps != null) {
+                return SimpleMethod.runSubOps(elseSubOps, methodContext);
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public void gatherArtifactInfo(ArtifactInfoContext aic) {
+        if (this.subOps != null) {
+            for (MethodOperation method : this.subOps) {
+                method.gatherArtifactInfo(aic);
+            }
         }
-        // always use an empty string by default
-        if (fieldVal == null) {
-            fieldVal = "";
+        if (this.elseSubOps != null) {
+            for (MethodOperation method : this.elseSubOps) {
+                method.gatherArtifactInfo(aic);
+            }
         }
-        return fieldVal;
     }
 
     public void prettyPrint(StringBuilder messageBuffer, MethodContext methodContext) {
-        String value = methodContext.expandString(this.value);
-        String operator = methodContext.expandString(this.operator);
-        String type = methodContext.expandString(this.type);
-        String format = methodContext.expandString(this.format);
-        Object fieldVal = getFieldVal(methodContext);
+        String value = valueFse.expandString(methodContext.getEnvMap());
+        String format = formatFse.expandString(methodContext.getEnvMap());
+        Object fieldVal = fieldFma.get(methodContext.getEnvMap());
         messageBuffer.append("[");
-        if (!this.mapAcsr.isEmpty()) {
-            messageBuffer.append(this.mapAcsr);
-            messageBuffer.append(".");
-        }
-        messageBuffer.append(this.fieldAcsr);
+        messageBuffer.append(this.fieldFma);
         messageBuffer.append("=");
         messageBuffer.append(fieldVal);
         messageBuffer.append("] ");
@@ -138,9 +168,33 @@ public class CompareCondition implements
         }
     }
 
-    public static final class CompareConditionFactory extends ConditionalFactory<CompareCondition> {
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder("<if-compare ");
+        sb.append("field=\"").append(this.fieldFma).append("\" operator=\"").append(operator).append("\" ");
+        if (!this.valueFse.isEmpty()) {
+            sb.append("value=\"").append(this.valueFse).append("\" ");
+        }
+        if (!this.type.isEmpty()) {
+            sb.append("type=\"").append(this.type).append("\" ");
+        }
+        if (!this.formatFse.isEmpty()) {
+            sb.append("format=\"").append(this.formatFse).append("\" ");
+        }
+        sb.append("/>");
+        return sb.toString();
+    }
+
+    /**
+     * A &lt;if-compare&gt; element factory. 
+     */
+    public static final class CompareConditionFactory extends ConditionalFactory<CompareCondition> implements Factory<CompareCondition> {
         @Override
-        public CompareCondition createCondition(Element element, SimpleMethod simpleMethod) {
+        public CompareCondition createCondition(Element element, SimpleMethod simpleMethod) throws MiniLangException {
+            return new CompareCondition(element, simpleMethod);
+        }
+
+        public CompareCondition createMethodOperation(Element element, SimpleMethod simpleMethod) throws MiniLangException {
             return new CompareCondition(element, simpleMethod);
         }
 

Modified: ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/conditional/CompareFieldCondition.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/conditional/CompareFieldCondition.java?rev=1359626&r1=1359625&r2=1359626&view=diff
==============================================================================
--- ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/conditional/CompareFieldCondition.java (original)
+++ ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/conditional/CompareFieldCondition.java Tue Jul 10 12:05:55 2012
@@ -18,148 +18,160 @@
  *******************************************************************************/
 package org.ofbiz.minilang.method.conditional;
 
+import java.util.Collections;
 import java.util.List;
-import java.util.Map;
 
-import javolution.util.FastList;
-
-import org.ofbiz.base.util.Debug;
+import org.ofbiz.base.util.ObjectType;
 import org.ofbiz.base.util.UtilValidate;
+import org.ofbiz.base.util.UtilXml;
+import org.ofbiz.base.util.collections.FlexibleMapAccessor;
+import org.ofbiz.base.util.string.FlexibleStringExpander;
+import org.ofbiz.minilang.MiniLangException;
+import org.ofbiz.minilang.MiniLangRuntimeException;
+import org.ofbiz.minilang.MiniLangUtil;
+import org.ofbiz.minilang.MiniLangValidate;
 import org.ofbiz.minilang.SimpleMethod;
-import org.ofbiz.minilang.method.ContextAccessor;
+import org.ofbiz.minilang.artifact.ArtifactInfoContext;
 import org.ofbiz.minilang.method.MethodContext;
-import org.ofbiz.minilang.operation.BaseCompare;
+import org.ofbiz.minilang.method.MethodOperation;
 import org.w3c.dom.Element;
 
 /**
- * Implements compare to a field condition.
+ * Implements the &lt;if-compare-field&gt; element.
+ * 
+ * @see <a href="https://cwiki.apache.org/OFBADMIN/mini-language-reference.html#Mini-languageReference-{{%3Cifcomparefield%3E}}">Mini-language Reference</a>
  */
-public class CompareFieldCondition implements Conditional {
+public final class CompareFieldCondition extends MethodOperation implements Conditional {
 
-    public static final String module = CompareFieldCondition.class.getName();
+    // This method is needed only during the v1 to v2 transition
+    private static boolean autoCorrect(Element element) {
+        // Correct missing to-field attribute
+        String toFieldAttr = element.getAttribute("to-field");
+        if (toFieldAttr.isEmpty()) {
+            element.setAttribute("to-field", element.getAttribute("field"));
+            return true;
+        }
+        return false;
+    }
 
-    ContextAccessor<Object> fieldAcsr;
-    String format;
-    ContextAccessor<Map<String, ? extends Object>> mapAcsr;
-    String operator;
-    SimpleMethod simpleMethod;
-    ContextAccessor<Object> toFieldAcsr;
-    ContextAccessor<Map<String, ? extends Object>> toMapAcsr;
-    String type;
-
-    public CompareFieldCondition(Element element, SimpleMethod simpleMethod) {
-        this.simpleMethod = simpleMethod;
-        // NOTE: this is still supported, but is deprecated
-        this.mapAcsr = new ContextAccessor<Map<String, ? extends Object>>(element.getAttribute("map-name"));
-        this.fieldAcsr = new ContextAccessor<Object>(element.getAttribute("field"));
-        if (this.fieldAcsr.isEmpty()) {
-            // NOTE: this is still supported, but is deprecated
-            this.fieldAcsr = new ContextAccessor<Object>(element.getAttribute("field-name"));
-        }
-        // NOTE: this is still supported, but is deprecated
-        this.toMapAcsr = new ContextAccessor<Map<String, ? extends Object>>(element.getAttribute("to-map-name"));
-        // set fieldAcsr to their default value of fieldAcsr if empty
-        this.toFieldAcsr = new ContextAccessor<Object>(element.getAttribute("to-field"), element.getAttribute("field"));
-        if (this.toFieldAcsr.isEmpty()) {
-            // NOTE: this is still supported, but is deprecated
-            this.toFieldAcsr = new ContextAccessor<Object>(element.getAttribute("to-field-name"), element.getAttribute("field-name"));
-        }
-        // do NOT default the to-map-name to the map-name because that
-        // would make it impossible to compare from a map field to an
-        // environment field
+    private final Compare compare;
+    private final FlexibleMapAccessor<Object> fieldFma;
+    private final FlexibleStringExpander formatFse;
+    private final String operator;
+    private final FlexibleMapAccessor<Object> toFieldFma;
+    private final Class<?> targetClass;
+    private final String type;
+    // Sub-operations are used only when this is a method operation.
+    private final List<MethodOperation> elseSubOps;
+    private final List<MethodOperation> subOps;
+
+    public CompareFieldCondition(Element element, SimpleMethod simpleMethod) throws MiniLangException {
+        super(element, simpleMethod);
+        if (MiniLangValidate.validationOn()) {
+            MiniLangValidate.attributeNames(simpleMethod, element, "field", "format", "operator", "type", "to-field");
+            MiniLangValidate.requiredAttributes(simpleMethod, element, "field", "operator", "to-field");
+            MiniLangValidate.constantAttributes(simpleMethod, element, "operator", "type");
+            MiniLangValidate.constantPlusExpressionAttributes(simpleMethod, element, "format");
+            MiniLangValidate.expressionAttributes(simpleMethod, element, "field", "to-field");
+        }
+        boolean elementModified = autoCorrect(element);
+        if (elementModified && MiniLangUtil.autoCorrectOn()) {
+            MiniLangUtil.flagDocumentAsCorrected(element);
+        }
+        this.fieldFma = FlexibleMapAccessor.getInstance(element.getAttribute("field"));
+        this.formatFse = FlexibleStringExpander.getInstance(element.getAttribute("format"));
         this.operator = element.getAttribute("operator");
+        this.compare = Compare.getInstance(this.operator);
+        if (this.compare == null) {
+            MiniLangValidate.handleError("Invalid operator " + this.operator, simpleMethod, element);
+        }
+        this.toFieldFma = FlexibleMapAccessor.getInstance(element.getAttribute("to-field"));
         this.type = element.getAttribute("type");
-        this.format = element.getAttribute("format");
+        Class<?> targetClass = null;
+        if (!this.type.isEmpty()) {
+            try {
+                targetClass = ObjectType.loadClass(this.type);
+            } catch (ClassNotFoundException e) {
+                MiniLangValidate.handleError("Invalid type " + this.type, simpleMethod, element);
+            }
+        }
+        this.targetClass = targetClass;
+        Element childElement = UtilXml.firstChildElement(element);
+        if (childElement != null && !"else".equals(childElement.getTagName())) {
+            this.subOps = Collections.unmodifiableList(SimpleMethod.readOperations(element, simpleMethod));
+        } else {
+            this.subOps = null;
+        }
+        Element elseElement = UtilXml.firstChildElement(element, "else");
+        if (elseElement != null) {
+            this.elseSubOps = Collections.unmodifiableList(SimpleMethod.readOperations(elseElement, simpleMethod));
+        } else {
+            this.elseSubOps = null;
+        }
     }
 
-    public boolean checkCondition(MethodContext methodContext) {
-        String operator = methodContext.expandString(this.operator);
-        String type = methodContext.expandString(this.type);
-        String format = methodContext.expandString(this.format);
-        Object fieldVal1 = getFieldVal1(methodContext);
-        Object fieldVal2 = getFieldVal2(methodContext);
-        List<Object> messages = FastList.newInstance();
-        Boolean resultBool = BaseCompare.doRealCompare(fieldVal1, fieldVal2, operator, type, format, messages, null, methodContext.getLoader(), false);
-        if (messages.size() > 0) {
-            messages.add(0, "Error with comparison in if-compare-field between fields [" + mapAcsr.toString() + "." + fieldAcsr.toString() + "] with value [" + fieldVal1 + "] and [" + toMapAcsr.toString() + "." + toFieldAcsr.toString() + "] with value [" + fieldVal2 + "] with operator [" + operator
-                    + "] and type [" + type + "]: ");
-            if (methodContext.getMethodType() == MethodContext.EVENT) {
-                StringBuilder fullString = new StringBuilder();
-                for (Object message : messages) {
-                    fullString.append(message);
-                }
-                Debug.logWarning(fullString.toString(), module);
-                methodContext.putEnv(simpleMethod.getEventErrorMessageName(), fullString.toString());
-                methodContext.putEnv(simpleMethod.getEventResponseCodeName(), simpleMethod.getDefaultErrorCode());
-            } else if (methodContext.getMethodType() == MethodContext.SERVICE) {
-                methodContext.putEnv(simpleMethod.getServiceErrorMessageListName(), messages);
-                methodContext.putEnv(simpleMethod.getServiceResponseMessageName(), simpleMethod.getDefaultErrorCode());
-            }
-            return false;
+    @Override
+    public boolean checkCondition(MethodContext methodContext) throws MiniLangException {
+        if (this.compare == null) {
+            throw new MiniLangRuntimeException("Invalid operator " + this.operator, this);
+        }
+        Object fieldVal = fieldFma.get(methodContext.getEnvMap());
+        Object toFieldVal = toFieldFma.get(methodContext.getEnvMap());
+        Class<?> targetClass = this.targetClass;
+        if (targetClass == null) {
+            targetClass = MiniLangUtil.getObjectClassForConversion(fieldVal);
+        }
+        String format = formatFse.expandString(methodContext.getEnvMap());
+        try {
+            return this.compare.doCompare(fieldVal, toFieldVal, targetClass, methodContext.getLocale(), methodContext.getTimeZone(), format);
+        } catch (Exception e) {
+            simpleMethod.addErrorMessage(methodContext, e.getMessage());
         }
-        if (resultBool != null)
-            return resultBool.booleanValue();
         return false;
     }
 
-    protected Object getFieldVal1(MethodContext methodContext) {
-        Object fieldVal1 = null;
-        if (!mapAcsr.isEmpty()) {
-            Map<String, ? extends Object> fromMap = mapAcsr.get(methodContext);
-            if (fromMap == null) {
-                if (Debug.infoOn())
-                    Debug.logInfo("Map not found with name " + mapAcsr + ", using null for comparison", module);
-            } else {
-                fieldVal1 = fieldAcsr.get(fromMap, methodContext);
+    @Override
+    public boolean exec(MethodContext methodContext) throws MiniLangException {
+        if (checkCondition(methodContext)) {
+            if (this.subOps != null) {
+                return SimpleMethod.runSubOps(subOps, methodContext);
             }
         } else {
-            // no map name, try the env
-            fieldVal1 = fieldAcsr.get(methodContext);
+            if (elseSubOps != null) {
+                return SimpleMethod.runSubOps(elseSubOps, methodContext);
+            }
         }
-        return fieldVal1;
+        return true;
     }
 
-    protected Object getFieldVal2(MethodContext methodContext) {
-        Object fieldVal2 = null;
-        if (!toMapAcsr.isEmpty()) {
-            Map<String, ? extends Object> toMap = toMapAcsr.get(methodContext);
-            if (toMap == null) {
-                if (Debug.infoOn())
-                    Debug.logInfo("To Map not found with name " + toMapAcsr + ", using null for comparison", module);
-            } else {
-                fieldVal2 = toFieldAcsr.get(toMap, methodContext);
+    @Override
+    public void gatherArtifactInfo(ArtifactInfoContext aic) {
+        if (this.subOps != null) {
+            for (MethodOperation method : this.subOps) {
+                method.gatherArtifactInfo(aic);
+            }
+        }
+        if (this.elseSubOps != null) {
+            for (MethodOperation method : this.elseSubOps) {
+                method.gatherArtifactInfo(aic);
             }
-        } else {
-            // no map name, try the env
-            fieldVal2 = toFieldAcsr.get(methodContext);
         }
-        return fieldVal2;
     }
 
     public void prettyPrint(StringBuilder messageBuffer, MethodContext methodContext) {
-        String operator = methodContext.expandString(this.operator);
-        String type = methodContext.expandString(this.type);
-        String format = methodContext.expandString(this.format);
-        Object fieldVal1 = getFieldVal1(methodContext);
-        Object fieldVal2 = getFieldVal2(methodContext);
+        String format = formatFse.expandString(methodContext.getEnvMap());
+        Object fieldVal = fieldFma.get(methodContext.getEnvMap());
+        Object toFieldVal = toFieldFma.get(methodContext.getEnvMap());
         messageBuffer.append("[");
-        if (!this.mapAcsr.isEmpty()) {
-            messageBuffer.append(this.mapAcsr);
-            messageBuffer.append(".");
-        }
-        messageBuffer.append(this.fieldAcsr);
+        messageBuffer.append(fieldFma);
         messageBuffer.append("=");
-        messageBuffer.append(fieldVal1);
+        messageBuffer.append(fieldVal);
         messageBuffer.append("] ");
         messageBuffer.append(operator);
         messageBuffer.append(" [");
-        if (!this.toMapAcsr.isEmpty()) {
-            messageBuffer.append(this.toMapAcsr);
-            messageBuffer.append(".");
-        }
-        messageBuffer.append(this.toFieldAcsr);
+        messageBuffer.append(toFieldFma);
         messageBuffer.append("=");
-        messageBuffer.append(fieldVal2);
+        messageBuffer.append(toFieldVal);
         messageBuffer.append("] ");
         messageBuffer.append(" as ");
         messageBuffer.append(type);
@@ -169,9 +181,33 @@ public class CompareFieldCondition imple
         }
     }
 
-    public static final class CompareFieldConditionFactory extends ConditionalFactory<CompareFieldCondition> {
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder("<if-compare-field ");
+        sb.append("field=\"").append(this.fieldFma).append("\" operator=\"").append(operator).append("\" ");
+        if (!this.toFieldFma.isEmpty()) {
+            sb.append("to-field=\"").append(this.toFieldFma).append("\" ");
+        }
+        if (!this.type.isEmpty()) {
+            sb.append("type=\"").append(this.type).append("\" ");
+        }
+        if (!this.formatFse.isEmpty()) {
+            sb.append("format=\"").append(this.formatFse).append("\" ");
+        }
+        sb.append("/>");
+        return sb.toString();
+    }
+
+    /**
+     * A &lt;if-compare-field&gt; element factory. 
+     */
+    public static final class CompareFieldConditionFactory extends ConditionalFactory<CompareFieldCondition> implements Factory<CompareFieldCondition> {
         @Override
-        public CompareFieldCondition createCondition(Element element, SimpleMethod simpleMethod) {
+        public CompareFieldCondition createCondition(Element element, SimpleMethod simpleMethod) throws MiniLangException {
+            return new CompareFieldCondition(element, simpleMethod);
+        }
+
+        public CompareFieldCondition createMethodOperation(Element element, SimpleMethod simpleMethod) throws MiniLangException {
             return new CompareFieldCondition(element, simpleMethod);
         }
 

Modified: ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/conditional/Conditional.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/conditional/Conditional.java?rev=1359626&r1=1359625&r2=1359626&view=diff
==============================================================================
--- ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/conditional/Conditional.java (original)
+++ ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/conditional/Conditional.java Tue Jul 10 12:05:55 2012
@@ -18,14 +18,15 @@
  *******************************************************************************/
 package org.ofbiz.minilang.method.conditional;
 
+import org.ofbiz.minilang.MiniLangException;
 import org.ofbiz.minilang.method.MethodContext;
 
 /**
- * Interface for all conditional elements under the master if element or and else-if element.
+ * Interface for all conditional elements under the &lt;if&gt; element.
  */
 public interface Conditional {
 
-    public boolean checkCondition(MethodContext methodContext);
+    public boolean checkCondition(MethodContext methodContext) throws MiniLangException;
 
     public void prettyPrint(StringBuilder messageBuffer, MethodContext methodContext);
 }

Modified: ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/conditional/ConditionalFactory.java
URL: http://svn.apache.org/viewvc/ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/conditional/ConditionalFactory.java?rev=1359626&r1=1359625&r2=1359626&view=diff
==============================================================================
--- ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/conditional/ConditionalFactory.java (original)
+++ ofbiz/branches/release12.04/framework/minilang/src/org/ofbiz/minilang/method/conditional/ConditionalFactory.java Tue Jul 10 12:05:55 2012
@@ -26,11 +26,15 @@ import java.util.ServiceLoader;
 
 import org.ofbiz.base.util.Debug;
 import org.ofbiz.base.util.UtilGenerics;
+import org.ofbiz.minilang.MiniLangException;
 import org.ofbiz.minilang.SimpleMethod;
 import org.w3c.dom.Element;
 
 /**
- * Creates Conditional objects according to the element that is passed.
+ * An abstract factory class for creating &lt;if&gt; element sub-element implementations.
+ * <p>Mini-language can be extended to support additional condition elements
+ * by extending this class to provide custom conditional element implementations.
+ * </p>
  */
 public abstract class ConditionalFactory<C extends Conditional> {
 
@@ -47,7 +51,7 @@ public abstract class ConditionalFactory
         conditionalFactories = Collections.unmodifiableMap(factories);
     }
 
-    public static Conditional makeConditional(Element element, SimpleMethod simpleMethod) {
+    public static Conditional makeConditional(Element element, SimpleMethod simpleMethod) throws MiniLangException {
         String tagName = element.getTagName();
         ConditionalFactory<?> factory = conditionalFactories.get(tagName);
         if (factory != null) {
@@ -58,7 +62,7 @@ public abstract class ConditionalFactory
         }
     }
 
-    public abstract C createCondition(Element element, SimpleMethod simpleMethod);
+    public abstract C createCondition(Element element, SimpleMethod simpleMethod) throws MiniLangException;
 
     public abstract String getName();
 }