Hi Adrian,

This is blocking trunk demo, please fix or revert

Thanks

Jacques

From: <adri...@apache.org>
Author: adrianc
Date: Thu Apr 26 22:40:22 2012
New Revision: 1331137

URL: http://svn.apache.org/viewvc?rev=1331137&view=rev
Log:
Added new attribute "memory-model" to the Mini-language <call-simple-method> element. Code cleanup and validation in FieldToResult.java. Improved validation in Now.java.

Modified:
   ofbiz/trunk/framework/minilang/dtd/simple-methods-v2.xsd
   
ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/callops/CallSimpleMethod.java
   ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/Now.java
   
ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/serviceops/FieldToResult.java

Modified: ofbiz/trunk/framework/minilang/dtd/simple-methods-v2.xsd
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/minilang/dtd/simple-methods-v2.xsd?rev=1331137&r1=1331136&r2=1331137&view=diff
==============================================================================
--- ofbiz/trunk/framework/minilang/dtd/simple-methods-v2.xsd (original)
+++ ofbiz/trunk/framework/minilang/dtd/simple-methods-v2.xsd Thu Apr 26 
22:40:22 2012
@@ -918,33 +918,64 @@ under the License.
    <xs:element name="call-simple-method" substitutionGroup="CallOperations">
        <xs:annotation>
            <xs:documentation>
-                The call-simple-method tag calls another simple-method in the 
same context as the current one.
-                In other words the called simple-method will have the same 
environment as the calling simple-method,
- including all environment fields, and either the event or service objects that the calling simple-method was called with.
+                Calls another simple-method in the same context as the current 
one.
+                The called simple-method will have the same environment as the 
calling simple-method,
+                including all environment fields, and either the event or 
service objects
+                that the calling simple-method was called
+                with.
            </xs:documentation>
        </xs:annotation>
        <xs:complexType>
-            <xs:attributeGroup ref="attlist.call-simple-method"/>
+            <xs:sequence>
+                <xs:element ref="result-to-field" minOccurs="0" 
maxOccurs="unbounded">
+                    <xs:annotation>
+                        <xs:documentation>
+                            Used when memory-model=&quot;function&quot;. 
Copies the called method fields
+                            to the calling method fields.
+                        </xs:documentation>
+                    </xs:annotation>
+                </xs:element>
+            </xs:sequence>
+            <xs:attribute type="xs:string" name="method-name" use="required">
+                <xs:annotation>
+                    <xs:documentation>
+                        The name of the simple-method to execute in the 
specified xml-resource,
+                        or in the current XML file if no xml-resource is 
specified.
+                        &lt;br/&gt;&lt;br/&gt;
+                        Required. Attribute type: constant.
+                    </xs:documentation>
+                </xs:annotation>
+            </xs:attribute>
+            <xs:attribute type="xs:string" name="xml-resource">
+                <xs:annotation>
+                    <xs:documentation>
+ The full path and filename on the classpath of the XML file which contains an external simple-method to execute.
+                        This is only required if a simple-method in a 
different file is desired.
+                        &lt;br/&gt;&lt;br/&gt;
+                        Optional. Attribute type: constant.
+                    </xs:documentation>
+                </xs:annotation>
+            </xs:attribute>
+            <xs:attribute name="memory-model">
+                <xs:annotation>
+                    <xs:documentation>
+ The memory model to use. In an &quot;inline&quot; memory model, fields declared or modified in the called method + will be reflected back to the calling method - as if the called method was inline. In a &quot;function&quot; memory
+                        model, fields declared or modified in the called 
method are local to the called method - they are not
+                        reflected back to the calling method.
+                        &lt;br/&gt;&lt;br/&gt;
+                        Optional. Attribute type: constant.
+                    </xs:documentation>
+                </xs:annotation>
+                <xs:simpleType>
+                    <xs:restriction base="xs:token">
+                        <xs:enumeration value="inline" />
+                        <xs:enumeration value="function" />
+                    </xs:restriction>
+                </xs:simpleType>
+            </xs:attribute>
        </xs:complexType>
    </xs:element>
