Author: adrianc
Date: Thu Jun 14 17:00:53 2012
New Revision: 1350337
URL: http://svn.apache.org/viewvc?rev=1350337&view=rev
Log:
Overhauled Mini-language <property-to-field> element.
The overhaul includes: removing unnecessary object creation, make the class
thread-safe, add syntax validation, and misc code cleanups.
Modified:
ofbiz/trunk/framework/minilang/dtd/simple-methods-v2.xsd
ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/otherops/PropertyToField.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=1350337&r1=1350336&r2=1350337&view=diff
==============================================================================
--- ofbiz/trunk/framework/minilang/dtd/simple-methods-v2.xsd (original)
+++ ofbiz/trunk/framework/minilang/dtd/simple-methods-v2.xsd Thu Jun 14
17:00:53 2012
@@ -4207,58 +4207,71 @@ under the License.
<xs:element name="property-to-field" substitutionGroup="OtherOperations">
<xs:annotation>
<xs:documentation>
- The property-to-field tag puts the inlined string value in the
specified field.
+ Assigns a property value to a field.
</xs:documentation>
</xs:annotation>
<xs:complexType>
- <xs:attributeGroup ref="attlist.property-to-field"/>
+ <xs:attribute ref="field" />
+ <xs:attribute type="xs:string" name="resource" use="required">
+ <xs:annotation>
+ <xs:documentation>
+ The name of a properties resource. Can be a file on
the classpath or
+ a resource defined in the SystemProperty entity.
+ <br/><br/>
+ Required. Attribute types: constant, ${expression}.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute type="xs:string" name="property" use="required">
+ <xs:annotation>
+ <xs:documentation>
+ The property whose value will be put in the field.
+ <br/><br/>
+ Required. Attribute types: constant, ${expression}.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute type="xs:string" name="default">
+ <xs:annotation>
+ <xs:documentation>
+ The default value to use if the specified property
value is null or empty.
+ <br/><br/>
+ Optional. Attribute types: constant, ${expression}.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <xs:attribute type="booleanConst" name="no-locale">
+ <xs:annotation>
+ <xs:documentation>
+ Suppress property value localization. The
user's/system locale will be ignored
+ when retriving the property value.
+ Defaults to "false".
+ <br/><br/>
+ Optional. Attribute type: constant.
+ </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 property 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="arg-list-name">
+ <xs:annotation>
+ <xs:documentation>
+ Deprecated - use the arg-list attribute.
+ </xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
</xs:complexType>
</xs:element>
- <xs:attributeGroup name="attlist.property-to-field">
- <xs:attribute type="xs:string" name="resource" use="required">
- <xs:annotation>
- <xs:documentation>
- Name of a properties file on the classpath.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute type="xs:string" name="property" use="required">
- <xs:annotation>
- <xs:documentation>
- The property whose value will be put in the field.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <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="default">
- <xs:annotation>
- <xs:documentation>
- The default value to use if the specified property is
empty.
- </xs:documentation>
- </xs:annotation>
- </xs:attribute>
- <xs:attribute name="no-locale" default="false">
- <xs:annotation>
- <xs:documentation>
- If sets to true don't use the default locale variable.
- Defaults 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="arg-list-name"/>
- </xs:attributeGroup>
<xs:element name="set-current-user-login"
substitutionGroup="OtherOperations">
<xs:annotation>
<xs:documentation>
@@ -4299,6 +4312,8 @@ under the License.
<xs:documentation>
Rounding mode for BigDecimal calculation, primarily
for divide operation.
Defaults to "HalfEven".
+ <br/><br/>
+ Optional. Attribute types: constant, ${expression}.
</xs:documentation>
</xs:annotation>
<xs:simpleType>
@@ -4373,6 +4388,8 @@ under the License.
<xs:annotation>
<xs:documentation>
Initial scale to use for the internal BigDecimal.
Defaults to "2".
+ <br/><br/>
+ Optional. Attribute types: constant, ${expression}.
</xs:documentation>
</xs:annotation>
</xs:attribute>
@@ -4380,6 +4397,8 @@ under the License.
<xs:annotation>
<xs:documentation>
Decimal format to use for conversion to string.
+ <br/><br/>
+ Optional. Attribute types: constant, ${expression}.
</xs:documentation>
</xs:annotation>
</xs:attribute>
@@ -4387,6 +4406,8 @@ under the License.
<xs:annotation>
<xs:documentation>
Data type of the calculation result. Defaults to
"BigDecimal".
+ <br/><br/>
+ Optional. Attribute types: constant, ${expression}.
</xs:documentation>
</xs:annotation>
<xs:simpleType>
@@ -4432,7 +4453,7 @@ under the License.
<xs:enumeration value="negative">
<xs:annotation>
<xs:documentation>
- Negates the value
+ Negates the value.
</xs:documentation>
</xs:annotation>
</xs:enumeration>
@@ -4460,6 +4481,8 @@ under the License.
<xs:annotation>
<xs:documentation>
Literal or flexible string.
+ <br/><br/>
+ Required. Attribute types: constant, ${expression}.
</xs:documentation>
</xs:annotation>
</xs:attribute>
Modified:
ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/otherops/PropertyToField.java
URL:
http://svn.apache.org/viewvc/ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/otherops/PropertyToField.java?rev=1350337&r1=1350336&r2=1350337&view=diff
==============================================================================
---
ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/otherops/PropertyToField.java
(original)
+++
ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/otherops/PropertyToField.java
Thu Jun 14 17:00:53 2012
@@ -20,103 +20,129 @@ package org.ofbiz.minilang.method.othero
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.entity.util.EntityUtilProperties;
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;
/**
- * Copies an properties file property value to a field
+ * Implements the <property-to-field> element.
*/
-public class PropertyToField extends MethodOperation {
+public final class PropertyToField extends MethodOperation {
- public static final String module = PropertyToField.class.getName();
+ // This method is needed only during the v1 to v2 transition
+ private static boolean autoCorrect(Element element) {
+ // Correct deprecated arg-list-name attribute
+ String listAttr = element.getAttribute("arg-list-name");
+ if (listAttr.length() > 0) {
+ element.setAttribute("arg-list", listAttr);
+ element.removeAttribute("arg-list-name");
+ return true;
+ }
+ return false;
+ }
- ContextAccessor<List<? extends Object>> argListAcsr;
- String defaultVal;
- ContextAccessor<Object> fieldAcsr;
- ContextAccessor<Map<String, Object>> mapAcsr;
- boolean noLocale;
- String property;
- String resource;
+ private final FlexibleMapAccessor<List<? extends Object>> argListFma;
+ private final FlexibleStringExpander defaultFse;
+ private final FlexibleMapAccessor<Object> fieldFma;
+ private final boolean noLocale;
+ private final FlexibleStringExpander propertyFse;
+ private final FlexibleStringExpander resourceFse;
public PropertyToField(Element element, SimpleMethod simpleMethod) throws
MiniLangException {
super(element, simpleMethod);
- resource = element.getAttribute("resource");
- property = element.getAttribute("property");
- // the schema for this element now just has the "field" attribute,
though the old "field-name" and "map-name" pair is still supported
- this.fieldAcsr = new
ContextAccessor<Object>(element.getAttribute("field"),
element.getAttribute("field-name"));
- this.mapAcsr = new ContextAccessor<Map<String,
Object>>(element.getAttribute("map-name"));
- defaultVal = element.getAttribute("default");
- // defaults to false, ie anything but true is false
+ if (MiniLangValidate.validationOn()) {
+ MiniLangValidate.deprecatedAttribute(simpleMethod, element,
"arg-list-name", "replace with \"arg-list\"");
+ MiniLangValidate.attributeNames(simpleMethod, element, "field",
"resource", "property", "arg-list", "default", "no-locale");
+ MiniLangValidate.requiredAttributes(simpleMethod, element,
"field", "resource", "property");
+ MiniLangValidate.expressionAttributes(simpleMethod, element,
"field", "arg-list");
+ MiniLangValidate.noChildElements(simpleMethod, element);
+ }
+ boolean elementModified = autoCorrect(element);
+ if (elementModified && MiniLangUtil.autoCorrectOn()) {
+ MiniLangUtil.flagDocumentAsCorrected(element);
+ }
+ fieldFma =
FlexibleMapAccessor.getInstance(element.getAttribute("field"));
+ resourceFse =
FlexibleStringExpander.getInstance(element.getAttribute("resource"));
+ propertyFse =
FlexibleStringExpander.getInstance(element.getAttribute("property"));
+ argListFma =
FlexibleMapAccessor.getInstance(element.getAttribute("arg-list"));
+ defaultFse =
FlexibleStringExpander.getInstance(element.getAttribute("default"));
noLocale = "true".equals(element.getAttribute("no-locale"));
- argListAcsr = new ContextAccessor<List<? extends
Object>>(element.getAttribute("arg-list-name"));
}
@Override
public boolean exec(MethodContext methodContext) throws MiniLangException {
- String resource = methodContext.expandString(this.resource);
- String property = methodContext.expandString(this.property);
+ String resource = resourceFse.expandString(methodContext.getEnvMap());
+ String property = propertyFse.expandString(methodContext.getEnvMap());
String value = null;
if (noLocale) {
value = EntityUtilProperties.getPropertyValue(resource, property,
methodContext.getDelegator());
} else {
value = EntityUtilProperties.getMessage(resource, property,
methodContext.getLocale(), methodContext.getDelegator());
}
- if (UtilValidate.isEmpty(value)) {
- value = defaultVal;
- }
- // note that expanding the value string here will handle defaultValue
and the string from
- // the properties file; if we decide later that we don't want the
string from the properties
- // file to be expanded we should just expand the defaultValue at the
beginning of this method.
- value = methodContext.expandString(value);
- if (!argListAcsr.isEmpty()) {
- List<? extends Object> argList = argListAcsr.get(methodContext);
- if (UtilValidate.isNotEmpty(argList)) {
+ value = FlexibleStringExpander.expandString(value,
methodContext.getEnvMap());
+ if (value.isEmpty()) {
+ value = defaultFse.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 property value: " + e.getMessage(), this);
}
}
- if (!mapAcsr.isEmpty()) {
- Map<String, Object> toMap = mapAcsr.get(methodContext);
- if (toMap == null) {
- if (Debug.infoOn())
- Debug.logInfo("Map not found with name " + mapAcsr + ",
creating new map", module);
- toMap = FastMap.newInstance();
- mapAcsr.put(methodContext, toMap);
- }
- fieldAcsr.put(toMap, value, methodContext);
- } else {
- fieldAcsr.put(methodContext, value);
- }
+ fieldFma.put(methodContext.getEnvMap(), value);
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 "<property-to-field field-name=\"" + this.fieldAcsr + "\"
map-name=\"" + this.mapAcsr + "\"/>";
+ return toString();
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sb = new StringBuilder("<property-to-field ");
+ sb.append("field=\"").append(this.fieldFma).append("\" ");
+ sb.append("resource=\"").append(this.resourceFse).append("\" ");
+ sb.append("property=\"").append(this.propertyFse).append("\" ");
+ if (!this.argListFma.isEmpty()) {
+ sb.append("arg-list=\"").append(this.argListFma).append("\" ");
+ }
+ if (!this.defaultFse.isEmpty()) {
+ sb.append("default=\"").append(this.defaultFse).append("\" ");
+ }
+ if (noLocale) {
+ sb.append("no-locale=\"true\" ");
+ }
+ sb.append("/>");
+ return sb.toString();
}
+ /**
+ * A factory for the <property-to-field> element.
+ */
public static final class PropertyToFieldFactory implements
Factory<PropertyToField> {
+ @Override
public PropertyToField createMethodOperation(Element element,
SimpleMethod simpleMethod) throws MiniLangException {
return new PropertyToField(element, simpleMethod);
}
+ @Override
public String getName() {
return "property-to-field";
}