/** * Implements the CFML Function numberformat */ package railo.runtime.functions.displayFormatting; import java.util.Locale; import railo.runtime.PageContext; import railo.runtime.exp.ExpressionException; import railo.runtime.exp.FunctionException; import railo.runtime.exp.PageException; import railo.runtime.ext.function.Function; import railo.runtime.op.Caster; import railo.runtime.op.Decision; import railo.runtime.util.InvalidMaskException; /** * Formats a Number by given pattern */ public final class NumberFormat implements Function { /** * @param pc * @param object * @return formated number * @throws ExpressionException */ public static String call(PageContext pc, Object object) throws PageException { return new railo.runtime.util.NumberFormat().format(Locale.US,toNumber(pc,object)); } /** * @param pc * @param object * @param mask * @return formated number * @throws ExpressionException */ public static String call(PageContext pc , Object object, String mask) throws PageException { if(mask==null) return call(pc, object); if(mask.equalsIgnoreCase("roman")) { return intToRoman(pc,(int)toNumber(pc,object)); } else if(mask.equalsIgnoreCase("hex")) { return Integer.toHexString((int)toNumber(pc,object)); } else if(mask.equalsIgnoreCase(",")) { return call(pc, object); } try { return new railo.runtime.util.NumberFormat().format(Locale.US,toNumber(pc,object),mask); } catch (InvalidMaskException e) { throw new FunctionException(pc,"numberFormat",2,"mask",e.getMessage()); } } public static double toNumber(PageContext pc, Object object) throws PageException { double d=Caster.toDoubleValue(object,Double.NaN); if(Decision.isValid(d)) return d; String str=Caster.toString(object); if(str.length()==0) return 0; throw new FunctionException(pc,"numberFormat",1,"number","can't cast value ["+str+"] to a number"); } private static String intToRoman(PageContext pc, int value) throws FunctionException { if(value == 0) throw new FunctionException(pc,"numberFormat",1,"number","a roman value can't be 0"); if(value < 0) throw new FunctionException(pc,"numberFormat",1,"number","a roman value can't be less than 0"); if(value > 3999) throw new FunctionException(pc,"numberFormat",1,"number","a roman value can't be greater than 3999"); StringBuffer roman = new StringBuffer(); while (value / 1000 >= 1) { roman.append('M'); value = value - 1000; } if (value / 900 >= 1) { roman.append("CM"); value = value - 900; } if (value / 500 >= 1) { roman.append("D"); value = value - 500; } if (value / 400 >= 1) { roman.append("CD"); value = value - 400; } while (value / 100 >= 1) { roman.append("C"); value = value - 100; } if (value / 90 >= 1) { roman.append("XC"); value = value - 90; } if (value / 50 >= 1) { roman.append("L"); value = value - 50; } if (value / 40 >= 1) { roman.append("XL"); value = value - 40; } while (value / 10 >= 1) { roman.append("X"); value = value - 10; } if (value / 9 >= 1) { roman.append("IX"); value = value - 9; } if (value / 5 >= 1) { roman.append("V"); value = value - 5; } if (value / 4 >= 1) { roman.append("IV"); value = value - 4; } while (value >= 1) { roman.append("I"); value = value - 1; } return roman.toString(); } }