|
Author: adrianc
Date: Mon May 14 14:11:33 2012 New Revision: 1338212 URL: http://svn.apache.org/viewvc?rev=1338212&view=rev Log: Modified the Mini-language comparison elements: 1. Moved comparison logic from ObjectType.java to the minilanguage component and improved it to be more modular. 2. Moved object type conversion from ObjectType.java to the minilanguage component and simplified it. 3. Modified comparison elements to use new comparison logic and object type conversion. Added: ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/conditional/Compare.java (with props) Modified: ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/MiniLangUtil.java ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/conditional/CompareCondition.java ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/conditional/CompareFieldCondition.java ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/ifops/IfCompare.java ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/ifops/IfCompareField.java ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/serviceops/FieldToResult.java Modified: ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/MiniLangUtil.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/MiniLangUtil.java?rev=1338212&r1=1338211&r2=1338212&view=diff ============================================================================== --- ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/MiniLangUtil.java (original) +++ ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/MiniLangUtil.java Mon May 14 14:11:33 2012 @@ -26,12 +26,17 @@ import java.net.URL; import java.util.Collections; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Set; +import java.util.TimeZone; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.stream.StreamSource; +import org.ofbiz.base.conversion.Converter; +import org.ofbiz.base.conversion.Converters; +import org.ofbiz.base.conversion.LocalizedConverter; import org.ofbiz.base.location.FlexibleLocation; import org.ofbiz.base.util.Debug; import org.ofbiz.base.util.ScriptUtil; @@ -40,6 +45,7 @@ import org.ofbiz.base.util.UtilValidate; import org.ofbiz.base.util.UtilXml; import org.ofbiz.base.util.collections.FlexibleMapAccessor; import org.ofbiz.base.util.string.FlexibleStringExpander; +import org.ofbiz.entity.GenericEntity; import org.ofbiz.minilang.method.MethodContext; import org.ofbiz.minilang.method.MethodObject; import org.ofbiz.minilang.method.MethodOperation; @@ -72,6 +78,7 @@ import org.ofbiz.minilang.method.ifops.I import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; /** * Mini-language utilities. @@ -135,6 +142,45 @@ public final class MiniLangUtil { } } + @SuppressWarnings("unchecked") + public static Object convertType(Object obj, Class<?> targetClass, Locale locale, TimeZone timeZone, String format) throws Exception { + if (obj == null || obj == GenericEntity.NULL_FIELD) { + return null; + } + if (obj instanceof Node) { + Node node = (Node) obj; + String nodeValue = node.getTextContent(); + if (targetClass == String.class) { + return nodeValue; + } else { + return convertType(nodeValue, targetClass, locale, timeZone, format); + } + } + if (targetClass == PlainString.class) { + return obj.toString(); + } + Class<?> sourceClass = obj.getClass(); + if (sourceClass == targetClass) { + return obj; + } + Converter<Object, Object> converter = (Converter<Object, Object>) Converters.getConverter(sourceClass, targetClass); + LocalizedConverter<Object, Object> localizedConverter = null; + try { + localizedConverter = (LocalizedConverter) converter; + if (locale == null) { + locale = Locale.getDefault(); + } + if (timeZone == null) { + timeZone = TimeZone.getDefault(); + } + if (format != null && format.isEmpty()) { + format = null; + } + return localizedConverter.convert(obj, locale, timeZone, format); + } catch (ClassCastException e) {} + return converter.convert(obj); + } + public static void findEntityNamesUsed(List<MethodOperation> methodOperations, Set<String> allEntityNames, Set<String> simpleMethodsVisited) throws MiniLangException { for (MethodOperation methodOperation : methodOperations) { if (methodOperation instanceof FindByPrimaryKey) { @@ -284,6 +330,22 @@ public final class MiniLangUtil { } } + public static Class<?> getObjectClassForConversion(Object object) { + if (object == null || object instanceof String) { + return PlainString.class; + } else { + if (object instanceof java.util.Map<?, ?>) { + return java.util.Map.class; + } else if (object instanceof java.util.List<?>) { + return java.util.List.class; + } else if (object instanceof java.util.Set<?>) { + return java.util.Set.class; + } else { + return object.getClass(); + } + } + } + public static boolean isConstantAttribute(String attributeValue) { if (attributeValue.length() > 0) { return !FlexibleStringExpander.containsExpression(FlexibleStringExpander.getInstance(attributeValue)); @@ -369,5 +431,7 @@ public final class MiniLangUtil { } } + public static class PlainString {} + private MiniLangUtil() {} } Added: ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/conditional/Compare.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/conditional/Compare.java?rev=1338212&view=auto ============================================================================== --- ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/conditional/Compare.java (added) +++ ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/conditional/Compare.java Mon May 14 14:11:33 2012 @@ -0,0 +1,298 @@ +/******************************************************************************* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + *******************************************************************************/ +package org.ofbiz.minilang.method.conditional; + +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.TimeZone; + +import org.ofbiz.base.util.Assert; +import org.ofbiz.base.util.UtilValidate; +import org.ofbiz.entity.GenericEntity; +import org.ofbiz.minilang.MiniLangUtil; + +/** + * Implements a comparison - consisting of an l-value, an r-value, and a comparison operator. + */ +public abstract class Compare { + + private static final Map<String, Compare> INSTANCE_MAP = createInstanceMap(); + + private static void assertValuesNotNull(Object lValue, Object rValue) { + if (lValue == null) { + throw new IllegalArgumentException("Cannot compare: l-value is null"); + } + if (rValue == null) { + throw new IllegalArgumentException("Cannot compare: r-value is null"); + } + } + + private static int compareBigDecimals(BigDecimal lBigDecimal, BigDecimal rBigDecimal) { + // Developers: Do not change this. We are comparing two fixed-point decimal numbers, + // not performing accounting calculations - so it is okay to specify the rounding mode. + int decimals = lBigDecimal.scale(); + if (rBigDecimal.scale() < decimals) { + lBigDecimal = lBigDecimal.setScale(rBigDecimal.scale(), RoundingMode.UP); + } else if (decimals < rBigDecimal.scale()) { + rBigDecimal = rBigDecimal.setScale(decimals, RoundingMode.UP); + } + return lBigDecimal.compareTo(rBigDecimal); + } + + private static Map<String, Compare> createInstanceMap() { + Map<String, Compare> writableMap = new HashMap<String, Compare>(10); + writableMap.put("contains", new CompareContains()); + writableMap.put("equals", new CompareEquals()); + writableMap.put("greater", new CompareGreater()); + writableMap.put("greater-equals", new CompareGreaterEquals()); + writableMap.put("is-empty", new CompareIsEmpty()); + writableMap.put("is-not-null", new CompareIsNotNull()); + writableMap.put("is-null", new CompareIsNull()); + writableMap.put("less", new CompareLess()); + writableMap.put("less-equals", new CompareLessEquals()); + writableMap.put("not-equals", new CompareNotEquals()); + return Collections.unmodifiableMap(writableMap); + } + + /** + * Returns a <code>Compare</code> instance for the specified operator. + * + * @param operator + * @return + */ + public static Compare getInstance(String operator) { + Assert.notNull("operator", operator); + return INSTANCE_MAP.get(operator); + } + + /** + * Returns the result of this comparison. + * + * @param lValue The object being compared + * @param rValue The object being compared to + * @param type The Java class to be used in the comparison + * @param format Optional format to be used in object type conversions + * @param locale Optional locale to be used in object type conversions + * @param timeZone Optional time zone to be used in object type conversions + * @return + * @throws Exception + */ + public abstract boolean doCompare(Object lValue, Object rValue, Class<?> type, Locale locale, TimeZone timeZone, String format) throws Exception; + + private static final class CompareContains extends Compare { + + @SuppressWarnings("unchecked") + @Override + public boolean doCompare(Object lValue, Object rValue, Class<?> type, Locale locale, TimeZone timeZone, String format) throws Exception { + // The type parameter is ignored when using the contains operator, so no conversions will be performed. + if (lValue == null || lValue == GenericEntity.NULL_FIELD) { + return false; + } + try { + Collection collection = (Collection) lValue; + return collection.contains(rValue); + } catch (ClassCastException e) { + } + if (lValue instanceof String && rValue instanceof String) { + return ((String) lValue).contains((String) rValue); + } + throw new IllegalArgumentException("Cannot compare: l-value is not a collection"); + } + } + + private static final class CompareEquals extends Compare { + + @SuppressWarnings("unchecked") + @Override + public boolean doCompare(Object lValue, Object rValue, Class<?> type, Locale locale, TimeZone timeZone, String format) throws Exception { + Object convertedLvalue = MiniLangUtil.convertType(lValue, type, locale, timeZone, format); + Object convertedRvalue = MiniLangUtil.convertType(rValue, type, locale, timeZone, format); + if (convertedLvalue == null) { + return convertedRvalue == null; + } + if (convertedRvalue == null) { + return false; + } + try { + BigDecimal lBigDecimal = (BigDecimal) convertedLvalue; + BigDecimal rBigDecimal = (BigDecimal) convertedRvalue; + return compareBigDecimals(lBigDecimal, rBigDecimal) == 0; + } catch (ClassCastException e) { + } + try { + Comparable comparable = (Comparable) convertedLvalue; + return comparable.compareTo(convertedRvalue) == 0; + } catch (ClassCastException e) { + } + return convertedLvalue.equals(convertedRvalue); + } + } + + private static final class CompareGreater extends Compare { + + @SuppressWarnings("unchecked") + @Override + public boolean doCompare(Object lValue, Object rValue, Class<?> type, Locale locale, TimeZone timeZone, String format) throws Exception { + Object convertedLvalue = MiniLangUtil.convertType(lValue, type, locale, timeZone, format); + Object convertedRvalue = MiniLangUtil.convertType(rValue, type, locale, timeZone, format); + assertValuesNotNull(convertedLvalue, convertedRvalue); + try { + BigDecimal lBigDecimal = (BigDecimal) convertedLvalue; + BigDecimal rBigDecimal = (BigDecimal) convertedRvalue; + return compareBigDecimals(lBigDecimal, rBigDecimal) > 0; + } catch (ClassCastException e) { + } + try { + Comparable comparable = (Comparable) convertedLvalue; + return comparable.compareTo(convertedRvalue) > 0; + } catch (ClassCastException e) { + } + throw new IllegalArgumentException("Cannot compare: l-value is not a comparable type"); + } + } + + private static final class CompareGreaterEquals extends Compare { + + @SuppressWarnings("unchecked") + @Override + public boolean doCompare(Object lValue, Object rValue, Class<?> type, Locale locale, TimeZone timeZone, String format) throws Exception { + Object convertedLvalue = MiniLangUtil.convertType(lValue, type, locale, timeZone, format); + Object convertedRvalue = MiniLangUtil.convertType(rValue, type, locale, timeZone, format); + assertValuesNotNull(convertedLvalue, convertedRvalue); + try { + BigDecimal lBigDecimal = (BigDecimal) convertedLvalue; + BigDecimal rBigDecimal = (BigDecimal) convertedRvalue; + return compareBigDecimals(lBigDecimal, rBigDecimal) >= 0; + } catch (ClassCastException e) { + } + try { + Comparable comparable = (Comparable) convertedLvalue; + return comparable.compareTo(convertedRvalue) >= 0; + } catch (ClassCastException e) { + } + throw new IllegalArgumentException("Cannot compare: l-value is not a comparable type"); + } + } + + private static final class CompareIsEmpty extends Compare { + + @Override + public boolean doCompare(Object lValue, Object rValue, Class<?> type, Locale locale, TimeZone timeZone, String format) throws Exception { + Object convertedLvalue = MiniLangUtil.convertType(lValue, type, locale, timeZone, format); + return UtilValidate.isEmpty(convertedLvalue); + } + } + + private static final class CompareIsNotNull extends Compare { + + @Override + public boolean doCompare(Object lValue, Object rValue, Class<?> type, Locale locale, TimeZone timeZone, String format) throws Exception { + Object convertedLvalue = MiniLangUtil.convertType(lValue, type, locale, timeZone, format); + return convertedLvalue != null; + } + } + + private static final class CompareIsNull extends Compare { + + @Override + public boolean doCompare(Object lValue, Object rValue, Class<?> type, Locale locale, TimeZone timeZone, String format) throws Exception { + Object convertedLvalue = MiniLangUtil.convertType(lValue, type, locale, timeZone, format); + return convertedLvalue == null; + } + } + + private static final class CompareLess extends Compare { + + @SuppressWarnings("unchecked") + @Override + public boolean doCompare(Object lValue, Object rValue, Class<?> type, Locale locale, TimeZone timeZone, String format) throws Exception { + Object convertedLvalue = MiniLangUtil.convertType(lValue, type, locale, timeZone, format); + Object convertedRvalue = MiniLangUtil.convertType(rValue, type, locale, timeZone, format); + assertValuesNotNull(convertedLvalue, convertedRvalue); + try { + BigDecimal lBigDecimal = (BigDecimal) convertedLvalue; + BigDecimal rBigDecimal = (BigDecimal) convertedRvalue; + return compareBigDecimals(lBigDecimal, rBigDecimal) < 0; + } catch (ClassCastException e) { + } + try { + Comparable comparable = (Comparable) convertedLvalue; + return comparable.compareTo(convertedRvalue) < 0; + } catch (ClassCastException e) { + } + throw new IllegalArgumentException("Cannot compare: l-value is not a comparable type"); + } + } + + private static final class CompareLessEquals extends Compare { + + @SuppressWarnings("unchecked") + @Override + public boolean doCompare(Object lValue, Object rValue, Class<?> type, Locale locale, TimeZone timeZone, String format) throws Exception { + Object convertedLvalue = MiniLangUtil.convertType(lValue, type, locale, timeZone, format); + Object convertedRvalue = MiniLangUtil.convertType(rValue, type, locale, timeZone, format); + assertValuesNotNull(convertedLvalue, convertedRvalue); + try { + BigDecimal lBigDecimal = (BigDecimal) convertedLvalue; + BigDecimal rBigDecimal = (BigDecimal) convertedRvalue; + return compareBigDecimals(lBigDecimal, rBigDecimal) <= 0; + } catch (ClassCastException e) { + } + try { + Comparable comparable = (Comparable) convertedLvalue; + return comparable.compareTo(convertedRvalue) <= 0; + } catch (ClassCastException e) { + } + throw new IllegalArgumentException("Cannot compare: l-value is not a comparable type"); + } + } + + private static final class CompareNotEquals extends Compare { + + @SuppressWarnings("unchecked") + @Override + public boolean doCompare(Object lValue, Object rValue, Class<?> type, Locale locale, TimeZone timeZone, String format) throws Exception { + Object convertedLvalue = MiniLangUtil.convertType(lValue, type, locale, timeZone, format); + Object convertedRvalue = MiniLangUtil.convertType(rValue, type, locale, timeZone, format); + if (convertedLvalue == null) { + return convertedRvalue != null; + } + if (convertedRvalue == null) { + return true; + } + try { + BigDecimal lBigDecimal = (BigDecimal) convertedLvalue; + BigDecimal rBigDecimal = (BigDecimal) convertedRvalue; + return compareBigDecimals(lBigDecimal, rBigDecimal) != 0; + } catch (ClassCastException e) { + } + try { + Comparable comparable = (Comparable) convertedLvalue; + return comparable.compareTo(convertedRvalue) != 0; + } catch (ClassCastException e) { + } + return !convertedLvalue.equals(convertedRvalue); + } + } +} Propchange: ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/conditional/Compare.java ------------------------------------------------------------------------------ svn:eol-style = native Propchange: ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/conditional/Compare.java ------------------------------------------------------------------------------ svn:keywords = Author Date Id Rev URL Modified: ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/conditional/CompareCondition.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/conditional/CompareCondition.java?rev=1338212&r1=1338211&r2=1338212&view=diff ============================================================================== --- ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/conditional/CompareCondition.java (original) +++ ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/conditional/CompareCondition.java Mon May 14 14:11:33 2012 @@ -18,10 +18,6 @@ *******************************************************************************/ package org.ofbiz.minilang.method.conditional; -import java.util.List; - -import javolution.util.FastList; - import org.ofbiz.base.util.ObjectType; import org.ofbiz.base.util.UtilValidate; import org.ofbiz.base.util.collections.FlexibleMapAccessor; @@ -29,6 +25,7 @@ import org.ofbiz.base.util.string.Flexib import org.ofbiz.minilang.MiniLangElement; 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.MethodContext; @@ -39,11 +36,11 @@ import org.w3c.dom.Element; */ public final class CompareCondition extends MiniLangElement implements Conditional { - public static final String module = CompareCondition.class.getName(); - + private final Compare compare; private final FlexibleMapAccessor<Object> fieldFma; private final FlexibleStringExpander formatFse; private final String operator; + private final Class<?> targetClass; private final String type; private final FlexibleStringExpander valueFse; @@ -60,27 +57,46 @@ public final class CompareCondition exte this.fieldFma = FlexibleMapAccessor.getInstance(element.getAttribute("field")); this.formatFse = FlexibleStringExpander.getInstance(element.getAttribute("format")); this.operator = element.getAttribute("operator"); - this.type = MiniLangValidate.checkAttribute(element.getAttribute("type"), "PlainString"); + this.compare = Compare.getInstance(this.operator); + if (this.compare == null) { + MiniLangValidate.handleError("Invalid operator " + this.operator, simpleMethod, element); + } + this.type = element.getAttribute("type"); + Class<?> targetClass = null; + if (!this.type.isEmpty()) { + if ("contains".equals(this.operator)) { + MiniLangValidate.handleError("Operator \"contains\" does not support type conversions (remove the type attribute).", simpleMethod, element); + targetClass = Object.class; + } else { + try { + targetClass = ObjectType.loadClass(this.type); + } catch (ClassNotFoundException e) { + MiniLangValidate.handleError("Invalid type " + this.type, simpleMethod, element); + } + } + } + this.targetClass = targetClass; this.valueFse = FlexibleStringExpander.getInstance(element.getAttribute("value")); } @Override - public boolean checkCondition(MethodContext methodContext) throws MiniLangRuntimeException { + public boolean checkCondition(MethodContext methodContext) throws MiniLangException { + if (this.compare == null) { + throw new MiniLangRuntimeException("Invalid operator " + this.operator, this); + } Object fieldVal = fieldFma.get(methodContext.getEnvMap()); - if (fieldVal == null) { - fieldVal = ""; + Class<?> targetClass = this.targetClass; + if (targetClass == null) { + targetClass = MiniLangUtil.getObjectClassForConversion(fieldVal); } String value = valueFse.expandString(methodContext.getEnvMap()); String format = formatFse.expandString(methodContext.getEnvMap()); - List<Object> errorMessages = FastList.newInstance(); - Boolean resultBool = ObjectType.doRealCompare(fieldVal, value, operator, type, format, errorMessages, methodContext.getLocale(), methodContext.getLoader(), true); - if (errorMessages.size() > 0 || resultBool == null) { - for (Object obj : errorMessages) { - simpleMethod.addErrorMessage(methodContext, (String) obj); - } - return false; + try { + return this.compare.doCompare(fieldVal, value, targetClass, methodContext.getLocale(), methodContext.getTimeZone(), format); + } catch (Exception e) { + simpleMethod.addErrorMessage(methodContext, e.getMessage()); } - return resultBool.booleanValue(); + return false; } public void prettyPrint(StringBuilder messageBuffer, MethodContext methodContext) { Modified: ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/conditional/CompareFieldCondition.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/conditional/CompareFieldCondition.java?rev=1338212&r1=1338211&r2=1338212&view=diff ============================================================================== --- ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/conditional/CompareFieldCondition.java (original) +++ ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/conditional/CompareFieldCondition.java Mon May 14 14:11:33 2012 @@ -18,16 +18,13 @@ *******************************************************************************/ package org.ofbiz.minilang.method.conditional; -import java.util.List; - -import javolution.util.FastList; - import org.ofbiz.base.util.ObjectType; import org.ofbiz.base.util.UtilValidate; import org.ofbiz.base.util.collections.FlexibleMapAccessor; import org.ofbiz.base.util.string.FlexibleStringExpander; import org.ofbiz.minilang.MiniLangElement; 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; @@ -39,8 +36,6 @@ import org.w3c.dom.Element; */ public final class CompareFieldCondition extends MiniLangElement implements Conditional { - public static final String module = CompareFieldCondition.class.getName(); - // This method is needed only during the v1 to v2 transition private static boolean autoCorrect(Element element) { // Correct missing to-field attribute @@ -52,10 +47,12 @@ public final class CompareFieldCondition return false; } + private final Compare compare; private final FlexibleMapAccessor<Object> fieldFma; private final FlexibleStringExpander formatFse; private final String operator; private final FlexibleMapAccessor<Object> toFieldFma; + private final Class<?> targetClass; private final String type; public CompareFieldCondition(Element element, SimpleMethod simpleMethod) throws MiniLangException { @@ -74,24 +71,41 @@ public final class CompareFieldCondition this.fieldFma = FlexibleMapAccessor.getInstance(element.getAttribute("field")); this.formatFse = FlexibleStringExpander.getInstance(element.getAttribute("format")); this.operator = element.getAttribute("operator"); + this.compare = Compare.getInstance(this.operator); + if (this.compare == null) { + MiniLangValidate.handleError("Invalid operator " + this.operator, simpleMethod, element); + } this.toFieldFma = FlexibleMapAccessor.getInstance(element.getAttribute("to-field")); - this.type = MiniLangValidate.checkAttribute(element.getAttribute("type"), "PlainString"); + this.type = element.getAttribute("type"); + Class<?> targetClass = null; + if (!this.type.isEmpty()) { + try { + targetClass = ObjectType.loadClass(this.type); + } catch (ClassNotFoundException e) { + MiniLangValidate.handleError("Invalid type " + this.type, simpleMethod, element); + } + } + this.targetClass = targetClass; } @Override public boolean checkCondition(MethodContext methodContext) throws MiniLangException { + if (this.compare == null) { + throw new MiniLangRuntimeException("Invalid operator " + this.operator, this); + } Object fieldVal = fieldFma.get(methodContext.getEnvMap()); Object toFieldVal = toFieldFma.get(methodContext.getEnvMap()); + Class<?> targetClass = this.targetClass; + if (targetClass == null) { + targetClass = MiniLangUtil.getObjectClassForConversion(fieldVal); + } String format = formatFse.expandString(methodContext.getEnvMap()); - List<Object> errorMessages = FastList.newInstance(); - Boolean resultBool = ObjectType.doRealCompare(fieldVal, toFieldVal, operator, type, format, errorMessages, methodContext.getLocale(), methodContext.getLoader(), true); - if (errorMessages.size() > 0 || resultBool == null) { - for (Object obj : errorMessages) { - simpleMethod.addErrorMessage(methodContext, (String) obj); - } - return false; + try { + return this.compare.doCompare(fieldVal, toFieldVal, targetClass, methodContext.getLocale(), methodContext.getTimeZone(), format); + } catch (Exception e) { + simpleMethod.addErrorMessage(methodContext, e.getMessage()); } - return resultBool.booleanValue(); + return false; } public void prettyPrint(StringBuilder messageBuffer, MethodContext methodContext) { Modified: ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/ifops/IfCompare.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/ifops/IfCompare.java?rev=1338212&r1=1338211&r2=1338212&view=diff ============================================================================== --- ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/ifops/IfCompare.java (original) +++ ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/ifops/IfCompare.java Mon May 14 14:11:33 2012 @@ -25,14 +25,17 @@ import java.util.Map; import javolution.util.FastList; import org.ofbiz.base.util.Debug; +import org.ofbiz.base.util.ObjectType; import org.ofbiz.base.util.UtilXml; 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.ofbiz.minilang.operation.BaseCompare; +import org.ofbiz.minilang.method.conditional.Compare; import org.w3c.dom.Element; /** @@ -42,12 +45,14 @@ public class IfCompare extends MethodOpe public static final String module = IfCompare.class.getName(); + private final Compare compare; protected List<MethodOperation> elseSubOps = null; protected ContextAccessor<Object> fieldAcsr; protected String format; protected ContextAccessor<Map<String, ? extends Object>> mapAcsr; protected String operator; protected List<MethodOperation> subOps; + private final Class<?> targetClass; protected String type; protected String value; @@ -62,7 +67,25 @@ public class IfCompare extends MethodOpe } this.value = element.getAttribute("value"); this.operator = element.getAttribute("operator"); - this.type = MiniLangValidate.checkAttribute(element.getAttribute("type"), "PlainString"); + this.compare = Compare.getInstance(this.operator); + if (this.compare == null) { + MiniLangValidate.handleError("Invalid operator " + this.operator, simpleMethod, element); + } + this.type = element.getAttribute("type"); + Class<?> targetClass = null; + if (!this.type.isEmpty()) { + if ("contains".equals(this.operator)) { + MiniLangValidate.handleError("Operator \"contains\" does not support type conversions (remove the type attribute).", simpleMethod, element); + targetClass = Object.class; + } else { + try { + targetClass = ObjectType.loadClass(this.type); + } catch (ClassNotFoundException e) { + MiniLangValidate.handleError("Invalid type " + this.type, simpleMethod, element); + } + } + } + this.targetClass = targetClass; this.format = element.getAttribute("format"); this.subOps = Collections.unmodifiableList(SimpleMethod.readOperations(element, simpleMethod)); Element elseElement = UtilXml.firstChildElement(element, "else"); @@ -73,11 +96,10 @@ public class IfCompare extends MethodOpe @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 return true + if (this.compare == null) { + throw new MiniLangRuntimeException("Invalid operator " + this.operator, this); + } String value = methodContext.expandString(this.value); - String operator = methodContext.expandString(this.operator); - String type = methodContext.expandString(this.type); String format = methodContext.expandString(this.format); Object fieldVal = null; if (!mapAcsr.isEmpty()) { @@ -92,29 +114,24 @@ public class IfCompare extends MethodOpe // no map name, try the env fieldVal = fieldAcsr.get(methodContext); } - // always use an empty string by default - if (fieldVal == null) { - fieldVal = ""; - } - List<Object> messages = FastList.newInstance(); - Boolean resultBool = BaseCompare.doRealCompare(fieldVal, value, operator, type, format, messages, null, methodContext.getLoader(), true); - if (messages.size() > 0) { - messages.add(0, "Error with comparison in if-compare between field [" + mapAcsr.toString() + "." + fieldAcsr.toString() + "] with value [" + fieldVal + "] and value [" + value + "] with operator [" + operator + "] and type [" + type + "]: "); + Class<?> targetClass = this.targetClass; + if (targetClass == null) { + targetClass = MiniLangUtil.getObjectClassForConversion(fieldVal); + } + boolean result = false; + try { + result = this.compare.doCompare(fieldVal, value, targetClass, methodContext.getLocale(), methodContext.getTimeZone(), format); + } catch (Exception e) { if (methodContext.getMethodType() == MethodContext.EVENT) { - StringBuilder fullString = new StringBuilder(); - for (Object message : messages) { - fullString.append(message); - } - Debug.logWarning(fullString.toString(), module); - methodContext.putEnv(simpleMethod.getEventErrorMessageName(), fullString.toString()); + methodContext.putEnv(simpleMethod.getEventErrorMessageName(), e.getMessage()); methodContext.putEnv(simpleMethod.getEventResponseCodeName(), simpleMethod.getDefaultErrorCode()); - } else if (methodContext.getMethodType() == MethodContext.SERVICE) { - methodContext.putEnv(simpleMethod.getServiceErrorMessageListName(), messages); + } else { + methodContext.putEnv(simpleMethod.getServiceErrorMessageListName(), e.getMessage()); methodContext.putEnv(simpleMethod.getServiceResponseMessageName(), simpleMethod.getDefaultErrorCode()); } return false; } - if (resultBool != null && resultBool.booleanValue()) { + if (result) { return SimpleMethod.runSubOps(subOps, methodContext); } else { if (elseSubOps != null) { Modified: ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/ifops/IfCompareField.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/ifops/IfCompareField.java?rev=1338212&r1=1338211&r2=1338212&view=diff ============================================================================== --- ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/ifops/IfCompareField.java (original) +++ ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/ifops/IfCompareField.java Mon May 14 14:11:33 2012 @@ -25,14 +25,17 @@ import java.util.Map; import javolution.util.FastList; import org.ofbiz.base.util.Debug; +import org.ofbiz.base.util.ObjectType; import org.ofbiz.base.util.UtilXml; 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.ofbiz.minilang.operation.BaseCompare; +import org.ofbiz.minilang.method.conditional.Compare; import org.w3c.dom.Element; /** @@ -42,6 +45,7 @@ public class IfCompareField extends Meth public static final String module = IfCompareField.class.getName(); + private final Compare compare; protected List<MethodOperation> elseSubOps = null; protected ContextAccessor<Object> fieldAcsr; protected String format; @@ -50,6 +54,7 @@ public class IfCompareField extends Meth protected List<MethodOperation> subOps; protected ContextAccessor<Object> toFieldAcsr; protected ContextAccessor<Map<String, ? extends Object>> toMapAcsr; + private final Class<?> targetClass; protected String type; public IfCompareField(Element element, SimpleMethod simpleMethod) throws MiniLangException { @@ -73,7 +78,20 @@ public class IfCompareField extends Meth // would make it impossible to compare from a map field to an // environment field this.operator = element.getAttribute("operator"); - this.type = MiniLangValidate.checkAttribute(element.getAttribute("type"), "PlainString"); + this.compare = Compare.getInstance(this.operator); + if (this.compare == null) { + MiniLangValidate.handleError("Invalid operator " + this.operator, simpleMethod, element); + } + this.type = element.getAttribute("type"); + Class<?> targetClass = null; + if (!this.type.isEmpty()) { + try { + targetClass = ObjectType.loadClass(this.type); + } catch (ClassNotFoundException e) { + MiniLangValidate.handleError("Invalid type " + this.type, simpleMethod, element); + } + } + this.targetClass = targetClass; this.format = element.getAttribute("format"); this.subOps = Collections.unmodifiableList(SimpleMethod.readOperations(element, simpleMethod)); Element elseElement = UtilXml.firstChildElement(element, "else"); @@ -84,10 +102,11 @@ public class IfCompareField extends Meth @Override public boolean exec(MethodContext methodContext) throws MiniLangException { + if (this.compare == null) { + throw new MiniLangRuntimeException("Invalid operator " + this.operator, this); + } // if conditions fails, always return true; if a sub-op returns false // return false and stop, otherwise return true - String operator = methodContext.expandString(this.operator); - String type = methodContext.expandString(this.type); String format = methodContext.expandString(this.format); Object fieldVal1 = null; Object fieldVal2 = null; @@ -115,26 +134,24 @@ public class IfCompareField extends Meth // no map name, try the env fieldVal2 = toFieldAcsr.get(methodContext); } - List<Object> messages = FastList.newInstance(); - Boolean resultBool = BaseCompare.doRealCompare(fieldVal1, fieldVal2, operator, type, format, messages, null, methodContext.getLoader(), false); - if (messages.size() > 0) { - messages.add(0, "Error with comparison in if-compare-field between fields [" + mapAcsr.toString() + "." + fieldAcsr.toString() + "] with value [" + fieldVal1 + "] and [" + toMapAcsr.toString() + "." + toFieldAcsr.toString() + "] with value [" + fieldVal2 + "] with operator [" + operator - + "] and type [" + type + "]: "); + Class<?> targetClass = this.targetClass; + if (targetClass == null) { + targetClass = MiniLangUtil.getObjectClassForConversion(fieldVal1); + } + boolean result = false; + try { + result = this.compare.doCompare(fieldVal1, fieldVal2, targetClass, methodContext.getLocale(), methodContext.getTimeZone(), format); + } catch (Exception e) { if (methodContext.getMethodType() == MethodContext.EVENT) { - StringBuilder fullString = new StringBuilder(); - for (Object message : messages) { - fullString.append(message); - } - Debug.logWarning(fullString.toString(), module); - methodContext.putEnv(simpleMethod.getEventErrorMessageName(), fullString.toString()); + methodContext.putEnv(simpleMethod.getEventErrorMessageName(), e.getMessage()); methodContext.putEnv(simpleMethod.getEventResponseCodeName(), simpleMethod.getDefaultErrorCode()); - } else if (methodContext.getMethodType() == MethodContext.SERVICE) { - methodContext.putEnv(simpleMethod.getServiceErrorMessageListName(), messages); + } else { + methodContext.putEnv(simpleMethod.getServiceErrorMessageListName(), e.getMessage()); methodContext.putEnv(simpleMethod.getServiceResponseMessageName(), simpleMethod.getDefaultErrorCode()); } return false; } - if (resultBool != null && resultBool.booleanValue()) { + if (result) { return SimpleMethod.runSubOps(subOps, methodContext); } else { if (elseSubOps != null) { Modified: ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/serviceops/FieldToResult.java URL: http://svn.apache.org/viewvc/ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/serviceops/FieldToResult.java?rev=1338212&r1=1338211&r2=1338212&view=diff ============================================================================== --- ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/serviceops/FieldToResult.java (original) +++ ofbiz/trunk/framework/minilang/src/org/ofbiz/minilang/method/serviceops/FieldToResult.java Mon May 14 14:11:33 2012 @@ -58,6 +58,8 @@ public final class FieldToResult extends public boolean exec(MethodContext methodContext) throws MiniLangException { Object fieldVal = this.fieldFma.get(methodContext.getEnvMap()); if (fieldVal != null) { + // FIXME: Needs special handling for nested expressions. + // The result attribute might contain a reference to an environment (not result Map) variable. this.resultFma.put(methodContext.getResults(), fieldVal); } return true; |
| Free forum by Nabble | Edit this page |
