001 /** 002 * Implements the CFML Function numberformat 003 */ 004 package railo.runtime.functions.displayFormatting; 005 006 import java.util.Locale; 007 008 import railo.runtime.PageContext; 009 import railo.runtime.exp.ExpressionException; 010 import railo.runtime.exp.FunctionException; 011 import railo.runtime.exp.PageException; 012 import railo.runtime.ext.function.Function; 013 import railo.runtime.op.Caster; 014 import railo.runtime.op.Decision; 015 import railo.runtime.util.InvalidMaskException; 016 017 /** 018 * Formats a Number by given pattern 019 */ 020 public final class NumberFormat implements Function { 021 022 /** 023 * @param pc 024 * @param object 025 * @return formated number 026 * @throws ExpressionException 027 */ 028 public static String call(PageContext pc, Object object) throws PageException { 029 return new railo.runtime.util.NumberFormat().format(Locale.US,toNumber(pc,object)); 030 } 031 032 /** 033 * @param pc 034 * @param object 035 * @param mask 036 * @return formated number 037 * @throws ExpressionException 038 */ 039 public static String call(PageContext pc , Object object, String mask) throws PageException { 040 if(mask==null) return call(pc, object); 041 if(mask.equalsIgnoreCase("roman")) { 042 return intToRoman(pc,(int)toNumber(pc,object)); 043 } 044 else if(mask.equalsIgnoreCase("hex")) { 045 return Integer.toHexString((int)toNumber(pc,object)); 046 } 047 else if(mask.equalsIgnoreCase(",")) { 048 return call(pc, object); 049 } 050 051 try { 052 return new railo.runtime.util.NumberFormat().format(Locale.US,toNumber(pc,object),mask); 053 } 054 catch (InvalidMaskException e) { 055 throw new FunctionException(pc,"numberFormat",2,"mask",e.getMessage()); 056 } 057 } 058 059 public static double toNumber(PageContext pc, Object object) throws PageException { 060 double d=Caster.toDoubleValue(object,Double.NaN); 061 if(Decision.isValid(d)) return d; 062 063 String str=Caster.toString(object); 064 if(str.length()==0) return 0; 065 throw new FunctionException(pc,"numberFormat",1,"number","can't cast value ["+str+"] to a number"); 066 } 067 068 069 private static String intToRoman(PageContext pc, int value) throws FunctionException { 070 if(value == 0) 071 throw new FunctionException(pc,"numberFormat",1,"number","a roman value can't be 0"); 072 if(value < 0) 073 throw new FunctionException(pc,"numberFormat",1,"number","a roman value can't be less than 0"); 074 if(value > 3999) 075 throw new FunctionException(pc,"numberFormat",1,"number","a roman value can't be greater than 3999"); 076 077 StringBuffer roman = new StringBuffer(); 078 079 080 081 while (value / 1000 >= 1) { 082 roman.append('M'); 083 value = value - 1000; 084 } 085 if (value / 900 >= 1) { 086 roman.append("CM"); 087 value = value - 900; 088 } 089 if (value / 500 >= 1) { 090 roman.append("D"); 091 value = value - 500; 092 } 093 if (value / 400 >= 1) { 094 roman.append("CD"); 095 value = value - 400; 096 } 097 while (value / 100 >= 1) { 098 roman.append("C"); 099 value = value - 100; 100 } 101 if (value / 90 >= 1) { 102 roman.append("XC"); 103 value = value - 90; 104 } 105 if (value / 50 >= 1) { 106 roman.append("L"); 107 value = value - 50; 108 } 109 if (value / 40 >= 1) { 110 roman.append("XL"); 111 value = value - 40; 112 } 113 while (value / 10 >= 1) { 114 roman.append("X"); 115 value = value - 10; 116 } 117 if (value / 9 >= 1) { 118 roman.append("IX"); 119 value = value - 9; 120 } 121 if (value / 5 >= 1) { 122 roman.append("V"); 123 value = value - 5; 124 } 125 if (value / 4 >= 1) { 126 roman.append("IV"); 127 value = value - 4; 128 } 129 while (value >= 1) { 130 roman.append("I"); 131 value = value - 1; 132 } 133 return roman.toString(); 134 } 135 136 }