|
Author: adrianc
Date: Wed Jun 13 06:04:49 2012 New Revision: 1349646 URL: http://svn.apache.org/viewvc?rev=1349646&view=rev Log: Overhauled Mini-language <order-map-list>, <set-calendar>, <string-append>, <string-to-list>, <to-string> elements. Added a format attribute to the <set> element - to be used for type conversions. Also removed deprecated StringToField class. The overhaul includes: removing unnecessary object creation, make the class thread-safe, add syntax validation, and misc code cleanups. Removed: ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/StringToField.java Modified: ofbiz/trunk/framework/minilang/dtd/simple-methods-v2.xsd ofbiz/trunk/framework/minilang/src/META-INF/services/org.ofbiz.minilang.method.MethodOperation$Factory ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/OrderMapList.java ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/SetCalendar.java ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/SetOperation.java ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/StringAppend.java ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/StringToList.java ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/ToString.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=1349646&r1=1349645&r2=1349646&view=diff ============================================================================== --- ofbiz/trunk/framework/minilang/dtd/simple-methods-v2.xsd (original) +++ ofbiz/trunk/framework/minilang/dtd/simple-methods-v2.xsd Wed Jun 13 06:04:49 2012 @@ -1418,7 +1418,7 @@ under the License. <xs:documentation> Copies a map to another map. Does nothing if the source map does not exist. If a target map is not specified, the source map is copied to the current - envirnment (memory space). + environment (memory space). </xs:documentation> </xs:annotation> <xs:complexType> @@ -1501,18 +1501,27 @@ under the License. </xs:complexType> </xs:element> <xs:element name="order-map-list" substitutionGroup="EnvOperations"> - <xs:annotation><xs:documentation>Sort a List containing Maps: order by fields names given in order-by sub-element.</xs:documentation> + <xs:annotation> + <xs:documentation> + Sorts a list of maps. Maps are sorted by the keys specified in the order-by sub-elements. + Does nothing if the list is not found. + </xs:documentation> </xs:annotation> <xs:complexType> - <xs:sequence><xs:element maxOccurs="unbounded" ref="order-by"/></xs:sequence> - <xs:attributeGroup ref="attlist.order-map-list"/> + <xs:sequence> + <xs:element maxOccurs="unbounded" ref="order-by" /> + </xs:sequence> + <xs:attribute type="xs:string" name="list" use="required"> + <xs:annotation> + <xs:documentation> + Name of the field containing the list to be sorted. + <br/><br/> + Required. Attribute type: expression. + </xs:documentation> + </xs:annotation> + </xs:attribute> </xs:complexType> </xs:element> - <xs:attributeGroup name="attlist.order-map-list"> - <xs:attribute type="xs:string" name="list" use="required"> - <xs:annotation><xs:documentation>Name of the list to be sorted.</xs:documentation></xs:annotation> - </xs:attribute> - </xs:attributeGroup> <xs:element name="set" substitutionGroup="EnvOperations"> <xs:annotation> <xs:documentation> @@ -1544,7 +1553,7 @@ under the License. <xs:documentation> A constant value, or a constant that includes an expression. The source of the assignment. <br/><br/> - Required if the from-field attribute is empty. Attribute type: constant+expr. + Required if the from attribute is empty. Attribute type: constant+expr. Defaults to java.lang.String data type. </xs:documentation> </xs:annotation> @@ -1559,7 +1568,7 @@ under the License. <xs:attribute type="xs:string" name="default"> <xs:annotation> <xs:documentation> - A default value that is used when the from-field attribute evaluates to null or empty. + A default value that is used when the from attribute evaluates to null or empty. <br/><br/> Optional. Attribute types: constant, ${expression}. </xs:documentation> @@ -1574,10 +1583,19 @@ under the License. </xs:documentation> </xs:annotation> </xs:attribute> + <xs:attribute type="xs:string" name="format"> + <xs:annotation> + <xs:documentation> + Format to be used for object type conversion. Used when the type attribute is not empty. + <br/><br/> + Optional. Attribute types: constant, ${expression}. + </xs:documentation> + </xs:annotation> + </xs:attribute> <xs:attribute name="set-if-null" type="booleanConst"> <xs:annotation> <xs:documentation> - Controls if the target field can be set to null when the from-field attribute evaluates to null. + Controls if the target field can be set to null when the from attribute evaluates to null. Defaults to "false". <br/><br/> Optional. Attribute type: constant. @@ -1599,158 +1617,150 @@ under the License. <xs:element name="string-append" substitutionGroup="EnvOperations"> <xs:annotation> <xs:documentation> - NOTE: the prefix and suffix will only be used IFF the current string and the string to be appended are both not empty. - - So if the field does not exist then it will create a new field with this string value. - If it does exist then it will append this string value to the end. + Performs string concatenation and formatting. The operation starts by applying + an argument list (if found) to the string attribute value, the result is + prepended by the prefix attribute value, and the suffix attribute value is + appended to the result. If the string specified in the field attribute exists, + the final result is appended to it, else the field is set to the final result. </xs:documentation> </xs:annotation> <xs:complexType> - <xs:attributeGroup ref="attlist.string-append"/> + <xs:attribute type="xs:string" name="field" use="required"> + <xs:annotation> + <xs:documentation> + The target of the string concatention. + <br/><br/> + Required. Attribute type: expression. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="string" use="required"> + <xs:annotation> + <xs:documentation> + The string to append to the field named in the field attribute. + This can be a formatting string that is used with the argument list + specified in the arg-list attribute. + <br/><br/> + Required. Attribute types: constant, ${expression}. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="arg-list"> + <xs:annotation> + <xs:documentation> + An argument list to be used with a formatting string. + The argument list is applied to the string attribute value. + Does nothing if the argument list is not found. + See the java.text.MessageFormat class for more information. + <br/><br/> + Optional. Attribute type: expression. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="prefix"> + <xs:annotation> + <xs:documentation> + A string that will be prepended to the string attribute value. + <br/><br/> + Optional. Attribute types: constant, ${expression}. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="suffix"> + <xs:annotation> + <xs:documentation> + A string that will be appended to the string attribute value. + <br/><br/> + Optional. Attribute types: constant, ${expression}. + </xs:documentation> + </xs:annotation> + </xs:attribute> </xs:complexType> </xs:element> - <xs:attributeGroup name="attlist.string-append"> - <xs:attribute type="xs:string" name="field" use="required"> - <xs:annotation> - <xs:documentation> - The field that you want string-append to operate on. - This is the target field where the value will be put, and this is the string to append to that field. - - So if the field does not exist then it will create a new field with this string value. - If it does exist then it will append this string value to the end. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="xs:string" name="string" use="required"> - <xs:annotation> - <xs:documentation> - The string to append to the field named in field-name. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="xs:string" name="arg-list"> - <xs:annotation> - <xs:documentation> - arg-list-name is used to insert values from a list into - the string using the object in the standard Java library - that does this sort of string expression with a { } brackets - and a number, no dollar sign. - - This pattern of the arg-list-name with the prefix and - suffix is something form the early days which is still - supported, but the best thing to do here is just use the - flexible string expander which is far more flexible and - powerful. So you can have the prefix variables to expand - and everything all mixed into one string. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="xs:string" name="prefix"> - <xs:annotation> - <xs:documentation> - Used in conjunction with arg-list-name. - String that will be prepended to the string, - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="xs:string" name="suffix"> - <xs:annotation> - <xs:documentation> - Used in conjunction with arg-list-name. - String that will be appended to the string, - </xs:documentation> - </xs:annotation> - </xs:attribute> - </xs:attributeGroup> <xs:element name="string-to-list" substitutionGroup="EnvOperations"> <xs:annotation> <xs:documentation> - Take a string literally that can also have a flexible string expander and such in it, - and it will add it to a list. - - Note that you can have an arg-listname for using the standard - Java style argument list where you have in the source - string numbers inside of { } brackets that represent the - number the index in the argument list to insert at that point. + Adds a string to a list of strings. Deprecated - use the set element. </xs:documentation> </xs:annotation> <xs:complexType> - <xs:attributeGroup ref="attlist.string-to-list"/> + <xs:attribute type="xs:string" name="string" use="required"> + <xs:annotation> + <xs:documentation> + The string to add to the list specified in the list attribute. + <br/><br/> + Required. Attribute types: constant, ${expression}. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="list" use="required"> + <xs:annotation> + <xs:documentation> + List to add the string to. If the list does not exist, one will be created. + <br/><br/> + Required. Attribute type: expression. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="arg-list"> + <xs:annotation> + <xs:documentation> + An argument list to be used with a formatting string. + The argument list is applied to the string attribute value. + Does nothing if the argument list is not found. + See the java.text.MessageFormat class for more information. + <br/><br/> + Optional. Attribute type: expression. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="message-field"> + <xs:annotation> + <xs:documentation> + To insert a message above a field (used in conjunction with @fieldErrors FTL macro) + <br/><br/> + Optional. Attribute type: constant. + </xs:documentation> + </xs:annotation> + </xs:attribute> </xs:complexType> </xs:element> - <xs:attributeGroup name="attlist.string-to-list"> - <xs:attribute type="xs:string" name="string" use="required"> - <xs:annotation> - <xs:documentation> - String to add to the list named in list-name. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="xs:string" name="list" use="required"> - <xs:annotation> - <xs:documentation> - List to add string to. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="xs:string" name="arg-list"> - <xs:annotation> - <xs:documentation> - arg-list-name is used to insert values from a list into - the string using the object in the standard Java library - that does this sort of string expresison with a { } brackets - and a number, no dollar sign. - - This pattern of the arg-list-name with the prefix and - suffix is something form the early days which is still - supported, but the best thing to do here is just use the - flexible string expander which is far more flexible and - powerful. So you can have the prefix variables to expand - and everything all mixed into one string. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="xs:string" name="message-field"> - <xs:annotation> - <xs:documentation> - To insert a message above a field (used in conjunction with @fieldErrors FTL macro) - </xs:documentation> - </xs:annotation> - </xs:attribute> - </xs:attributeGroup> <xs:element name="to-string" substitutionGroup="EnvOperations"> <xs:annotation> <xs:documentation> - The to-string tag converts the Object in the specified field to a String, putting the string in the same field. + Converts an object to a string. Deprecated - use the set element. </xs:documentation> </xs:annotation> <xs:complexType> - <xs:attributeGroup ref="attlist.to-string"/> + <xs:attribute type="xs:string" name="field" use="required"> + <xs:annotation> + <xs:documentation> + The name of the field containing the object to convert. + <br/><br/> + Required. Attribute type: expression. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="format"> + <xs:annotation> + <xs:documentation> + Format to use for the conversion. + <br/><br/> + Optional. Attribute type: constant. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="numeric-padding"> + <xs:annotation> + <xs:documentation> + Left-pad the string with the specified number of zeroes. + <br/><br/> + Optional. Attribute type: constant. + </xs:documentation> + </xs:annotation> + </xs:attribute> </xs:complexType> </xs:element> - <xs:attributeGroup name="attlist.to-string"> - <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="format"> - <xs:annotation> - <xs:documentation> - Format based on the type of the object (date,number, etc.). - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="xs:string" name="numeric-padding"> - <xs:annotation> - <xs:documentation> - Padding to use if a numeric object is used. - </xs:documentation> - </xs:annotation> - </xs:attribute> - </xs:attributeGroup> <xs:element name="clear-field" substitutionGroup="EnvOperations"> <xs:annotation> <xs:documentation> @@ -4381,193 +4391,204 @@ under the License. </xs:annotation> </xs:attribute> </xs:attributeGroup> - <xs:element name="set-calendar" substitutionGroup="OtherOperations"> + <xs:element name="set-calendar" substitutionGroup="EnvOperations"> <xs:annotation> <xs:documentation> - The set-calendar tag allows to set a date "field" from another "from-field" date field type - or directly from a value using at least one adjuster to modify the from-field date. - The type of fields or value is Timestamp. - - Again you can use the flexible string expander here, the ${} syntax and such. It can also do a type conversion, - so going from whatever type the source data is in, which would be a string value or whatever the variable - type is for a from field, it can convert that to any ofthese types before setting it in the target field. - - You can also specify a default value in the case that the value evaluates to an empty string or the from-field is - null or empty. Then the default-value will be used. - - Adjuster years, months, days, hours, minutes, seconds and millis use integers optionally precedeed by + or - - Period-align-start and period-align-end allows to align on end or start of a period. - - You may specify a locale or a time-zone else the respective default request value is used. + Adjusts a Timestamp by a specified time duration. </xs:documentation> </xs:annotation> <xs:complexType> - <xs:attributeGroup ref="attlist.set-calendar"/> + <xs:attribute ref="field" /> + <xs:attribute type="xs:string" name="from-field"> + <xs:annotation> + <xs:documentation> + Deprecated - use the from attribute. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="from"> + <xs:annotation> + <xs:documentation> + An expression or script that returns an object or null. The source of the assignment. + <br/><br/> + A script must be prefixed with the script language followed by a colon (":"). + <br/><br/> + Required if the value attribute is empty. Attribute types: expression, script. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="value"> + <xs:annotation> + <xs:documentation> + A constant value, or a constant that includes an expression. The source of the assignment. + <br/><br/> + Required if the from attribute is empty. Attribute type: constant+expr. + Defaults to java.lang.String data type. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="default-value"> + <xs:annotation> + <xs:documentation> + Deprecated - use the default attribute. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="default"> + <xs:annotation> + <xs:documentation> + A default value that is used when the from attribute evaluates to null or empty. + <br/><br/> + Optional. Attribute types: constant, ${expression}. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="set-if-null" type="booleanConst"> + <xs:annotation> + <xs:documentation> + Controls if the target field can be set to null when the from attribute evaluates to null. + Defaults to "false". + <br/><br/> + Optional. Attribute type: constant. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="set-if-empty" type="booleanConst"> + <xs:annotation> + <xs:documentation> + Controls if the target field can be set to an empty value. The meaning of "empty" depends on the Java data type. + Defaults to "true". + <br/><br/> + Optional. Attribute type: constant. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="years"> + <xs:annotation> + <xs:documentation> + Add (optionally using +) or subtract (using -) a number of year(s). + If an expression is used, it should evaluate to an integer. + <br/><br/> + Optional. Attribute types: constant, ${expression}. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="months"> + <xs:annotation> + <xs:documentation> + Add (optionally using +) or subtract (using -) a number of month(s). + If an expression is used, it should evaluate to an integer. + <br/><br/> + Optional. Attribute types: constant, ${expression}. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="days"> + <xs:annotation> + <xs:documentation> + Add (optionally using +) or subtract (using -) a number of days(s). + If an expression is used, it should evaluate to an integer. + <br/><br/> + Optional. Attribute types: constant, ${expression}. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="hours"> + <xs:annotation> + <xs:documentation> + Add (optionally using +) or subtract (using -) a number of hour(s). + If an expression is used, it should evaluate to an integer. + <br/><br/> + Optional. Attribute types: constant, ${expression}. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="minutes"> + <xs:annotation> + <xs:documentation> + Add (optionally using +) or subtract (using -) a number of minute(s). + If an expression is used, it should evaluate to an integer. + <br/><br/> + Optional. Attribute types: constant, ${expression}. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="seconds"> + <xs:annotation> + <xs:documentation> + Add (optionally using +) or subtract (using -) a number of second(s). + If an expression is used, it should evaluate to an integer. + <br/><br/> + Optional. Attribute types: constant, ${expression}. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="millis"> + <xs:annotation> + <xs:documentation> + Add (optionally using +) or subtract (using -) a number of milli-second(s). + If an expression is used, it should evaluate to an integer. + <br/><br/> + Optional. Attribute types: constant, ${expression}. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute name="period-align-start"> + <xs:annotation> + <xs:documentation> + Align the adjusted date to the start of a period. + <br/><br/> + Optional. Attribute types: constant, ${expression}. + </xs:documentation> + </xs:annotation> + <xs:simpleType> + <xs:restriction base="xs:token"> + <xs:enumeration value="year" /> + <xs:enumeration value="month" /> + <xs:enumeration value="week" /> + <xs:enumeration value="day" /> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + <xs:attribute name="period-align-end"> + <xs:annotation> + <xs:documentation> + Align the adjusted date to the end of a period. + <br/><br/> + Optional. Attribute types: constant, ${expression}. + </xs:documentation> + </xs:annotation> + <xs:simpleType> + <xs:restriction base="xs:token"> + <xs:enumeration value="year" /> + <xs:enumeration value="month" /> + <xs:enumeration value="week" /> + <xs:enumeration value="day" /> + </xs:restriction> + </xs:simpleType> + </xs:attribute> + <xs:attribute type="xs:string" name="locale"> + <xs:annotation> + <xs:documentation> + A locale value (eg: en). The locale selects the calendar to be used for the adjustment. + Defaults to the environment locale. + <br/><br/> + Optional. Attribute types: constant, ${expression}. + </xs:documentation> + </xs:annotation> + </xs:attribute> + <xs:attribute type="xs:string" name="time-zone"> + <xs:annotation> + <xs:documentation> + A time zone value (eg: GMT). + Defaults to the environment time zone. + <br/><br/> + Optional. Attribute types: constant, ${expression}. + </xs:documentation> + </xs:annotation> + </xs:attribute> </xs:complexType> </xs:element> - <xs:attributeGroup name="attlist.set-calendar"> - <xs:attribute type="xs:string" name="field" use="required"> - <xs:annotation> - <xs:documentation> - Name of the field to copy value to. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="xs:string" name="from-field"> - <xs:annotation> - <xs:documentation> - Name of the field to copy value from. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="xs:string" name="value"> - <xs:annotation> - <xs:documentation> - Simple value to copy in field. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="xs:string" name="default-value"> - <xs:annotation> - <xs:documentation> - Default value to copy in field if value evaluates to an empty string or the from-field is null or empty. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute name="set-if-null" default="false"> - <xs:annotation> - <xs:documentation> - Specifies whether or not to set fields that are null or empty. - Defaults to true. - </xs:documentation> - </xs:annotation> - <xs:simpleType> - <xs:restriction base="xs:token"> - <xs:enumeration value="true"/> - <xs:enumeration value="false"/> - </xs:restriction> - </xs:simpleType> - </xs:attribute> - <xs:attribute name="set-if-empty" default="true"> - <xs:annotation> - <xs:documentation> - If the source value, either from a value or from a field, is empty, and - empty-string an empty list or a null value. - In this case it's set to true. - - If you don't want to set, if you want it to - leave the target field alone when the source is empty, - then you need to set this to false. - </xs:documentation> - </xs:annotation> - <xs:simpleType> - <xs:restriction base="xs:token"> - <xs:enumeration value="true"/> - <xs:enumeration value="false"/> - </xs:restriction> - </xs:simpleType> - </xs:attribute> - <xs:attribute type="xs:string" name="years"> - <xs:annotation> - <xs:documentation> - Add (optionally using +) or subtract (using -) a number of year(s). - If an expression is used, it should evaluate to an integer. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="xs:string" name="months"> - <xs:annotation> - <xs:documentation> - Add (optionally using +) or subtract (using -) a number of month(s). - If an expression is used, it should evaluate to an integer. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="xs:string" name="days"> - <xs:annotation> - <xs:documentation> - Add (optionally using +) or subtract (using -) a number of days(s). - If an expression is used, it should evaluate to an integer. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="xs:string" name="hours"> - <xs:annotation> - <xs:documentation> - Add (optionally using +) or subtract (using -) a number of hour(s). - If an expression is used, it should evaluate to an integer. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="xs:string" name="minutes"> - <xs:annotation> - <xs:documentation> - Add (optionally using +) or subtract (using -) a number of minute(s). - If an expression is used, it should evaluate to an integer. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="xs:string" name="seconds"> - <xs:annotation> - <xs:documentation> - Add (optionally using +) or subtract (using -) a number of second(s). - If an expression is used, it should evaluate to an integer. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="xs:string" name="millis"> - <xs:annotation> - <xs:documentation> - Add (optionally using +) or subtract (using -) a number of milli-second(s). - If an expression is used, it should evaluate to an integer. - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute name="period-align-start"> - <xs:annotation> - <xs:documentation> - Align the returned date to the start of the chosen adjustment between year, month, week or day. - </xs:documentation> - </xs:annotation> - <xs:simpleType> - <xs:restriction base="xs:token"> - <xs:enumeration value="year"/> - <xs:enumeration value="month"/> - <xs:enumeration value="week"/> - <xs:enumeration value="day"/> - </xs:restriction> - </xs:simpleType> - </xs:attribute> - <xs:attribute name="period-align-end"> - <xs:annotation> - <xs:documentation> - Align the returned date to the end of the chosen adjustment between year, month, week or day. - </xs:documentation> - </xs:annotation> - <xs:simpleType> - <xs:restriction base="xs:token"> - <xs:enumeration value="year"/> - <xs:enumeration value="month"/> - <xs:enumeration value="week"/> - <xs:enumeration value="day"/> - </xs:restriction> - </xs:simpleType> - </xs:attribute> - <xs:attribute type="xs:string" name="locale"> - <xs:annotation> - <xs:documentation> - A locale value (eg: en) - </xs:documentation> - </xs:annotation> - </xs:attribute> - <xs:attribute type="xs:string" name="time-zone"> - <xs:annotation> - <xs:documentation> - a time zone value (eg: GMT) - </xs:documentation> - </xs:annotation> - </xs:attribute> - </xs:attributeGroup> <!-- ====================================================== ========== The Simple Map Processor Section ========== Modified: ofbiz/trunk/framework/minilang/src/META-INF/services/org.ofbiz.minilang.method.MethodOperation$Factory URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/minilang/src/META-INF/services/org.ofbiz.minilang.method.MethodOperation%24Factory?rev=1349646&r1=1349645&r2=1349646&view=diff ============================================================================== --- ofbiz/trunk/framework/minilang/src/META-INF/services/org.ofbiz.minilang.method.MethodOperation$Factory (original) +++ ofbiz/trunk/framework/minilang/src/META-INF/services/org.ofbiz.minilang.method.MethodOperation$Factory Wed Jun 13 06:04:49 2012 @@ -86,7 +86,6 @@ org.ofbiz.minilang.method.envops.OrderMa org.ofbiz.minilang.method.envops.SetCalendar$SetCalendarFactory org.ofbiz.minilang.method.envops.SetOperation$SetOperationFactory org.ofbiz.minilang.method.envops.StringAppend$StringAppendFactory -org.ofbiz.minilang.method.envops.StringToField$StringToFieldFactory org.ofbiz.minilang.method.envops.StringToList$StringToListFactory org.ofbiz.minilang.method.envops.ToString$ToStringFactory org.ofbiz.minilang.method.envops.While$WhileFactory Modified: ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/OrderMapList.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/OrderMapList.java?rev=1349646&r1=1349645&r2=1349646&view=diff ============================================================================== --- ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/OrderMapList.java (original) +++ ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/OrderMapList.java Wed Jun 13 06:04:49 2012 @@ -18,73 +18,93 @@ *******************************************************************************/ package org.ofbiz.minilang.method.envops; +import java.util.ArrayList; 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.UtilValidate; import org.ofbiz.base.util.UtilXml; import org.ofbiz.base.util.collections.FlexibleMapAccessor; import org.ofbiz.base.util.collections.MapComparator; +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.w3c.dom.Element; /** - * Copies an environment field to a list + * Implements the <order-map-list> element. */ -public class OrderMapList extends MethodOperation { - - public static final String module = FieldToList.class.getName(); +public final class OrderMapList extends MethodOperation { - protected ContextAccessor<List<Map<Object, Object>>> listAcsr; - protected MapComparator mc; - protected List<FlexibleMapAccessor<String>> orderByAcsrList = FastList.newInstance(); + private final FlexibleMapAccessor<List<Map<Object, Object>>> listFma; + private final MapComparator mc; public OrderMapList(Element element, SimpleMethod simpleMethod) throws MiniLangException { super(element, simpleMethod); - listAcsr = new ContextAccessor<List<Map<Object, Object>>>(element.getAttribute("list"), element.getAttribute("list-name")); - for (Element orderByElement : UtilXml.childElementList(element, "order-by")) { - FlexibleMapAccessor<String> fma = FlexibleMapAccessor.getInstance(UtilValidate.isNotEmpty(orderByElement.getAttribute("field")) ? orderByElement.getAttribute("field") : orderByElement.getAttribute("field-name")); - this.orderByAcsrList.add(fma); + if (MiniLangValidate.validationOn()) { + MiniLangValidate.attributeNames(simpleMethod, element, "list"); + MiniLangValidate.requiredAttributes(simpleMethod, element, "list"); + MiniLangValidate.expressionAttributes(simpleMethod, element, "list"); + MiniLangValidate.childElements(simpleMethod, element, "order-by"); + MiniLangValidate.requiredChildElements(simpleMethod, element, "order-by"); + } + listFma = FlexibleMapAccessor.getInstance(element.getAttribute("list")); + List<? extends Element> orderByElements = UtilXml.childElementList(element, "order-by"); + if (orderByElements.size() > 0) { + ArrayList<FlexibleMapAccessor<String>> orderByList = new ArrayList<FlexibleMapAccessor<String>>(orderByElements.size()); + for (Element orderByElement : orderByElements) { + FlexibleMapAccessor<String> fma = FlexibleMapAccessor.getInstance(orderByElement.getAttribute("field")); + orderByList.add(fma); + } + mc = new MapComparator(orderByList); + } else { + mc = null; } - this.mc = new MapComparator(this.orderByAcsrList); } @Override public boolean exec(MethodContext methodContext) throws MiniLangException { - List<Map<Object, Object>> orderList = listAcsr.get(methodContext); - if (orderList == null) { - if (Debug.infoOn()) - Debug.logInfo("List not found with name " + listAcsr + ", not ordering/sorting list.", module); - return true; + if (mc == null) { + throw new MiniLangRuntimeException("order-by sub-elements not found.", this); + } + List<Map<Object, Object>> orderList = listFma.get(methodContext.getEnvMap()); + if (orderList != null) { + Collections.sort(orderList, mc); } - Collections.sort(orderList, mc); 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() { - return "<order-map-list list-name=\"" + this.listAcsr + "\"/>"; + return toString(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("<order-map-list "); + sb.append("list=\"").append(this.listFma).append("\" />"); + return sb.toString(); } + /** + * A factory for the <order-map-list> element. + */ public static final class OrderMapListFactory implements Factory<OrderMapList> { + @Override public OrderMapList createMethodOperation(Element element, SimpleMethod simpleMethod) throws MiniLangException { return new OrderMapList(element, simpleMethod); } + @Override public String getName() { return "order-map-list"; } Modified: ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/SetCalendar.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/SetCalendar.java?rev=1349646&r1=1349645&r2=1349646&view=diff ============================================================================== --- ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/SetCalendar.java (original) +++ ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/SetCalendar.java Wed Jun 13 06:04:49 2012 @@ -24,12 +24,16 @@ import java.util.TimeZone; import org.ofbiz.base.util.Debug; import org.ofbiz.base.util.ObjectType; +import org.ofbiz.base.util.Scriptlet; +import org.ofbiz.base.util.StringUtil; import org.ofbiz.base.util.UtilDateTime; +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.method.MethodContext; import org.ofbiz.minilang.method.MethodOperation; import org.w3c.dom.Element; @@ -37,90 +41,144 @@ import org.w3c.dom.Element; import com.ibm.icu.util.Calendar; /** - * Adjust a Timestamp by a specified time. + * Implements the <set-calendar> element. */ -public class SetCalendar extends MethodOperation { +public final class SetCalendar extends MethodOperation { public static final String module = SetCalendar.class.getName(); - protected FlexibleStringExpander daysExdr; - protected FlexibleStringExpander defaultExdr; - protected ContextAccessor<Timestamp> field; - protected ContextAccessor<Object> fromField; - protected FlexibleStringExpander hoursExdr; - protected FlexibleStringExpander localeExdr; - protected FlexibleStringExpander millisExdr; - protected FlexibleStringExpander minutesExdr; - protected FlexibleStringExpander monthsExdr; - protected FlexibleStringExpander periodAlignEnd; - protected FlexibleStringExpander periodAlignStart; - protected FlexibleStringExpander secondsExdr; - protected boolean setIfEmpty; // default to true - protected boolean setIfNull; // default to false - protected FlexibleStringExpander timeZoneExdr; - protected FlexibleStringExpander valueExdr; - protected FlexibleStringExpander yearsExdr; + // This method is needed only during the v1 to v2 transition + private static boolean autoCorrect(Element element) { + boolean elementModified = false; + // Correct deprecated default-value attribute + String defaultAttr = element.getAttribute("default-value"); + if (defaultAttr.length() > 0) { + element.setAttribute("default", defaultAttr); + element.removeAttribute("default-value"); + elementModified = true; + } + // Correct deprecated from-field attribute + String fromAttr = element.getAttribute("from-field"); + if (fromAttr.length() > 0) { + element.setAttribute("from", fromAttr); + element.removeAttribute("from-field"); + elementModified = true; + } + // Correct value attribute expression that belongs in from attribute + String valueAttr = element.getAttribute("value").trim(); + if (valueAttr.startsWith("${") && valueAttr.endsWith("}")) { + valueAttr = valueAttr.substring(2, valueAttr.length() - 1); + if (!valueAttr.contains("${")) { + element.setAttribute("from", valueAttr); + element.removeAttribute("value"); + elementModified = true; + } + } + return elementModified; + } + + private final FlexibleStringExpander daysFse; + private final FlexibleStringExpander defaultFse; + private final FlexibleMapAccessor<Object> fieldFma; + private final FlexibleMapAccessor<Object> fromFma; + private final FlexibleStringExpander hoursFse; + private final FlexibleStringExpander localeFse; + private final FlexibleStringExpander millisFse; + private final FlexibleStringExpander minutesFse; + private final FlexibleStringExpander monthsFse; + private final FlexibleStringExpander periodAlignEnd; + private final FlexibleStringExpander periodAlignStart; + private final FlexibleStringExpander secondsFse; + private final boolean setIfEmpty; + private final boolean setIfNull; + private final Scriptlet scriptlet; + private final FlexibleStringExpander timeZoneFse; + private final FlexibleStringExpander valueFse; + private final FlexibleStringExpander yearsFse; public SetCalendar(Element element, SimpleMethod simpleMethod) throws MiniLangException { super(element, simpleMethod); - this.field = new ContextAccessor<Timestamp>(element.getAttribute("field")); - this.fromField = new ContextAccessor<Object>(element.getAttribute("from-field")); - this.valueExdr = FlexibleStringExpander.getInstance(element.getAttribute("value")); - this.defaultExdr = FlexibleStringExpander.getInstance(element.getAttribute("default-value")); - this.yearsExdr = FlexibleStringExpander.getInstance(element.getAttribute("years")); - this.monthsExdr = FlexibleStringExpander.getInstance(element.getAttribute("months")); - this.daysExdr = FlexibleStringExpander.getInstance(element.getAttribute("days")); - this.hoursExdr = FlexibleStringExpander.getInstance(element.getAttribute("hours")); - this.minutesExdr = FlexibleStringExpander.getInstance(element.getAttribute("minutes")); - this.secondsExdr = FlexibleStringExpander.getInstance(element.getAttribute("seconds")); - this.millisExdr = FlexibleStringExpander.getInstance(element.getAttribute("millis")); - this.periodAlignStart = FlexibleStringExpander.getInstance(element.getAttribute("period-align-start")); - this.periodAlignEnd = FlexibleStringExpander.getInstance(element.getAttribute("period-align-end")); - this.localeExdr = FlexibleStringExpander.getInstance(element.getAttribute("locale")); - this.timeZoneExdr = FlexibleStringExpander.getInstance(element.getAttribute("time-zone")); - // default to false, anything but true is false + if (MiniLangValidate.validationOn()) { + MiniLangValidate.deprecatedAttribute(simpleMethod, element, "from-field", "replace with \"from\""); + MiniLangValidate.deprecatedAttribute(simpleMethod, element, "default-value", "replace with \"default\""); + MiniLangValidate.attributeNames(simpleMethod, element, "field", "from-field", "from", "value", "default-value", "default", "set-if-null", "set-if-empty", + "years", "months", "days", "hours", "minutes", "seconds", "millis", "period-align-start", "period-align-end", "locale", "time-zone"); + MiniLangValidate.requiredAttributes(simpleMethod, element, "field"); + MiniLangValidate.requireAnyAttribute(simpleMethod, element, "from", "value"); + MiniLangValidate.constantPlusExpressionAttributes(simpleMethod, element, "value"); + MiniLangValidate.constantAttributes(simpleMethod, element, "set-if-null", "set-if-empty"); + MiniLangValidate.expressionAttributes(simpleMethod, element, "field", "from", "from-field"); + MiniLangValidate.noChildElements(simpleMethod, element); + } + boolean elementModified = autoCorrect(element); + if (elementModified && MiniLangUtil.autoCorrectOn()) { + MiniLangUtil.flagDocumentAsCorrected(element); + } + this.fieldFma = FlexibleMapAccessor.getInstance(element.getAttribute("field")); + String fromAttribute = element.getAttribute("from"); + if (MiniLangUtil.containsScript(fromAttribute)) { + this.scriptlet = new Scriptlet(StringUtil.convertOperatorSubstitutions(fromAttribute)); + this.fromFma = FlexibleMapAccessor.getInstance(null); + } else { + this.scriptlet = null; + this.fromFma = FlexibleMapAccessor.getInstance(fromAttribute); + } + this.valueFse = FlexibleStringExpander.getInstance(element.getAttribute("value")); + if (!fromAttribute.isEmpty() && !this.valueFse.isEmpty()) { + throw new IllegalArgumentException("Cannot include both a from attribute and a value attribute in a <set-calendar> element."); + } + this.defaultFse = FlexibleStringExpander.getInstance(element.getAttribute("default")); this.setIfNull = "true".equals(element.getAttribute("set-if-null")); - // default to true, anything but false is true this.setIfEmpty = !"false".equals(element.getAttribute("set-if-empty")); - if (!this.fromField.isEmpty() && !this.valueExdr.isEmpty()) { - throw new IllegalArgumentException("Cannot specify a from-field [" + element.getAttribute("from-field") + "] and a value [" + element.getAttribute("value") + "] on the set-calendar action in a screen widget"); - } + this.yearsFse = FlexibleStringExpander.getInstance(element.getAttribute("years")); + this.monthsFse = FlexibleStringExpander.getInstance(element.getAttribute("months")); + this.daysFse = FlexibleStringExpander.getInstance(element.getAttribute("days")); + this.hoursFse = FlexibleStringExpander.getInstance(element.getAttribute("hours")); + this.minutesFse = FlexibleStringExpander.getInstance(element.getAttribute("minutes")); + this.secondsFse = FlexibleStringExpander.getInstance(element.getAttribute("seconds")); + this.millisFse = FlexibleStringExpander.getInstance(element.getAttribute("millis")); + this.periodAlignStart = FlexibleStringExpander.getInstance(element.getAttribute("period-align-start")); + this.periodAlignEnd = FlexibleStringExpander.getInstance(element.getAttribute("period-align-end")); + this.localeFse = FlexibleStringExpander.getInstance(element.getAttribute("locale")); + this.timeZoneFse = FlexibleStringExpander.getInstance(element.getAttribute("time-zone")); } @Override public boolean exec(MethodContext methodContext) throws MiniLangException { Object newValue = null; - if (!this.fromField.isEmpty()) { - newValue = this.fromField.get(methodContext); - if (Debug.verboseOn()) - Debug.logVerbose("In screen getting value for field from [" + this.fromField.toString() + "]: " + newValue, module); - } else if (!this.valueExdr.isEmpty()) { - newValue = methodContext.expandString(this.valueExdr); - } - // If newValue is still empty, use the default value - if (ObjectType.isEmpty(newValue) && !this.defaultExdr.isEmpty()) { - newValue = methodContext.expandString(this.defaultExdr); + if (this.scriptlet != null) { + try { + newValue = this.scriptlet.executeScript(methodContext.getEnvMap()); + } catch (Exception exc) { + Debug.logWarning(exc, "Error evaluating scriptlet [" + this.scriptlet + "]: " + exc, module); + } + } else if (!this.fromFma.isEmpty()) { + newValue = this.fromFma.get(methodContext.getEnvMap()); + } else if (!this.valueFse.isEmpty()) { + newValue = this.valueFse.expand(methodContext.getEnvMap()); + } + if (ObjectType.isEmpty(newValue) && !this.defaultFse.isEmpty()) { + newValue = this.defaultFse.expand(methodContext.getEnvMap()); } if (!setIfNull && newValue == null) { - if (Debug.verboseOn()) - Debug.logVerbose("Field value not found (null) with name [" + fromField + "] and value [" + valueExdr + "], and there was not default value, not setting field", module); return true; } if (!setIfEmpty && ObjectType.isEmpty(newValue)) { - if (Debug.verboseOn()) - Debug.logVerbose("Field value not found (empty) with name [" + fromField + "] and value [" + valueExdr + "], and there was not default value, not setting field", module); return true; } - // Convert attributes to the corresponding data types Locale locale = null; TimeZone timeZone = null; Timestamp fromStamp = null; + int years = 0; + int months = 0; + int days = 0; + int hours = 0; + int minutes = 0; + int seconds = 0; + int millis = 0; try { - if (!this.localeExdr.isEmpty()) { - locale = (Locale) ObjectType.simpleTypeConvert(methodContext.expandString(this.localeExdr), "Locale", null, null); - } - if (!this.timeZoneExdr.isEmpty()) { - timeZone = (TimeZone) ObjectType.simpleTypeConvert(methodContext.expandString(this.timeZoneExdr), "TimeZone", null, null); + if (!this.localeFse.isEmpty()) { + locale = (Locale) ObjectType.simpleTypeConvert(this.localeFse.expand(methodContext.getEnvMap()), "Locale", null, null); } if (locale == null) { locale = methodContext.getLocale(); @@ -128,6 +186,9 @@ public class SetCalendar extends MethodO if (locale == null) { locale = Locale.getDefault(); } + if (!this.timeZoneFse.isEmpty()) { + timeZone = (TimeZone) ObjectType.simpleTypeConvert(this.timeZoneFse.expand(methodContext.getEnvMap()), "TimeZone", null, null); + } if (timeZone == null) { timeZone = methodContext.getTimeZone(); } @@ -135,21 +196,30 @@ public class SetCalendar extends MethodO timeZone = TimeZone.getDefault(); } fromStamp = (Timestamp) MiniLangUtil.convertType(newValue, java.sql.Timestamp.class, locale, timeZone, UtilDateTime.DATE_TIME_FORMAT); + if (!this.yearsFse.isEmpty()) { + years= Integer.parseInt(this.yearsFse.expandString(methodContext.getEnvMap())); + } + if (!this.monthsFse.isEmpty()) { + months = Integer.parseInt(this.monthsFse.expandString(methodContext.getEnvMap())); + } + if (!this.daysFse.isEmpty()) { + days = Integer.parseInt(this.daysFse.expandString(methodContext.getEnvMap())); + } + if (!this.hoursFse.isEmpty()) { + hours = Integer.parseInt(this.hoursFse.expandString(methodContext.getEnvMap())); + } + if (!this.minutesFse.isEmpty()) { + minutes = Integer.parseInt(this.minutesFse.expandString(methodContext.getEnvMap())); + } + if (!this.secondsFse.isEmpty()) { + seconds = Integer.parseInt(this.secondsFse.expandString(methodContext.getEnvMap())); + } + if (!this.millisFse.isEmpty()) { + millis = Integer.parseInt(this.millisFse.expandString(methodContext.getEnvMap())); + } } catch (Exception e) { - // Catching all exceptions - even potential ClassCastException - if (Debug.verboseOn()) - Debug.logVerbose("Error converting attributes to objects: " + e.getMessage(), module); - return true; + throw new MiniLangRuntimeException("Exception thrown while parsing attributes: " + e.getMessage(), this); } - // Convert Strings to ints - int years = this.yearsExdr.isEmpty() ? 0 : Integer.parseInt(methodContext.expandString(this.yearsExdr)); - int months = this.monthsExdr.isEmpty() ? 0 : Integer.parseInt(methodContext.expandString(this.monthsExdr)); - int days = this.daysExdr.isEmpty() ? 0 : Integer.parseInt(methodContext.expandString(this.daysExdr)); - int hours = this.hoursExdr.isEmpty() ? 0 : Integer.parseInt(methodContext.expandString(this.hoursExdr)); - int minutes = this.minutesExdr.isEmpty() ? 0 : Integer.parseInt(methodContext.expandString(this.minutesExdr)); - int seconds = this.secondsExdr.isEmpty() ? 0 : Integer.parseInt(methodContext.expandString(this.secondsExdr)); - int millis = this.millisExdr.isEmpty() ? 0 : Integer.parseInt(methodContext.expandString(this.millisExdr)); - // Adjust calendar Calendar cal = UtilDateTime.toCalendar(fromStamp, timeZone, locale); cal.add(Calendar.MILLISECOND, millis); cal.add(Calendar.SECOND, seconds); @@ -159,9 +229,8 @@ public class SetCalendar extends MethodO cal.add(Calendar.MONTH, months); cal.add(Calendar.YEAR, years); Timestamp toStamp = new Timestamp(cal.getTimeInMillis()); - // Align period start/end if (!periodAlignStart.isEmpty()) { - String period = methodContext.expandString(periodAlignStart); + String period = periodAlignStart.expandString(methodContext.getEnvMap()); if ("day".equals(period)) { toStamp = UtilDateTime.getDayStart(toStamp, 0, timeZone, locale); } else if ("week".equals(period)) { @@ -170,9 +239,11 @@ public class SetCalendar extends MethodO toStamp = UtilDateTime.getMonthStart(toStamp, 0, timeZone, locale); } else if ("year".equals(period)) { toStamp = UtilDateTime.getYearStart(toStamp, 0, timeZone, locale); + } else { + throw new MiniLangRuntimeException("Invalid period-align-start attribute value: " + period, this); } } else if (!periodAlignEnd.isEmpty()) { - String period = methodContext.expandString(periodAlignEnd); + String period = periodAlignEnd.expandString(methodContext.getEnvMap()); if ("day".equals(period)) { toStamp = UtilDateTime.getDayEnd(toStamp, timeZone, locale); } else if ("week".equals(period)) { @@ -181,31 +252,93 @@ public class SetCalendar extends MethodO toStamp = UtilDateTime.getMonthEnd(toStamp, timeZone, locale); } else if ("year".equals(period)) { toStamp = UtilDateTime.getYearEnd(toStamp, timeZone, locale); + } else { + throw new MiniLangRuntimeException("Invalid period-align-end attribute value: " + period, this); } } - if (Debug.verboseOn()) - Debug.logVerbose("In screen setting calendar [" + this.field.toString(), module); - this.field.put(methodContext, toStamp); + this.fieldFma.put(methodContext.getEnvMap(), toStamp); 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() { - return "<set-calendar field=\"" + this.field + (this.valueExdr.isEmpty() ? "" : "\" value=\"" + this.valueExdr.getOriginal()) + (this.fromField.isEmpty() ? "" : "\" from-field=\"" + this.fromField) + (this.defaultExdr.isEmpty() ? "" : "\" default-value=\"" + this.defaultExdr.getOriginal()) - + "\"/>"; + return toString(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("<set-calendar "); + sb.append("field=\"").append(this.fieldFma).append("\" "); + if (!this.fromFma.isEmpty()) { + sb.append("from=\"").append(this.fromFma).append("\" "); + } + if (this.scriptlet != null) { + sb.append("from=\"").append(this.scriptlet).append("\" "); + } + if (!this.valueFse.isEmpty()) { + sb.append("value=\"").append(this.valueFse).append("\" "); + } + if (!this.defaultFse.isEmpty()) { + sb.append("default=\"").append(this.defaultFse).append("\" "); + } + if (!this.yearsFse.isEmpty()) { + sb.append("years=\"").append(this.yearsFse).append("\" "); + } + if (!this.monthsFse.isEmpty()) { + sb.append("months=\"").append(this.monthsFse).append("\" "); + } + if (!this.daysFse.isEmpty()) { + sb.append("days=\"").append(this.daysFse).append("\" "); + } + if (!this.hoursFse.isEmpty()) { + sb.append("hours=\"").append(this.hoursFse).append("\" "); + } + if (!this.minutesFse.isEmpty()) { + sb.append("minutes=\"").append(this.minutesFse).append("\" "); + } + if (!this.secondsFse.isEmpty()) { + sb.append("seconds=\"").append(this.secondsFse).append("\" "); + } + if (!this.millisFse.isEmpty()) { + sb.append("millis=\"").append(this.millisFse).append("\" "); + } + if (!this.periodAlignStart.isEmpty()) { + sb.append("period-align-start=\"").append(this.localeFse).append("\" "); + } + if (!this.periodAlignEnd.isEmpty()) { + sb.append("period-align-end=\"").append(this.localeFse).append("\" "); + } + if (!this.localeFse.isEmpty()) { + sb.append("locale=\"").append(this.localeFse).append("\" "); + } + if (!this.timeZoneFse.isEmpty()) { + sb.append("time-zone=\"").append(this.timeZoneFse).append("\" "); + } + if (this.setIfNull) { + sb.append("set-if-null=\"true\" "); + } + if (!this.setIfEmpty) { + sb.append("set-if-empty=\"false\" "); + } + sb.append("/>"); + return sb.toString(); } + /** + * A factory for the <set-calendar> element. + */ public static final class SetCalendarFactory implements Factory<SetCalendar> { + @Override public SetCalendar createMethodOperation(Element element, SimpleMethod simpleMethod) throws MiniLangException { return new SetCalendar(element, simpleMethod); } + @Override public String getName() { return "set-calendar"; } Modified: ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/SetOperation.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/SetOperation.java?rev=1349646&r1=1349645&r2=1349646&view=diff ============================================================================== --- ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/SetOperation.java (original) +++ ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/SetOperation.java Wed Jun 13 06:04:49 2012 @@ -36,7 +36,7 @@ import org.ofbiz.minilang.method.MethodO import org.w3c.dom.Element; /** - * Assigns a field from an expression or script, or from a constant value. Also supports a default value and type conversion. + * Implements the <set> element. */ public final class SetOperation extends MethodOperation { @@ -73,6 +73,7 @@ public final class SetOperation extends } private final FlexibleStringExpander defaultFse; + private final FlexibleStringExpander formatFse; private final FlexibleMapAccessor<Object> fieldFma; private final FlexibleMapAccessor<Object> fromFma; private final Scriptlet scriptlet; @@ -85,11 +86,9 @@ public final class SetOperation extends public SetOperation(Element element, SimpleMethod simpleMethod) throws MiniLangException { super(element, simpleMethod); if (MiniLangValidate.validationOn()) { - /* MiniLangValidate.deprecatedAttribute(simpleMethod, element, "from-field", "replace with \"from\""); MiniLangValidate.deprecatedAttribute(simpleMethod, element, "default-value", "replace with \"default\""); - */ - MiniLangValidate.attributeNames(simpleMethod, element, "field", "from-field", "from", "value", "default-value", "default", "type", "set-if-null", "set-if-empty"); + MiniLangValidate.attributeNames(simpleMethod, element, "field", "from-field", "from", "value", "default-value", "default", "format", "type", "set-if-null", "set-if-empty"); MiniLangValidate.requiredAttributes(simpleMethod, element, "field"); MiniLangValidate.requireAnyAttribute(simpleMethod, element, "from-field", "from", "value"); MiniLangValidate.constantPlusExpressionAttributes(simpleMethod, element, "value"); @@ -112,6 +111,7 @@ public final class SetOperation extends } this.valueFse = FlexibleStringExpander.getInstance(element.getAttribute("value")); this.defaultFse = FlexibleStringExpander.getInstance(element.getAttribute("default")); + this.formatFse = FlexibleStringExpander.getInstance(element.getAttribute("format")); this.type = element.getAttribute("type"); Class<?> targetClass = null; if (!this.type.isEmpty()) { @@ -124,7 +124,7 @@ public final class SetOperation extends this.targetClass = targetClass; this.setIfNull = "true".equals(element.getAttribute("set-if-null")); // default to false, anything but true is false this.setIfEmpty = !"false".equals(element.getAttribute("set-if-empty")); // default to true, anything but false is true - if (!this.fromFma.isEmpty() && !this.valueFse.isEmpty()) { + if (!fromAttribute.isEmpty() && !this.valueFse.isEmpty()) { throw new IllegalArgumentException("Cannot include both a from attribute and a value attribute in a <set> element."); } } @@ -166,13 +166,17 @@ public final class SetOperation extends newValue = FastList.newInstance(); } else { try { + String format = null; + if (!this.formatFse.isEmpty()) { + format = this.formatFse.expandString(methodContext.getEnvMap()); + } Class<?> targetClass = this.targetClass; if (targetClass == null) { targetClass = MiniLangUtil.getObjectClassForConversion(newValue); } - newValue = MiniLangUtil.convertType(newValue, targetClass, methodContext.getLocale(), methodContext.getTimeZone(), null); + newValue = MiniLangUtil.convertType(newValue, targetClass, methodContext.getLocale(), methodContext.getTimeZone(), format); } catch (Exception e) { - String errMsg = "Could not convert field value for the field: [" + this.fieldFma.toString() + "] to the [" + this.type + "] type for the value [" + newValue + "]: " + e.toString(); + String errMsg = "Could not convert field value for the field: [" + this.fieldFma.toString() + "] to the [" + this.type + "] type for the value [" + newValue + "]: " + e.getMessage(); Debug.logWarning(e, errMsg, module); this.simpleMethod.addErrorMessage(methodContext, errMsg); return false; @@ -180,7 +184,7 @@ public final class SetOperation extends } } if (Debug.verboseOn()) - Debug.logVerbose("In screen setting field [" + this.fieldFma.toString() + "] to value: " + newValue, module); + Debug.logVerbose("Setting field [" + this.fieldFma.toString() + "] to value: " + newValue, module); this.fieldFma.put(methodContext.getEnvMap(), newValue); return true; } @@ -216,15 +220,26 @@ public final class SetOperation extends if (this.type.length() > 0) { sb.append("type=\"").append(this.type).append("\" "); } + if (this.setIfNull) { + sb.append("set-if-null=\"true\" "); + } + if (!this.setIfEmpty) { + sb.append("set-if-empty=\"false\" "); + } sb.append("/>"); return sb.toString(); } + /** + * A factory for the <set> element. + */ public static final class SetOperationFactory implements Factory<SetOperation> { + @Override public SetOperation createMethodOperation(Element element, SimpleMethod simpleMethod) throws MiniLangException { return new SetOperation(element, simpleMethod); } + @Override public String getName() { return "set"; } Modified: ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/StringAppend.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/StringAppend.java?rev=1349646&r1=1349645&r2=1349646&view=diff ============================================================================== --- ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/StringAppend.java (original) +++ ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/envops/StringAppend.java Wed Jun 13 06:04:49 2012 @@ -20,110 +20,106 @@ package org.ofbiz.minilang.method.envops import java.text.MessageFormat; 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.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.w3c.dom.Element; /** - * Appends the specified String to a field + * Implements the <string-append> element. */ -public class StringAppend extends MethodOperation { - - public static final String module = StringAppend.class.getName(); +public final class StringAppend extends MethodOperation { - ContextAccessor<List<? extends Object>> argListAcsr; - ContextAccessor<String> fieldAcsr; - ContextAccessor<Map<String, Object>> mapAcsr; - String prefix; - String string; - String suffix; + private final FlexibleMapAccessor<List<? extends Object>> argListFma; + private final FlexibleMapAccessor<String> fieldFma; + private final FlexibleStringExpander prefixFse; + private final FlexibleStringExpander stringFse; + private final FlexibleStringExpander suffixFse; public StringAppend(Element element, SimpleMethod simpleMethod) throws MiniLangException { super(element, simpleMethod); - string = element.getAttribute("string"); - prefix = element.getAttribute("prefix"); - suffix = element.getAttribute("suffix"); - // the schema for this element now just has the "field" attribute, though the old "field-name" and "map-name" pair is still supported - fieldAcsr = new ContextAccessor<String>(element.getAttribute("field"), element.getAttribute("field-name")); - mapAcsr = new ContextAccessor<Map<String, Object>>(element.getAttribute("map-name")); - argListAcsr = new ContextAccessor<List<? extends Object>>(element.getAttribute("arg-list"), element.getAttribute("arg-list-name")); - } - - public String appendString(String oldValue, MethodContext methodContext) { - String value = methodContext.expandString(string); - String prefixValue = methodContext.expandString(prefix); - String suffixValue = methodContext.expandString(suffix); - if (!argListAcsr.isEmpty()) { - List<? extends Object> argList = argListAcsr.get(methodContext); - if (UtilValidate.isNotEmpty(argList)) { - value = MessageFormat.format(value, argList.toArray()); - } - } - StringBuilder newValue = new StringBuilder(); - if (UtilValidate.isNotEmpty(value)) { - if (UtilValidate.isEmpty(oldValue)) { - newValue.append(value); - } else { - newValue.append(oldValue); - if (prefixValue != null) - newValue.append(prefixValue); - newValue.append(value); - if (suffixValue != null) - newValue.append(suffixValue); - } - } else { - if (UtilValidate.isEmpty(oldValue)) { - newValue.append(oldValue); - } + if (MiniLangValidate.validationOn()) { + MiniLangValidate.attributeNames(simpleMethod, element, "field", "arg-list", "prefix", "string", "suffix"); + MiniLangValidate.requiredAttributes(simpleMethod, element, "field", "string"); + MiniLangValidate.expressionAttributes(simpleMethod, element, "field", "arg-list"); + MiniLangValidate.noChildElements(simpleMethod, element); } - return newValue.toString(); + argListFma = FlexibleMapAccessor.getInstance(element.getAttribute("arg-list")); + fieldFma = FlexibleMapAccessor.getInstance(element.getAttribute("field")); + prefixFse = FlexibleStringExpander.getInstance(element.getAttribute("prefix")); + stringFse = FlexibleStringExpander.getInstance(element.getAttribute("string")); + suffixFse = FlexibleStringExpander.getInstance(element.getAttribute("suffix")); } @Override public boolean exec(MethodContext methodContext) throws MiniLangException { - if (!mapAcsr.isEmpty()) { - Map<String, Object> toMap = mapAcsr.get(methodContext); - if (toMap == null) { - if (Debug.verboseOn()) - Debug.logVerbose("Map not found with name " + mapAcsr + ", creating new map", module); - toMap = FastMap.newInstance(); - mapAcsr.put(methodContext, toMap); + String value = stringFse.expandString(methodContext.getEnvMap()); + List<? extends Object> argList = argListFma.get(methodContext.getEnvMap()); + if (argList != null) { + try { + value = MessageFormat.format(value, argList.toArray()); + } catch (IllegalArgumentException e) { + throw new MiniLangRuntimeException("Exception thrown while formatting the string attribute: " + e.getMessage(), this); } - String oldValue = fieldAcsr.get(toMap, methodContext); - fieldAcsr.put(toMap, this.appendString(oldValue, methodContext), methodContext); - } else { - String oldValue = fieldAcsr.get(methodContext); - fieldAcsr.put(methodContext, this.appendString(oldValue, methodContext)); + } + if (!value.isEmpty()) { + String prefixValue = prefixFse.expandString(methodContext.getEnvMap()); + String suffixValue = suffixFse.expandString(methodContext.getEnvMap()); + StringBuilder newValue = new StringBuilder(); + String oldValue = fieldFma.get(methodContext.getEnvMap()); + if (oldValue != null) { + newValue.append(oldValue); + } + newValue.append(prefixValue).append(value).append(suffixValue); + fieldFma.put(methodContext.getEnvMap(), newValue.toString()); } 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: something more than the empty tag - return "<string-append string=\"" + this.string + "\" prefix=\"" + this.prefix + "\" suffix=\"" + this.suffix + "\" field-name=\"" + this.fieldAcsr + "\" map-name=\"" + this.mapAcsr + "\"/>"; + return toString(); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("<string-append "); + sb.append("field=\"").append(this.fieldFma).append("\" "); + sb.append("string=\"").append(this.stringFse).append("\" "); + if (!this.argListFma.isEmpty()) { + sb.append("arg-list=\"").append(this.argListFma).append("\" "); + } + if (!this.prefixFse.isEmpty()) { + sb.append("prefix=\"").append(this.prefixFse).append("\" "); + } + if (!this.suffixFse.isEmpty()) { + sb.append("suffix=\"").append(this.suffixFse).append("\" "); + } + sb.append("/>"); + return sb.toString(); } + /** + * A factory for the <string-append> element. + */ public static final class StringAppendFactory implements Factory<StringAppend> { + @Override public StringAppend createMethodOperation(Element element, SimpleMethod simpleMethod) throws MiniLangException { return new StringAppend(element, simpleMethod); } + @Override public String getName() { return "string-append"; } |
| Free forum by Nabble | Edit this page |
