Author: adrianc
Date: Sun May 6 00:43:58 2012 New Revision: 1334536 URL: http://svn.apache.org/viewvc?rev=1334536&view=rev Log: Overhauled Mini-language <iterate-map>, <loop>, and <while> elements. Modified: ofbiz/trunk/framework/minilang/dtd/simple-methods-v2.xsd ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/conditional/While.java ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/IterateMap.java ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/Loop.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=1334536&r1=1334535&r2=1334536&view=diff ============================================================================== --- ofbiz/trunk/framework/minilang/dtd/simple-methods-v2.xsd (original) +++ ofbiz/trunk/framework/minilang/dtd/simple-methods-v2.xsd Sun May 6 00:43:58 2012 @@ -3415,19 +3415,19 @@ under the License. </xs:annotation> <xs:complexType> <xs:group minOccurs="0" maxOccurs="unbounded" ref="AllOperations" /> - <xs:attribute type="xs:string" name="entry" use="required"> + <xs:attribute type="xs:string" name="list" use="required"> <xs:annotation> <xs:documentation> - The name of the environment field that will contain each entry in the list. + The name of the environment field that contains the list to iterate over. <br/><br/> Required. Attribute type: expression. </xs:documentation> </xs:annotation> </xs:attribute> - <xs:attribute type="xs:string" name="list" use="required"> + <xs:attribute type="xs:string" name="entry" use="required"> <xs:annotation> <xs:documentation> - The name of the environment field that contains the list to iterate over. + The name of the environment field that will contain each entry in the list. <br/><br/> Required. Attribute type: expression. </xs:documentation> @@ -3438,77 +3438,84 @@ under the License. <xs:element name="iterate-map" substitutionGroup="ControlOperations"> <xs:annotation> <xs:documentation> - The operations contained by the iterate-map tag will be executed for each of the entries in the map. - It will run all of the operations underneath the iterate-map-element for each of the entries in the given map, - setting the key for that entry and the key name variable, and the value for that entry and the value variable. - - This tag can contain any of the simple-method operations, including the conditional/if operations. - - Any simple-method operation can be nested under the iterate-map tag. + The operations contained in the iterate-map element will be executed for each of the entries in the list, + and will make the current entry key/value pair available in the environment by the names specified. </xs:documentation> </xs:annotation> <xs:complexType> - <xs:group minOccurs="0" maxOccurs="unbounded" ref="AllOperations"/> - <xs:attributeGroup ref="attlist.iterate-map"/> + <xs:group minOccurs="0" maxOccurs="unbounded" ref="AllOperations" /> + <xs:attribute type="xs:string" name="map" use="required"> + <xs:annotation> + <xs:documentation> + The name of the environment field that contains the map to iterate over. + <br/><br/> + Required. Attribute type: expression. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="key" use="required"> + <xs:annotation> + <xs:documentation> + The name of the environment field that will contain the map entry key. + <br/><br/> + Required. Attribute type: expression. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="value" use="required"> + <xs:annotation> + <xs:documentation> + The name of the environment field that will contain the map entry value. + <br/><br/> + Required. Attribute type: expression. + </xs:documentation> + </xs:annotation> + </xs:attribute> </xs:complexType> </xs:element> - <xs:attributeGroup name="attlist.iterate-map"> - <xs:attribute type="xs:string" name="key" use="required"> - <xs:annotation> - <xs:documentation> - Name of the variable to put the key. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="xs:string" name="value" use="required"> - <xs:annotation> - <xs:documentation> - Name of the variable to put the value in. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="xs:string" name="map" use="required"> - <xs:annotation> - <xs:documentation> - Name of the map to use. - </xs:documentation> - </xs:annotation> - </xs:attribute> - </xs:attributeGroup> <xs:element name="loop" substitutionGroup="ControlOperations"> <xs:annotation> <xs:documentation> - Loop, rather than iterating over some sort of a structure, - will simply loop a certain number of times. The - number of times to loop is specified in the count attribute, - and it will put the current count in the field attribute, - or in the variable named by the field attribute. So if you - want to loop ten times you say count=ten, and - field=count for example. First time through count will - be zero; last time through count will be nine. + The operations contained in the loop element will be executed repeatedly until the specified count is reached. + The current count value is available in the environment by the name specified. </xs:documentation> </xs:annotation> <xs:complexType> - <xs:group minOccurs="0" maxOccurs="unbounded" ref="AllOperations"/> - <xs:attributeGroup ref="attlist.loop"/> + <xs:group minOccurs="0" maxOccurs="unbounded" ref="AllOperations" /> + <xs:attribute type="xs:string" name="count" use="required"> + <xs:annotation> + <xs:documentation> + The number of times to loop. + <br/><br/> + Required. Attribute types: constant, expression. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="field"> + <xs:annotation> + <xs:documentation> + The name of the environment field that will contain the current count. + <br/><br/> + Optional. Attribute type: expression. + </xs:documentation> + </xs:annotation> + </xs:attribute> + </xs:complexType> + </xs:element> + <xs:element name="while" substitutionGroup="ControlOperations"> + <xs:annotation> + <xs:documentation> + The operations contained in the while element will be executed as long as its condition element + evaluates to true. + </xs:documentation> + </xs:annotation> + <xs:complexType> + <xs:sequence> + <xs:element ref="condition" /> + <xs:element ref="then" /> + </xs:sequence> </xs:complexType> </xs:element> - <xs:attributeGroup name="attlist.loop"> - <xs:attribute type="xs:string" name="count" use="required"> - <xs:annotation> - <xs:documentation> - Number of times to loop. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="xs:string" name="field" use="optional"> - <xs:annotation> - <xs:documentation> - Current count is put in the field attribute. - </xs:documentation> - </xs:annotation> - </xs:attribute> - </xs:attributeGroup> <xs:element name="check-errors" substitutionGroup="ControlOperations"> <xs:annotation> <xs:documentation> @@ -3682,34 +3689,6 @@ under the License. </xs:sequence> </xs:complexType> </xs:element> - <xs:element name="while" substitutionGroup="IfOtherOperations"> - <xs:annotation> - <xs:documentation> - While loop operation, uses the same condition element as the if operation. - </xs:documentation> - </xs:annotation> - <xs:complexType> - <xs:sequence> - <xs:element ref="condition"> - <xs:annotation> - <xs:documentation> - A simple element with no attributes that contains the condition that will be evaluated to determine which sub-operations to execute. - To combine the other if operations documented below the and, or, xor, and notelements can be used. - The and, or, and xor elements can contain as many general if operations and modifier/combination elements (ie and, or, xor, and not). - </xs:documentation> - </xs:annotation> - </xs:element> - <xs:element ref="then"> - <xs:annotation> - <xs:documentation> - The then element is used to contain operations that will run if the condition evaluate to true. - A then tag must be included, but can be empty. - </xs:documentation> - </xs:annotation> - </xs:element> - </xs:sequence> - </xs:complexType> - </xs:element> <xs:element name="condition"> <xs:annotation> <xs:documentation> Modified: ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/conditional/While.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/conditional/While.java?rev=1334536&r1=1334535&r2=1334536&view=diff ============================================================================== --- ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/conditional/While.java (original) +++ ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/conditional/While.java Sun May 6 00:43:58 2012 @@ -23,6 +23,7 @@ import java.util.List; import org.ofbiz.base.util.UtilXml; 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; @@ -33,13 +34,17 @@ import org.w3c.dom.Element; /** * Continually processes sub-ops while the condition remains true */ -public class While extends MethodOperation { +public final class While extends MethodOperation { - Conditional condition; - List<MethodOperation> thenSubOps; + private final Conditional condition; + private final List<MethodOperation> thenSubOps; public While(Element element, SimpleMethod simpleMethod) throws MiniLangException { super(element, simpleMethod); + if (MiniLangValidate.validationOn()) { + MiniLangValidate.childElements(simpleMethod, element, "condition", "then"); + MiniLangValidate.requiredChildElements(simpleMethod, element, "condition", "then"); + } Element conditionElement = UtilXml.firstChildElement(element, "condition"); Element conditionChildElement = UtilXml.firstChildElement(conditionElement); this.condition = ConditionalFactory.makeConditional(conditionChildElement, simpleMethod); @@ -49,9 +54,6 @@ public class While extends MethodOperati @Override public boolean exec(MethodContext methodContext) throws MiniLangException { - // if conditions fails, always return true; - // if a sub-op returns false return false and stop, otherwise drop though loop and - // return true while (condition.checkCondition(methodContext)) { try { for (MethodOperation methodOperation : thenSubOps) { Modified: ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/IterateMap.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/IterateMap.java?rev=1334536&r1=1334535&r2=1334536&view=diff ============================================================================== --- ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/IterateMap.java (original) +++ ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/IterateMap.java Sun May 6 00:43:58 2012 @@ -23,9 +23,12 @@ import java.util.List; 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.MiniLangRuntimeException; +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.ofbiz.minilang.method.envops.Break.BreakElementException; @@ -35,51 +38,57 @@ import org.w3c.dom.Element; /** * Process sub-operations for each entry in the map */ -public class IterateMap extends MethodOperation { +public final class IterateMap extends MethodOperation { public static final String module = IterateMap.class.getName(); - ContextAccessor<Object> keyAcsr; - ContextAccessor<Map<? extends Object, ? extends Object>> mapAcsr; - List<MethodOperation> subOps; - ContextAccessor<Object> valueAcsr; + private final FlexibleMapAccessor<Object> keyFma; + private final FlexibleMapAccessor<Map<? extends Object, ? extends Object>> mapFma; + private final List<MethodOperation> subOps; + private final FlexibleMapAccessor<Object> valueFma; public IterateMap(Element element, SimpleMethod simpleMethod) throws MiniLangException { super(element, simpleMethod); - this.keyAcsr = new ContextAccessor<Object>(element.getAttribute("key"), element.getAttribute("key-name")); - this.valueAcsr = new ContextAccessor<Object>(element.getAttribute("value"), element.getAttribute("value-name")); - this.mapAcsr = new ContextAccessor<Map<? extends Object, ? extends Object>>(element.getAttribute("map"), element.getAttribute("map-name")); + if (MiniLangValidate.validationOn()) { + MiniLangValidate.attributeNames(simpleMethod, element, "key", "map", "value"); + MiniLangValidate.requiredAttributes(simpleMethod, element, "key", "map", "value"); + MiniLangValidate.expressionAttributes(simpleMethod, element, "key", "map", "value"); + } + this.keyFma = FlexibleMapAccessor.getInstance(element.getAttribute("key")); + this.mapFma = FlexibleMapAccessor.getInstance(element.getAttribute("map")); + this.valueFma = FlexibleMapAccessor.getInstance(element.getAttribute("value")); this.subOps = Collections.unmodifiableList(SimpleMethod.readOperations(element, simpleMethod)); } @Override public boolean exec(MethodContext methodContext) throws MiniLangException { - if (mapAcsr.isEmpty()) { - Debug.logWarning("No map-name specified in iterate tag, doing nothing: " + rawString(), module); - return true; + if (mapFma.isEmpty()) { + throw new MiniLangRuntimeException("No map specified.", this); } - Object oldKey = keyAcsr.get(methodContext); - Object oldValue = valueAcsr.get(methodContext); + Object oldKey = keyFma.get(methodContext.getEnvMap()); + Object oldValue = valueFma.get(methodContext.getEnvMap()); if (oldKey != null) { - Debug.logWarning("In iterate-map the key had a non-null value before entering the loop for the operation: " + this.rawString(), module); + if (Debug.verboseOn()) + Debug.logVerbose("In iterate-map the key had a non-null value before entering the loop for the operation: " + this, module); } if (oldValue != null) { - Debug.logWarning("In iterate-map the value had a non-null value before entering the loop for the operation: " + this.rawString(), module); + if (Debug.verboseOn()) + Debug.logVerbose("In iterate-map the value had a non-null value before entering the loop for the operation: " + this, module); } - Map<? extends Object, ? extends Object> theMap = mapAcsr.get(methodContext); + Map<? extends Object, ? extends Object> theMap = mapFma.get(methodContext.getEnvMap()); if (theMap == null) { - if (Debug.infoOn()) - Debug.logInfo("Map not found with name " + mapAcsr + ", doing nothing: " + rawString(), module); + if (Debug.verboseOn()) + Debug.logVerbose("Map not found with name " + mapFma + ", doing nothing: " + this, module); return true; } if (theMap.size() == 0) { if (Debug.verboseOn()) - Debug.logVerbose("Map with name " + mapAcsr + " has zero entries, doing nothing: " + rawString(), module); + Debug.logVerbose("Map with name " + mapFma + " has zero entries, doing nothing: " + this, module); return true; } for (Map.Entry<? extends Object, ? extends Object> theEntry : theMap.entrySet()) { - keyAcsr.put(methodContext, theEntry.getKey()); - valueAcsr.put(methodContext, theEntry.getValue()); + keyFma.put(methodContext.getEnvMap(), theEntry.getKey()); + valueFma.put(methodContext.getEnvMap(), theEntry.getValue()); try { for (MethodOperation methodOperation : subOps) { if (!methodOperation.exec(methodContext)) { @@ -101,8 +110,7 @@ public class IterateMap extends MethodOp @Override public String expandedString(MethodContext methodContext) { - // TODO: something more than a stub/dummy - return this.rawString(); + return FlexibleStringExpander.expandString(toString(), methodContext.getEnvMap()); } public List<MethodOperation> getSubOps() { @@ -111,7 +119,23 @@ public class IterateMap extends MethodOp @Override public String rawString() { - return "<iterate-map map-name=\"" + this.mapAcsr + "\" key=\"" + this.keyAcsr + "\" value=\"" + this.valueAcsr + "\"/>"; + return toString(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("<iterate-map "); + if (!this.mapFma.isEmpty()) { + sb.append("map=\"").append(this.mapFma).append("\" "); + } + if (!this.keyFma.isEmpty()) { + sb.append("key=\"").append(this.keyFma).append("\" "); + } + if (!this.valueFma.isEmpty()) { + sb.append("value=\"").append(this.valueFma).append("\" "); + } + sb.append("/>"); + return sb.toString(); } public static final class IterateMapFactory implements Factory<IterateMap> { Modified: ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/Loop.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/Loop.java?rev=1334536&r1=1334535&r2=1334536&view=diff ============================================================================== --- ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/Loop.java (original) +++ ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/Loop.java Sun May 6 00:43:58 2012 @@ -21,10 +21,12 @@ package org.ofbiz.minilang.method.envops import java.util.Collections; import java.util.List; -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.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.ofbiz.minilang.method.envops.Break.BreakElementException; @@ -34,40 +36,40 @@ import org.w3c.dom.Element; /** * Loop */ -public class Loop extends MethodOperation { +public final class Loop extends MethodOperation { public static final String module = Loop.class.getName(); - protected String countStr; - protected ContextAccessor<Integer> fieldAcsr; - protected List<MethodOperation> subOps; + private final FlexibleStringExpander countFse; + private final FlexibleMapAccessor<Integer> fieldFma; + private final List<MethodOperation> subOps; public Loop(Element element, SimpleMethod simpleMethod) throws MiniLangException { super(element, simpleMethod); - this.fieldAcsr = new ContextAccessor<Integer>(element.getAttribute("field")); - this.countStr = element.getAttribute("count"); + if (MiniLangValidate.validationOn()) { + MiniLangValidate.attributeNames(simpleMethod, element, "count", "field"); + MiniLangValidate.requiredAttributes(simpleMethod, element, "count"); + MiniLangValidate.expressionAttributes(simpleMethod, element, "count", "field"); + } + this.countFse = FlexibleStringExpander.getInstance(element.getAttribute("count")); + this.fieldFma = FlexibleMapAccessor.getInstance(element.getAttribute("field")); this.subOps = Collections.unmodifiableList(SimpleMethod.readOperations(element, simpleMethod)); } @Override public boolean exec(MethodContext methodContext) throws MiniLangException { - String countStrExp = methodContext.expandString(this.countStr); + String countStr = this.countFse.expandString(methodContext.getEnvMap()); int count = 0; try { - Double ctDbl = Double.valueOf(countStrExp); - if (ctDbl != null) { - count = ctDbl.intValue(); - } + count = Double.valueOf(countStr).intValue(); } catch (NumberFormatException e) { - Debug.logError(e, module); - return false; + throw new MiniLangRuntimeException("Error while converting \"" + countStr + "\" to a number: " + e.getMessage(), this); } if (count < 0) { - Debug.logWarning("Unable to execute loop operation because the count variable is negative: " + rawString(), module); - return false; + throw new MiniLangRuntimeException("Unable to execute loop operation because the count is negative: " + countStr, this); } for (int i = 0; i < count; i++) { - fieldAcsr.put(methodContext, i); + this.fieldFma.put(methodContext.getEnvMap(), i); try { for (MethodOperation methodOperation : subOps) { if (!methodOperation.exec(methodContext)) { @@ -89,7 +91,7 @@ public class Loop extends MethodOperatio @Override public String expandedString(MethodContext methodContext) { - return this.rawString(); + return FlexibleStringExpander.expandString(toString(), methodContext.getEnvMap()); } public List<MethodOperation> getSubOps() { @@ -98,7 +100,20 @@ public class Loop extends MethodOperatio @Override public String rawString() { - return "<loop field=\"" + this.fieldAcsr + "\" count=\"" + this.countStr + "\"/>"; + return toString(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("<loop "); + if (!this.countFse.isEmpty()) { + sb.append("count=\"").append(this.countFse).append("\" "); + } + if (!this.fieldFma.isEmpty()) { + sb.append("field=\"").append(this.fieldFma).append("\" "); + } + sb.append("/>"); + return sb.toString(); } public static final class LoopFactory implements Factory<Loop> { |
Free forum by Nabble | Edit this page |