001package org.andromda.utils; 002 003import java.text.MessageFormat; 004import java.util.ArrayList; 005import java.util.Arrays; 006import java.util.List; 007 008import org.apache.commons.lang.StringUtils; 009 010/** 011 * A utility object used by the code generator when it needs to convert an object 012 * from one data type to another. 013 * 014 * @author Joel Kozikowski 015 * @author Bob Fields 016 */ 017public class JavaTypeConverter 018{ 019 private List<String> javaTypeConversionIgnoreList = new ArrayList<String>(); 020 021 /** 022 * Specifies a list of one or more fully qualified java types that should be ignored 023 * whenever a type conversion is done. See Spring namespace property "javaTypeConversionIgnoreList" 024 * @param commaSeparatedIgnoreList comma separated list of types to be ignored 025 */ 026 public void setJavaTypeConversionIgnoreList(String commaSeparatedIgnoreList) 027 { 028 javaTypeConversionIgnoreList = new ArrayList<String>(); 029 if (commaSeparatedIgnoreList != null) 030 { 031 final String[] typeList = commaSeparatedIgnoreList.split("\\s*,\\s*"); 032 javaTypeConversionIgnoreList.addAll(Arrays.asList(typeList)); 033 } 034 } 035 036 private static class ConversionEntry 037 { 038 // - not private to increase performance of 039 // inner class access 040 final String sourceType; 041 final String targetType; 042 final String conversionPattern; 043 044 public ConversionEntry( 045 final String sourceType, 046 final String targetType, 047 final String conversionPattern) 048 { 049 this.sourceType = sourceType; 050 this.targetType = targetType; 051 this.conversionPattern = conversionPattern; 052 } 053 } 054 055 private static ConversionEntry[] conversionTable = 056 { 057 new ConversionEntry("int", "java.lang.Integer", "new java.lang.Integer({0})"), 058 new ConversionEntry("int", "java.lang.String", "java.lang.String.valueOf({0})"), 059 new ConversionEntry("int", "long", "(long){0}"), 060 new ConversionEntry("int", "double", "(double){0}"), 061 new ConversionEntry("int", "float", "(float){0}"), 062 new ConversionEntry("int", "boolean", "({0} != 0)"), 063 new ConversionEntry("java.lang.Integer", "int", "({0} == null ? 0 : {0}.intValue())"), 064 new ConversionEntry("java.lang.Integer", "java.lang.String", "({0} == null ? null : {0}.toString())"), 065 new ConversionEntry("java.lang.String", "int", "({0} == null ? 0 : Integer.valueOf({0}).intValue())"), 066 new ConversionEntry("java.lang.String", "java.lang.Integer", "({0} == null ? null : Integer.valueOf({0}))"), 067 068 new ConversionEntry("long", "java.lang.Long", "new java.lang.Long({0})"), 069 new ConversionEntry("long", "java.lang.String", "java.lang.String.valueOf({0})"), 070 new ConversionEntry("long", "int", "(int){0}"), 071 new ConversionEntry("long", "double", "(double){0}"), 072 new ConversionEntry("long", "float", "(float){0}"), 073 new ConversionEntry("long", "boolean", "({0} != 0)"), 074 new ConversionEntry("java.lang.Long", "long", "({0} == null ? 0 : {0}.longValue())"), 075 new ConversionEntry("java.lang.Long", "java.lang.String", "({0} == null ? null : {0}.toString())"), 076 new ConversionEntry("java.lang.String", "long", "({0} == null ? 0 : Long.valueOf({0}).longValue())"), 077 new ConversionEntry("java.lang.String", "java.lang.Long", "({0} == null ? null : Long.valueOf({0}))"), 078 079 new ConversionEntry("double", "java.lang.Double", "new java.lang.Double({0})"), 080 new ConversionEntry("double", "java.lang.String", "java.lang.String.valueOf({0})"), 081 new ConversionEntry("double", "int", "(int){0}"), 082 new ConversionEntry("double", "long", "(long){0}"), 083 new ConversionEntry("double", "float", "(float){0}"), 084 new ConversionEntry("double", "boolean", "({0} != 0.0)"), 085 new ConversionEntry("java.lang.Double", "double", "({0} == null ? 0.0 : {0}.doubleValue())"), 086 new ConversionEntry("java.lang.Double", "java.lang.String", "({0} == null ? null : {0}.toString())"), 087 new ConversionEntry("java.lang.String", "double", "({0} == null ? 0.0 : Double.valueOf({0}).doubleValue())"), 088 new ConversionEntry("java.lang.String", "java.lang.Double", "({0} == null ? null : Double.valueOf({0}))"), 089 090 new ConversionEntry("float", "java.lang.Float", "new java.lang.Float({0})"), 091 new ConversionEntry("float", "java.lang.String", "java.lang.String.valueOf({0})"), 092 new ConversionEntry("float", "int", "(int){0}"), 093 new ConversionEntry("float", "long", "(long){0}"), 094 new ConversionEntry("float", "double", "(double){0}"), 095 new ConversionEntry("float", "boolean", "({0} != 0.0f)"), 096 new ConversionEntry("java.lang.Float", "float", "({0} == null ? 0.0f : {0}.floatValue())"), 097 new ConversionEntry("java.lang.Float", "java.lang.String", "({0} == null ? null : {0}.toString())"), 098 new ConversionEntry("java.lang.String", "float", "({0} == null ? 0.0f : Float.valueOf({0}).floatValue())"), 099 new ConversionEntry("java.lang.String", "java.lang.Float", "({0} == null ? null : Float.valueOf({0}))"), 100 101 new ConversionEntry("int", "java.math.BigInteger", "java.math.BigInteger.valueOf((long){0})"), 102 new ConversionEntry("java.math.BigInteger", "int", "({0} == null ? 0 : {0}.intValue())"), 103 new ConversionEntry("long", "java.math.BigInteger", "java.math.BigInteger.valueOf({0})"), 104 new ConversionEntry("java.math.BigInteger", "long", "({0} == null ? 0 : {0}.longValue())"), 105 new ConversionEntry("java.math.BigInteger", "float", "({0} == null ? 0.0f : {0}.floatValue())"), 106 new ConversionEntry("float", "java.math.BigInteger", "new java.math.BigDecimal((double){0}).toBigInteger()"), 107 new ConversionEntry("java.math.BigInteger", "double", "({0} == null ? 0.0 : {0}.doubleValue())"), 108 new ConversionEntry("double", "java.math.BigInteger", "new java.math.BigDecimal({0}).toBigInteger()"), 109 new ConversionEntry("java.lang.String", "java.math.BigInteger", "new java.math.BigInteger({0})"), 110 new ConversionEntry("java.math.BigInteger", "java.lang.String", "({0} == null ? null : {0}.toString())"), 111 new ConversionEntry("java.math.BigDecimal", "java.math.BigInteger", "({0} == null ? null : {0}.toBigInteger())"), 112 new ConversionEntry("java.lang.Integer", "java.math.BigInteger", "({0} == null ? null : java.math.BigInteger.valueOf((long){0}.intValue()))"), 113 new ConversionEntry("java.math.BigInteger", "java.lang.Integer", "({0} == null ? null : new java.lang.Integer({0}.intValue()))"), 114 new ConversionEntry("java.lang.Long", "java.math.BigInteger", "({0} == null ? null : java.math.BigInteger.valueOf({0}.longValue()))"), 115 new ConversionEntry("java.math.BigInteger", "java.lang.Long", "({0} == null ? null : new java.lang.Long({0}.longValue()))"), 116 new ConversionEntry("java.lang.Float", "java.math.BigInteger", "({0} == null ? null : new java.math.BigDecimal((double){0}.floatValue()).toBigInteger())"), 117 new ConversionEntry("java.lang.Double", "java.math.BigInteger", "({0} == null ? null : new java.math.BigDecimal({0}.doubleValue()).toBigInteger())"), 118 119 new ConversionEntry("int", "java.math.BigDecimal", "java.math.BigDecimal.valueOf((long){0})"), 120 new ConversionEntry("java.math.BigDecimal", "int", "({0} == null ? 0 : {0}.intValue())"), 121 new ConversionEntry("long", "java.math.BigDecimal", "java.math.BigDecimal.valueOf({0})"), 122 new ConversionEntry("java.math.BigDecimal", "long", "({0} == null ? 0 : {0}.longValue())"), 123 new ConversionEntry("java.math.BigDecimal", "float", "({0} == null ? 0.0f : {0}.floatValue())"), 124 new ConversionEntry("float", "java.math.BigDecimal", "new java.math.BigDecimal((double){0})"), 125 new ConversionEntry("java.math.BigDecimal", "double", "({0} == null ? 0.0 : {0}.doubleValue())"), 126 new ConversionEntry("double", "java.math.BigDecimal", "new java.math.BigDecimal({0})"), 127 new ConversionEntry("java.lang.String", "java.math.BigDecimal", "new java.math.BigDecimal({0})"), 128 new ConversionEntry("java.math.BigDecimal", "java.lang.String", "({0} == null ? null : {0}.toString())"), 129 new ConversionEntry("java.math.BigInteger", "java.math.BigDecimal", "new java.math.BigDecimal({0})"), 130 new ConversionEntry("java.lang.Integer", "java.math.BigDecimal", "({0} == null ? null : java.math.BigDecimal.valueOf((long){0}.intValue()))"), 131 new ConversionEntry("java.math.BigDecimal", "java.lang.Integer", "({0} == null ? null : new java.lang.Integer({0}.intValue()))"), 132 new ConversionEntry("java.lang.Long", "java.math.BigDecimal", "({0} == null ? null : java.math.BigDecimal.valueOf({0}.longValue()))"), 133 new ConversionEntry("java.math.BigDecimal", "java.lang.Long", "({0} == null ? null : new java.lang.Long({0}.longValue()))"), 134 new ConversionEntry("java.lang.Float", "java.math.BigDecimal", "({0} == null ? null : new java.math.BigDecimal((double){0}.floatValue()))"), 135 new ConversionEntry("java.lang.Double", "java.math.BigDecimal", "({0} == null ? null : new java.math.BigDecimal({0}.doubleValue()))"), 136 137 new ConversionEntry("boolean", "java.lang.Boolean", "new java.lang.Boolean({0})"), 138 new ConversionEntry("boolean", "java.lang.String", "java.lang.String.valueOf({0})"), 139 new ConversionEntry("boolean", "int", "({0} ? 1 : 0)"), 140 new ConversionEntry("boolean", "long", "({0} ? 1 : 0)"), 141 new ConversionEntry("boolean", "double", "({0} ? 1.0 : 0.0)"), 142 new ConversionEntry("boolean", "float", "({0} ? 1.0f : 0.0f)"), 143 new ConversionEntry("java.lang.Boolean", "boolean", "({0} == null ? false : {0}.booleanValue())"), 144 new ConversionEntry("java.lang.Boolean", "java.lang.String", "({0} == null ? null : {0}.toString())"), 145 new ConversionEntry("java.lang.String", "boolean", "({0} == null ? false : Boolean.valueOf({0}).booleanValue())"), 146 new ConversionEntry("java.lang.String", "java.lang.Boolean", "({0} == null ? null : Boolean.valueOf({0}))"), 147 148 new ConversionEntry("string", "java.lang.String", "{0}"), 149 new ConversionEntry("java.lang.String", "string", "{0}"), 150 151 new ConversionEntry("java.util.Date", "java.lang.String", 152 "({0} == null ? null : new java.text.SimpleDateFormat(\"yyyy-MM-dd HH:mm:ssZ\").format({0}))"), 153 new ConversionEntry("java.sql.Timestamp", "java.lang.String", 154 "({0} == null ? null : new java.text.SimpleDateFormat(\"yyyy-MM-dd HH:mm:ssZ\").format({0}))"), 155 new ConversionEntry("java.sql.Time", "java.lang.String", 156 "({0} == null ? null : new java.text.SimpleDateFormat(\"HH:mm:ssZ\").format({0}))"), 157 new ConversionEntry("java.sql.Date", "java.lang.String", 158 "({0} == null ? null : new java.text.SimpleDateFormat(\"yyyy-MM-dd\").format({0}))"), 159 new ConversionEntry("java.lang.String", "java.util.Date", 160 "({0} == null ? null : new java.text.SimpleDateFormat(\"yyyy-MM-dd HH:mm:ssZ\").parse({0}))"), 161 new ConversionEntry("java.lang.String", "java.sql.Timestamp", 162 "({0} == null ? null : new java.sql.Timestamp(new java.text.SimpleDateFormat(\"yyyy-MM-dd HH:mm:ssZ\").parse({0}).getTime()))"), 163 new ConversionEntry("java.lang.String", "java.sql.Time", 164 "({0} == null ? null : new java.sql.Time(new java.text.SimpleDateFormat(\"HH:mm:ssZ\").parse({0}).getTime()))"), 165 new ConversionEntry("java.lang.String", "java.sql.Date", 166 "({0} == null ? null : new java.sql.Date(new java.text.SimpleDateFormat(\"yyyy-MM-dd\").parse({0}).getTime()))"), 167 new ConversionEntry("java.sql.Timestamp", "java.util.Date", "{0}"), 168 new ConversionEntry("java.sql.Timestamp", "java.sql.Time", "({0} == null ? null : new java.sql.Time({0}.getTime()))"), 169 new ConversionEntry("java.sql.Timestamp", "java.sql.Date", "({0} == null ? null : new java.sql.Date({0}.getTime()))"), 170 new ConversionEntry("java.sql.Time", "java.util.Date", "{0}"), 171 new ConversionEntry("java.sql.Time", "java.sql.Timestamp", "({0} == null ? null : new java.sql.Timestamp({0}.getTime()))"), 172 new ConversionEntry("java.sql.Date", "java.util.Date", "{0}"), 173 new ConversionEntry("java.sql.Date", "java.sql.Timestamp", "({0} == null ? null : new java.sql.Timestamp({0}.getTime()))"), 174 new ConversionEntry("java.util.Date", "java.sql.Timestamp", "({0} == null ? null : new java.sql.Timestamp({0}.getTime()))"), 175 new ConversionEntry("java.util.Date", "java.sql.Time", "({0} == null ? null : new java.sql.Time({0}.getTime()))"), 176 new ConversionEntry("java.util.Date", "java.sql.Date", "({0} == null ? null : new java.sql.Date({0}.getTime()))"), 177 new ConversionEntry("java.util.Date", "long", "({0} == null ? 0 : {0}.getTime())"), 178 new ConversionEntry("java.sql.Timestamp", "long", "({0} == null ? 0 : {0}.getTime())"), 179 new ConversionEntry("java.sql.Time", "long", "({0} == null ? 0 : {0}.getTime())"), 180 new ConversionEntry("java.sql.Date", "long", "({0} == null ? 0 : {0}.getTime())"), 181 new ConversionEntry("long", "java.sql.Date", "new java.sql.Date({0})"), 182 new ConversionEntry("long", "java.sql.Time", "new java.sql.Time({0})"), 183 new ConversionEntry("long", "java.sql.Timestamp", "new java.sql.Timestamp({0})"), 184 new ConversionEntry("long", "java.util.Date", "new java.util.Date({0})"), 185 186 new ConversionEntry("java.lang.Character", "java.lang.String", "({0} == null ? null : {0}.toString())"), 187 new ConversionEntry("java.lang.String", "java.lang.Character", "({0} == null || {0}.length() == 0 ? null : java.lang.Character.valueOf({0}.charAt(0)))"), 188 189 new ConversionEntry("java.lang.Object", "java.lang.String", "{0} == null ? null : {0}.toString()"), 190 new ConversionEntry("java.lang.Object", "java.lang.Integer", "{0} == null ? null : {0}.toString()"), 191 new ConversionEntry("java.lang.Object", "java.lang.Long", "{0} == null ? null : {0}.toString()"), 192 new ConversionEntry("java.lang.Object", "java.lang.Float", "{0} == null ? null : {0}.toString()"), 193 new ConversionEntry("java.lang.Object", "java.lang.Double", "{0} == null ? null : {0}.toString()"), 194 new ConversionEntry("java.lang.Object", "java.lang.Character", "({0} == null || {0}.toString().length() == 0 ? null : java.lang.Character.valueOf({0}.toString().charAr(0)))"), 195 new ConversionEntry("java.lang.String", "java.lang.Object", "{0}"), 196 new ConversionEntry("java.lang.Integer", "java.lang.Object", "{0}"), 197 new ConversionEntry("java.lang.Long", "java.lang.Object", "{0}"), 198 new ConversionEntry("java.lang.Float", "java.lang.Object", "{0}"), 199 new ConversionEntry("java.lang.Double", "java.lang.Object", "{0}"), 200 new ConversionEntry("java.lang.Character", "java.lang.Object", "{0}"), 201 new ConversionEntry("java.lang.Character", "char", "({0} == null ? 0 : {0}.charValue())"), 202 new ConversionEntry("char", "java.lang.Character", "java.lang.Character.valueOf({0})"), 203 }; 204 205 /** 206 * Attempts to code a type conversion from the specified source value to the target 207 * type that can be used on the right hand side of an assignment. If such a conversion 208 * exists, the Java code fragment to do that will be returned. If no such conversion exists, 209 * null is returned. 210 * @param sourceType The fully qualified data type of the source value 211 * @param sourceValue The actual source value (usually a variable name) 212 * @param targetType The fully qualified data type of the target value 213 * @return The converted value, or null if no conversion can be done. 214 */ 215 public String typeConvert( 216 final String sourceType, 217 final String sourceValue, 218 final String targetType) 219 { 220 String convertedValue; 221 222 if (StringUtils.isBlank(sourceType) || StringUtils.isBlank(targetType) || 223 javaTypeConversionIgnoreList.contains(sourceType) || javaTypeConversionIgnoreList.contains(targetType)) 224 { 225 convertedValue = null; 226 } 227 else if (sourceType.equals(targetType)) 228 { 229 convertedValue = sourceValue; 230 } 231 else 232 { 233 convertedValue = null; 234 235 for (int i = 0; i < conversionTable.length && convertedValue == null; i++) 236 { 237 if (conversionTable[i].sourceType.equals(sourceType) && 238 conversionTable[i].targetType.equals(targetType)) 239 { 240 convertedValue = 241 MessageFormat.format( 242 conversionTable[i].conversionPattern, 243 sourceValue); 244 } // if 245 } // for 246 247 if (convertedValue == null && sourceType.startsWith("java.lang.") && !sourceType.endsWith("[]")) 248 { 249 // If source is a primitive wrapper, try to convert 250 // to the base primitive first... 251 String primitiveSource = sourceType.substring(10).toLowerCase(); 252 if ("integer".equals(primitiveSource)) 253 { 254 primitiveSource = "int"; 255 } 256 else if ("character".equals(primitiveSource)) { 257 primitiveSource = "char"; 258 } 259 260 String interimValue = typeConvert( 261 sourceType, 262 sourceValue, 263 primitiveSource); 264 265 if (interimValue != null) 266 { 267 convertedValue = typeConvert( 268 primitiveSource, 269 interimValue, 270 targetType); 271 } 272 } 273 274 if (convertedValue == null && targetType.startsWith("java.lang.") && !targetType.endsWith("[]")) 275 { 276 // One last try - if target is a primitive wrapper, try to convert 277 // to the base primitive first... 278 String primitiveTarget = targetType.substring(10).toLowerCase(); 279 if ("integer".equals(primitiveTarget)) 280 { 281 primitiveTarget = "int"; 282 } 283 else if ("character".equals(primitiveTarget)) 284 { 285 primitiveTarget = "char"; 286 } 287 288 String interimValue = typeConvert( 289 sourceType, 290 sourceValue, 291 primitiveTarget); 292 if (interimValue != null) 293 { 294 convertedValue = typeConvert( 295 primitiveTarget, 296 interimValue, 297 targetType); 298 } 299 } 300 } 301 302 return convertedValue; 303 } 304 305 private static final List<String> javaLangList = new ArrayList<String>(); 306 /** 307 * Creates a java.lang. fully qualified name from the given <code>name</code>, 308 * inserting 'java.lang.' in front if needed. Many EJB3 and Hibernate configuration files 309 * require java.lang. in the type name, where Java code does not (gives compiler warning). 310 * This allows UML Primitive types to be modeled and mapped without java.lang. implementation. 311 * 312 * @param name the name of the model element. 313 * @return the java.lang. fully qualified name, if needed. 314 */ 315 public static String getJavaLangTypeName(String name) 316 { 317 if (StringUtils.isBlank(name)) 318 { 319 return name; 320 } 321 synchronized (javaLangList) 322 { 323 if (javaLangList.isEmpty()) 324 { 325 javaLangList.add("String"); 326 javaLangList.add("Boolean"); 327 javaLangList.add("Integer"); 328 javaLangList.add("Long"); 329 javaLangList.add("Double"); 330 javaLangList.add("Object"); 331 javaLangList.add("Short"); 332 javaLangList.add("Character"); 333 javaLangList.add("Byte"); 334 javaLangList.add("Float"); 335 javaLangList.add("Number"); 336 javaLangList.add("Math"); 337 javaLangList.add("Class"); 338 javaLangList.add("Exception"); 339 javaLangList.add("Enum"); 340 } 341 } 342 // If type has no package and is not the same as lowercase (i.e. primitive type)... 343 if (!(name.indexOf('.')>-1) && !(name.equals(name.toLowerCase()))) 344 { 345 if (javaLangList.contains(name) 346 || (name.endsWith("[]") && javaLangList.contains(name.substring(0, name.length()-2)))) 347 { 348 name = "java.lang." + name; 349 } 350 } 351 return name; 352 } 353}