-    <xs:attributeGroup name="attlist.call-simple-method">
-        <xs:attribute type="xs:string" name="xml-resource">
-            <xs:annotation>
-                <xs:documentation>
- The full path and filename on the classpath of the XML file which contains an external simple-method to execute.
-                    This is only required if a simple-method in a different 
file is desired.
-                </xs:documentation>
-            </xs:annotation>
-        </xs:attribute>
-        <xs:attribute type="xs:string" name="method-name" use="required">
-            <xs:annotation>
-                <xs:documentation>
-                    The name of the simple-method to execute in the specified 
xml-resource,
-                    or in the current XML file if no xml-resource is specified.
-                </xs:documentation>
-            </xs:annotation>
-        </xs:attribute>
-    </xs:attributeGroup>
    <!-- Operations to call Java methods and create Java objects -->
    <xs:element name="call-object-method" substitutionGroup="CallOperations">
        <xs:annotation>
@@ -1265,26 +1296,43 @@ under the License.
<xs:annotation><xs:documentation>The name of the session attribute to use. Defaults to the value of field attribute</xs:documentation></xs:annotation>
        </xs:attribute>
    </xs:attributeGroup>
-    <!-- Service specific operations -->
-    <xs:element name="field-to-result" substitutionGroup="ServiceOperations">
+    <xs:element name="field-to-result" substitutionGroup="EnvOperations">
        <xs:annotation>
            <xs:documentation>
-                The field-to-result tag copies a field from a map to the 
specified service result field.
-                The tag is only used when the simple-method is called as a 
service, it is ignored otherwise.
+                Copies a field to a service OUT attribute.
            </xs:documentation>
        </xs:annotation>
        <xs:complexType>
-            <xs:attributeGroup ref="attlist.field-to-result"/>
+            <xs:attribute name="field" use="required">
+                <xs:annotation>
+                    <xs:documentation>
+                        The name of the field to copy from. The source of the 
assignment.
+                        &lt;br/&gt;&lt;br/&gt;
+                        Required. Attribute type: expression.
+                    </xs:documentation>
+                </xs:annotation>
+                <xs:simpleType>
+                    <xs:restriction base="xs:string">
+                        <xs:minLength value="1" />
+                    </xs:restriction>
+                </xs:simpleType>
+            </xs:attribute>
+            <xs:attribute name="result-name">
+                <xs:annotation>
+                    <xs:documentation>
+                        The name of the result field to set. The target of the 
assignment.
+                        &lt;br/&gt;&lt;br/&gt;
+                        Optional. Attribute type: expression.
+                    </xs:documentation>
+                </xs:annotation>
+                <xs:simpleType>
+                    <xs:restriction base="xs:string">
+                        <xs:minLength value="1" />
+                    </xs:restriction>
+                </xs:simpleType>
+            </xs:attribute>
        </xs:complexType>
    </xs:element>
-    <xs:attributeGroup name="attlist.field-to-result">
-        <xs:attribute type="xs:string" name="field" use="required">
-            <xs:annotation><xs:documentation>The name (key) of the map field to 
use.</xs:documentation></xs:annotation>
-        </xs:attribute>
-        <xs:attribute type="xs:string" name="result-name">
- <xs:annotation><xs:documentation>The name of the result Map name/key to use. Defaults to the value of field attribute.</xs:documentation></xs:annotation>
-        </xs:attribute>
-    </xs:attributeGroup>
    <!-- Environment specific operations -->
    <xs:element name="map-to-map" substitutionGroup="EnvOperations">
        <xs:annotation>
@@ -4436,6 +4484,8 @@ under the License.
                <xs:annotation>
                    <xs:documentation>
                        The field data type. Defaults to java.sql.Timestamp.
+                        &lt;br/&gt;&lt;br/&gt;
+                        Optional. Attribute type: constant.
                    </xs:documentation>
                </xs:annotation>
                <xs:simpleType>

Modified: 
ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/callops/CallSimpleMethod.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/callops/CallSimpleMethod.java?rev=1331137&r1=1331136&r2=1331137&view=diff
==============================================================================
--- 
ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/callops/CallSimpleMethod.java
 (original)
+++ 
ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/callops/CallSimpleMethod.java
 Thu Apr 26 22:40:22 2012
@@ -18,117 +18,151 @@
 
*******************************************************************************/
package org.ofbiz.minilang.method.callops;

+import java.util.ArrayList;
+import java.util.List;
import java.util.Map;

+import javolution.util.FastMap;
+
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.method.MethodContext;
import org.ofbiz.minilang.method.MethodOperation;
import org.w3c.dom.Element;

