Author: bpoussin Date: 2014-08-01 11:50:53 +0200 (Fri, 01 Aug 2014) New Revision: 1589 Url: http://forge.nuiton.org/projects/wikitty/repository/revisions/1589 Log: add expression support when convert string to number (ex: 2+2*2=6) Modified: trunk/pom.xml trunk/wikitty-api/pom.xml trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyUtil.java Modified: trunk/pom.xml =================================================================== --- trunk/pom.xml 2014-07-30 16:25:48 UTC (rev 1588) +++ trunk/pom.xml 2014-08-01 09:50:53 UTC (rev 1589) @@ -263,6 +263,13 @@ <version>2.3.8</version> </dependency> + <!-- pour l'evaluation d'expression mathematique, lors de la conversion d'une chaine en nombre --> + <dependency> + <groupId>net.objecthunter</groupId> + <artifactId>exp4j</artifactId> + <version>0.4.0.ALPHA-3</version> + </dependency> + <!-- html form fileupload used in wikitty-publication --> <dependency> <groupId>commons-fileupload</groupId> Modified: trunk/wikitty-api/pom.xml =================================================================== --- trunk/wikitty-api/pom.xml 2014-07-30 16:25:48 UTC (rev 1588) +++ trunk/wikitty-api/pom.xml 2014-08-01 09:50:53 UTC (rev 1589) @@ -150,6 +150,12 @@ <artifactId>smackx</artifactId> </dependency> + <!-- pour l'evaluation d'expression mathematique, lors de la conversion d'une chaine en nombre --> + <dependency> + <groupId>net.objecthunter</groupId> + <artifactId>exp4j</artifactId> + </dependency> + <!-- TEST --> <dependency> <groupId>junit</groupId> Modified: trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyUtil.java =================================================================== --- trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyUtil.java 2014-07-30 16:25:48 UTC (rev 1588) +++ trunk/wikitty-api/src/main/java/org/nuiton/wikitty/WikittyUtil.java 2014-08-01 09:50:53 UTC (rev 1589) @@ -28,20 +28,9 @@ import java.beans.PropertyDescriptor; import java.io.File; import java.io.IOException; +import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; - -import org.apache.commons.io.FileUtils; -import org.apache.commons.lang3.StringUtils; -import org.nuiton.wikitty.entities.BusinessEntity; -import org.nuiton.wikitty.entities.WikittyExtension; -import org.nuiton.wikitty.entities.Wikitty; -import org.nuiton.wikitty.entities.WikittyField; -import org.nuiton.wikitty.entities.WikittyImpl; -import org.nuiton.wikitty.entities.FieldType; -import org.nuiton.wikitty.entities.BusinessEntityImpl; -import org.nuiton.wikitty.services.WikittyServiceEnhanced; -import java.lang.reflect.Constructor; import java.math.BigDecimal; import java.math.BigInteger; import java.net.Inet4Address; @@ -50,7 +39,6 @@ import java.net.NetworkInterface; import java.security.Key; import java.text.DecimalFormat; -import java.text.NumberFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; @@ -60,7 +48,6 @@ import java.util.Collections; import java.util.Date; import java.util.Enumeration; -import java.util.Formatter; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedHashSet; @@ -70,27 +57,35 @@ import java.util.Set; import java.util.TimeZone; import java.util.UUID; -import java.util.logging.Level; -import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import javax.crypto.Cipher; import javax.crypto.spec.SecretKeySpec; import net.iharder.Base64; +import net.objecthunter.exp4j.ExpressionBuilder; import org.apache.commons.beanutils.BeanUtilsBean; import org.apache.commons.beanutils.converters.DateTimeConverter; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringEscapeUtils; - +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateUtils; import org.apache.commons.lang3.time.FastDateFormat; -import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.nuiton.util.DateUtil; +import org.nuiton.wikitty.entities.BusinessEntity; +import org.nuiton.wikitty.entities.BusinessEntityImpl; +import org.nuiton.wikitty.entities.FieldType; +import org.nuiton.wikitty.entities.Wikitty; +import org.nuiton.wikitty.entities.WikittyExtension; +import org.nuiton.wikitty.entities.WikittyField; +import org.nuiton.wikitty.entities.WikittyImpl; import org.nuiton.wikitty.entities.WikittyTypes; import org.nuiton.wikitty.generator.WikittyTransformerUtil; +import org.nuiton.wikitty.services.WikittyServiceEnhanced; /** * Util static method for wikitty. @@ -565,6 +560,9 @@ /** * Get value as BigDecimal. * + * If value is String, mathematical evaluation is done. + * ex: 2+2*2 create BigDecimal(6) as result + * * @param value null and empty string are casted to '0' value. * @throws WikittyException on NumberFormatException or if value object can't be casted to number. * @@ -577,38 +575,47 @@ } else if (value instanceof BigDecimal) { result = (BigDecimal) value; } else { - String s = value.toString(); - // suppression de tous les blancs pour un parsing plus sur - s = StringUtils.deleteWhitespace(s); - s = StringUtils.remove(s, nbsp); + String all = value.toString(); try { - // on commence par essayer par la methode la plus simple - result = new BigDecimal(s); - } catch (NumberFormatException eee) { - // on essaie avec un parse, en dernier ressort - // si jamais le nombre etait localise (ex: 99,987.76) + double d = new ExpressionBuilder(all).build().evaluate(); + result = new BigDecimal(d); + } catch (Exception eee) { + String s = all; + // suppression de tous les blancs pour un parsing plus sur + s = StringUtils.deleteWhitespace(s); + s = StringUtils.remove(s, nbsp); try { - DecimalFormat parser = new DecimalFormat(); - // on veut des BigDecimal en resultat et pas un Double - parser.setParseBigDecimal(true); + // on commence par essayer par la methode la plus simple + result = new BigDecimal(s); + } catch (NumberFormatException yyy) { + // on essaie avec un parse, en dernier ressort + // si jamais le nombre etait localise (ex: 99,987.76) + try { + DecimalFormat parser = new DecimalFormat(); + // on veut des BigDecimal en resultat et pas un Double + parser.setParseBigDecimal(true); - Number n = parser.parse(s); - // meme si on demande au parser un BigDecimal, il retourne - // certaine fois un Double (NaN, Infinit, ...). - // mais dans ce cas la, ca revient a une erreur de parsing - // qui explosera avec le cast - result = (BigDecimal)n; - } catch (Exception zzz) { - // on fait suivre eee et non pas zzz car l'erreur initial - // est bien eee, zzz est juste le fallback, et certain fois - // on aurait un ClassCastException qui n'a rien a voir, - // mais on log tout de meme zzz - log.debug(String.format( - "Can't convert value '%s(%s)' to numeric, this exception is not throw but just logged", - value, getClass(value)), zzz); - throw new WikittyException( - String.format("Can't convert value '%s(%s)' to numeric", - value, getClass(value)), eee); + Number n = parser.parse(s); + // meme si on demande au parser un BigDecimal, il retourne + // certaine fois un Double (NaN, Infinit, ...). + // mais dans ce cas la, ca revient a une erreur de parsing + // qui explosera avec le cast + result = (BigDecimal)n; + } catch (Exception zzz) { + // on fait suivre eee et non pas yyy ou zzz car l'erreur initial + // est bien eee, yyy et zzz sont juste le fallback, et certain fois + // on aurait un ClassCastException qui n'a rien a voir, + // mais on log tout de meme zzz + log.debug(String.format( + "Try one, can't convert value '%s(%s)' to numeric, this exception is not throw but just logged", + value, getClass(value)), yyy); + log.debug(String.format( + "Try two, can't convert value '%s(%s)' to numeric, this exception is not throw but just logged", + value, getClass(value)), zzz); + throw new WikittyException( + String.format("Can't convert value '%s(%s)' to numeric", + value, getClass(value)), eee); + } } } }