/**
- * An operation that calls a simple method in the same, or from another, file
+ * Invokes a Mini-language simple method.
 */
-public class CallSimpleMethod extends MethodOperation {
+public final class CallSimpleMethod extends MethodOperation {

    public static final String module = CallSimpleMethod.class.getName();

-    String methodName;
-    String xmlResource;
+    private final String methodName;
+    private final String xmlResource;
+    private final String memoryModel;
+    private final List<ResultToField> resultToFieldList;

    public CallSimpleMethod(Element element, SimpleMethod simpleMethod) throws 
MiniLangException {
        super(element, simpleMethod);
+        if (MiniLangValidate.validationOn()) {
+            MiniLangValidate.attributeNames(simpleMethod, element, "method-name", 
"xml-resource", "memory-model");
+            MiniLangValidate.requiredAttributes(simpleMethod, element, 
"method-name");
+            MiniLangValidate.constantAttributes(simpleMethod, element, "method-name", 
"xml-resource", "memory-model");
+            MiniLangValidate.childElements(simpleMethod, element, 
"result-to-field");
+        }
        this.methodName = element.getAttribute("method-name");
        this.xmlResource = element.getAttribute("xml-resource");
+        this.memoryModel = element.getAttribute("memory-model");
+        List<? extends Element> resultToFieldElements = 
UtilXml.childElementList(element, "result-to-field");
+        if (UtilValidate.isNotEmpty(resultToFieldElements)) {
+            if (!"function".equals(this.memoryModel)) {
+ MiniLangValidate.handleError("Inline memory model cannot include <result-to-field> elements.", simpleMethod, element);
+            }
+            List<ResultToField> resultToFieldList = new 
ArrayList<ResultToField>(resultToFieldElements.size());
+            for (Element resultToFieldElement : resultToFieldElements) {
+                resultToFieldList.add(new ResultToField(resultToFieldElement, 
simpleMethod));
+            }
+            this.resultToFieldList = resultToFieldList;
+        } else {
+            this.resultToFieldList = null;
+        }
    }

    @Override
    public boolean exec(MethodContext methodContext) throws MiniLangException {
-        if (UtilValidate.isNotEmpty(this.methodName)) {
-            String methodName = methodContext.expandString(this.methodName);
-            String xmlResource = methodContext.expandString(this.xmlResource);
-            SimpleMethod simpleMethodToCall = null;
-            try {
-                simpleMethodToCall = 
getSimpleMethodToCall(methodContext.getLoader());
-            } catch (MiniLangException e) {
- String errMsg = "ERROR: Could not complete the " + simpleMethod.getShortDescription() + " process [error getting methods from resource: " + e.getMessage() + "]";
-                Debug.logError(e, errMsg, module);
-                methodContext.setErrorReturn(errMsg, simpleMethod);
-                return false;
+        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);
+        }
+        if (simpleMethodToCall == null) {
+ throw new MiniLangRuntimeException("Could not find <simple-method name=\"" + this.methodName + "\"> in XML document " + this.xmlResource, this);
+        }
+        MethodContext localContext = methodContext;
+        if ("function".equals(this.memoryModel)) {
+            Map<String, Object> localEnv = FastMap.newInstance();
+            localEnv.putAll(methodContext.getEnvMap());
+            localEnv.remove(this.simpleMethod.getEventResponseCodeName());
+            localEnv.remove(this.simpleMethod.getServiceResponseMessageName());
+            localContext = new MethodContext(localEnv, 
methodContext.getLoader(), methodContext.getMethodType());
+        }
+        String returnVal = simpleMethodToCall.exec(localContext);
+        if (Debug.verboseOn())
+ Debug.logVerbose("Called simple-method named [" + this.methodName + "] in resource [" + this.xmlResource + "], returnVal is [" + returnVal + "]", module);
+        if (simpleMethodToCall.getDefaultErrorCode().equals(returnVal)) {
+            if (methodContext.getMethodType() == MethodContext.EVENT) {
+                methodContext.putEnv(simpleMethod.getEventResponseCodeName(), 
simpleMethod.getDefaultErrorCode());
+            } else if (methodContext.getMethodType() == MethodContext.SERVICE) 
{
+                
methodContext.putEnv(simpleMethod.getServiceResponseMessageName(), 
simpleMethod.getDefaultErrorCode());
            }
-            if (simpleMethodToCall == null) {
- String errMsg = "ERROR: Could not complete the " + simpleMethod.getShortDescription() + " process, could not find SimpleMethod " + methodName + " in XML document in resource: " + xmlResource;
-                methodContext.setErrorReturn(errMsg, simpleMethod);
+            return false;
+        }
+        if (methodContext.getMethodType() == MethodContext.EVENT) {
+            // FIXME: This doesn't make sense. We are comparing the called 
method's response code with this method's
+            // response code. Since response codes are configurable per 
method, this code will fail.
+            String responseCode = (String) 
localContext.getEnv(this.simpleMethod.getEventResponseCodeName());
+            if (this.simpleMethod.getDefaultErrorCode().equals(responseCode)) {
+ Debug.logWarning("Got error [" + responseCode + "] calling inline simple-method named [" + this.methodName + "] in resource [" + this.xmlResource + "], message is " + methodContext.getEnv(this.simpleMethod.getEventErrorMessageName()), module);
                return false;
            }
-            String returnVal = simpleMethodToCall.exec(methodContext);
-            if (Debug.verboseOn())
- Debug.logVerbose("Called inline simple-method named [" + methodName + "] in resource [" + xmlResource + "], returnVal is [" + returnVal + "]", module);
-            if (returnVal != null && 
returnVal.equals(simpleMethodToCall.getDefaultErrorCode())) {
-                // in this case just set the error code just in case it hasn't 
already
-                // been set, the error messages will already be in place...
-                if (methodContext.getMethodType() == MethodContext.EVENT) {
-                    
methodContext.putEnv(simpleMethod.getEventResponseCodeName(), 
simpleMethod.getDefaultErrorCode());
-                } else if (methodContext.getMethodType() == 
MethodContext.SERVICE) {
-                    
methodContext.putEnv(simpleMethod.getServiceResponseMessageName(), 
simpleMethod.getDefaultErrorCode());
-                }
+        } else if (methodContext.getMethodType() == MethodContext.SERVICE) {
+            // FIXME: This doesn't make sense. We are comparing the called 
method's response message with this method's
+            // response message. Since response messages are configurable per 
method, this code will fail.
+            String responseMessage = (String) 
localContext.getEnv(this.simpleMethod.getServiceResponseMessageName());
+            if 
(this.simpleMethod.getDefaultErrorCode().equals(responseMessage)) {
+ Debug.logWarning("Got error [" + responseMessage + "] calling inline simple-method named [" + this.methodName + "] in resource [" + this.xmlResource + "], message is " + methodContext.getEnv(this.simpleMethod.getServiceErrorMessageName()) + ", and the error message list is: "
+                        + 
methodContext.getEnv(this.simpleMethod.getServiceErrorMessageListName()), 
module);
                return false;
            }
-            // if the response code/message is error, if so show the error and 
return
-            // false
-            if (methodContext.getMethodType() == MethodContext.EVENT) {
-                String responseCode = (String) 
methodContext.getEnv(simpleMethod.getEventResponseCodeName());
-                if (responseCode != null && 
responseCode.equals(simpleMethod.getDefaultErrorCode())) {
- Debug.logWarning("Got error [" + responseCode + "] calling inline simple-method named [" + methodName + "] in resource [" + xmlResource + "], message is " + methodContext.getEnv(simpleMethod.getEventErrorMessageName()), module);
-                    return false;
-                }
-            } else if (methodContext.getMethodType() == MethodContext.SERVICE) 
{
-                String resonseMessage = (String) 
methodContext.getEnv(simpleMethod.getServiceResponseMessageName());
-                if (resonseMessage != null && 
resonseMessage.equals(simpleMethod.getDefaultErrorCode())) {
- Debug.logWarning("Got error [" + resonseMessage + "] calling inline simple-method named [" + methodName + "] in resource [" + xmlResource + "], message is " + methodContext.getEnv(simpleMethod.getServiceErrorMessageName()) + ", and the error message list is: "
-                            + 
methodContext.getEnv(simpleMethod.getServiceErrorMessageListName()), module);
-                    return false;
+        }
+        if ("function".equals(this.memoryModel) && this.resultToFieldList != 
null) {
+            Map<String, Object> results = localContext.getResults();
+            if (results != null) {
+                for (ResultToField resultToField : this.resultToFieldList) {
+                    resultToField.exec(methodContext.getEnvMap(), results);
                }
            }
-        } else {
-            String errMsg = "ERROR in call-simple-method: methodName was missing; 
not running simpleMethod";
-            Debug.logError(errMsg, module);
-            methodContext.setErrorReturn(errMsg, simpleMethod);
-            return false;
        }
        return true;
    }

    @Override
    public String expandedString(MethodContext methodContext) {
-        // TODO: something more than a stub/dummy
-        return this.rawString();
+        return FlexibleStringExpander.expandString(toString(), 
methodContext.getEnvMap());
    }

-    public String getMethodName() {
-        return this.methodName;
-    }
-
-    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;
-    }
-
-    public String getXmlResource() {
-        return this.xmlResource;
+    @Override
+    public String rawString() {
+        return toString();
    }

    @Override
-    public String rawString() {
-        return "<call-simple-method xml-resource=\"" + this.xmlResource + "\" method-name=\"" + 
this.methodName + "\" />";
+    public String toString() {
+        StringBuilder sb = new StringBuilder("<call-simple-method ");
+        if (this.methodName.length() > 0) {
+            sb.append("method-name=\"").append(this.methodName).append("\" ");
+        }
+        if (this.xmlResource.length() > 0) {
+            sb.append("xml-resource=\"").append(this.xmlResource).append("\" 
");
+        }
+        if (this.memoryModel.length() > 0) {
+            sb.append("memory-model=\"").append(this.memoryModel).append("\" 
");
+        }
+        sb.append("/>");
+        return sb.toString();
    }

    public static final class CallSimpleMethodFactory implements 
Factory<CallSimpleMethod> {
@@ -140,4 +174,33 @@ public class CallSimpleMethod extends Me
            return "call-simple-method";
        }
    }
+
+    private final class ResultToField {
+
+        private final FlexibleMapAccessor<Object> fieldFma;
+        private final FlexibleMapAccessor<Object> resultNameFma;
+
+        private ResultToField(Element element, SimpleMethod simpleMethod) 
throws ValidationException {
+            if (MiniLangValidate.validationOn()) {
+                MiniLangValidate.attributeNames(simpleMethod, element, "result-name", 
"field");
+                MiniLangValidate.requiredAttributes(simpleMethod, element, 
"result-name");
+                MiniLangValidate.expressionAttributes(simpleMethod, element, 
"result-name", "field");
+                MiniLangValidate.noChildElements(simpleMethod, element);
+            }
+            this.resultNameFma = 
FlexibleMapAccessor.getInstance(element.getAttribute("result-name"));
+            String fieldAttribute = element.getAttribute("field");
+            if (fieldAttribute.length() == 0) {
+                this.fieldFma = this.resultNameFma;
+            } else {
+                this.fieldFma = 
FlexibleMapAccessor.getInstance(fieldAttribute);
+            }
+        }
+
+        private void exec(Map<String, Object> context, Map<String, Object> 
results) throws MiniLangException {
+            Object value = this.resultNameFma.get(results);
+            if (value != null) {
+                this.fieldFma.put(context, value);
+            }
+        }
+    }
}

Modified: 
ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/Now.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/Now.java?rev=1331137&r1=1331136&r2=1331137&view=diff
==============================================================================
--- 
ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/Now.java 
(original)
+++ 
ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/Now.java 
Thu Apr 26 22:40:22 2012
@@ -47,6 +47,8 @@ public final class Now extends MethodOpe
        if (MiniLangValidate.validationOn()) {
            MiniLangValidate.attributeNames(simpleMethod, element, "field", 
"type");
            MiniLangValidate.requiredAttributes(simpleMethod, element, "field");
+            MiniLangValidate.expressionAttributes(simpleMethod, element, 
"field");
+            MiniLangValidate.constantAttributes(simpleMethod, element, "type");
            MiniLangValidate.noChildElements(simpleMethod, element);
        }
        this.fieldFma = 
FlexibleMapAccessor.getInstance(element.getAttribute("field"));

Modified: 
ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/serviceops/FieldToResult.java
URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/serviceops/FieldToResult.java?rev=1331137&r1=1331136&r2=1331137&view=diff
==============================================================================
--- 
ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/serviceops/FieldToResult.java
 (original)
+++ 
ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/serviceops/FieldToResult.java
 Thu Apr 26 22:40:22 2012
@@ -18,70 +18,72 @@
 
*******************************************************************************/
package org.ofbiz.minilang.method.serviceops;

-import java.util.Map;
-
-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.MiniLangValidate;
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.w3c.dom.Element;

/**
- * Copies a map field to a Service result entry
+ * Copies a field to a service OUT attribute.
 */
-public class FieldToResult extends MethodOperation {
+public final class FieldToResult extends MethodOperation {

    public static final String module = FieldToResult.class.getName();

-    ContextAccessor<Object> fieldAcsr;
-    ContextAccessor<Map<String, ? extends Object>> mapAcsr;
-    ContextAccessor<Object> resultAcsr;
+    private final FlexibleMapAccessor<Object> fieldFma;
+    private final FlexibleMapAccessor<Object> resultFma;

    public FieldToResult(Element element, SimpleMethod simpleMethod) throws 
MiniLangException {
        super(element, simpleMethod);
- // the schema for this element now just has the "field" attribute, though the old "field-name" and "map-name" pair is still supported
-        mapAcsr = new ContextAccessor<Map<String, ? extends 
Object>>(element.getAttribute("map-name"));
-        fieldAcsr = new ContextAccessor<Object>(element.getAttribute("field"), 
element.getAttribute("field-name"));
-        resultAcsr = new 
ContextAccessor<Object>(element.getAttribute("result-name"), 
fieldAcsr.toString());
+        if (MiniLangValidate.validationOn()) {
+            MiniLangValidate.attributeNames(simpleMethod, element, "field", 
"result-name");
+            MiniLangValidate.requiredAttributes(simpleMethod, element, 
"field");
+            MiniLangValidate.expressionAttributes(simpleMethod, element, "field", 
"result-name");
+            MiniLangValidate.noChildElements(simpleMethod, element);
+        }
+        this.fieldFma = 
FlexibleMapAccessor.getInstance(element.getAttribute("field"));
+        String resultNameAttribute = element.getAttribute("result-name");
+        if (resultNameAttribute.length() == 0) {
+            this.resultFma = this.fieldFma;
+        } else {
+            this.resultFma = 
FlexibleMapAccessor.getInstance(resultNameAttribute);
+        }
    }

    @Override
    public boolean exec(MethodContext methodContext) throws MiniLangException {
-        // only run this if it is in an SERVICE context
-        if (methodContext.getMethodType() == MethodContext.SERVICE) {
-            Object fieldVal = null;
-            if (!mapAcsr.isEmpty()) {
-                Map<String, ? extends Object> fromMap = 
mapAcsr.get(methodContext);
-                if (fromMap == null) {
-                    Debug.logWarning("Map not found with name " + mapAcsr, 
module);
-                    return true;
-                }
-                fieldVal = fieldAcsr.get(fromMap, methodContext);
-            } else {
-                // no map name, try the env
-                fieldVal = fieldAcsr.get(methodContext);
-            }
-            if (fieldVal == null) {
-                Debug.logWarning("Field value not found with name " + fieldAcsr + " 
in Map with name " + mapAcsr, module);
-                return true;
-            }
-            resultAcsr.put(methodContext.getResults(), fieldVal, 
methodContext);
+        Object fieldVal = this.fieldFma.get(methodContext.getEnvMap());
+        if (fieldVal != null) {
+            this.resultFma.put(methodContext.getResults(), fieldVal);
        }
        return true;
    }

    @Override
    public String expandedString(MethodContext methodContext) {
-        // TODO: something more than a stub/dummy
-        return this.rawString();
+        return FlexibleStringExpander.expandString(toString(), 
methodContext.getEnvMap());
    }

    @Override
    public String rawString() {
-        // TODO: add all attributes and other info
-        return "<field-to-result field-name=\"" + this.fieldAcsr + "\" map-name=\"" + 
this.mapAcsr + "\"/>";
+        return toString();
+    }
+
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder("<now ");
+        if (!this.fieldFma.isEmpty()) {
+            sb.append("field=\"").append(this.fieldFma).append("\" ");
+        }
+        if (!this.resultFma.isEmpty()) {
+            sb.append("result-name=\"").append(this.resultFma).append("\" ");
+        }
+        sb.append("/>");
+        return sb.toString();
    }

    public static final class FieldToResultFactory implements 
Factory<FieldToResult> {


Reply via email to