1 24 25 package com.mckoi.database; 26 27 import com.mckoi.database.global.StringObject; 28 import com.mckoi.database.global.ByteLongObject; 29 import com.mckoi.database.global.ObjectTranslator; 30 import com.mckoi.database.global.SQLTypes; 31 import com.mckoi.util.BigNumber; 32 33 import java.lang.reflect.Constructor ; 34 35 40 41 public class Caster { 42 43 44 public final static int PRIMITIVE_COST = 100; 45 46 47 public final static int OBJECT_COST = 200; 48 49 50 private final static BigNumber maxBigNumByte = 51 BigNumber.fromInt(Byte.MAX_VALUE); 52 53 54 private final static BigNumber minBigNumByte = 55 BigNumber.fromInt(Byte.MIN_VALUE); 56 57 58 private final static BigNumber maxBigNumShort = 59 BigNumber.fromInt(Short.MAX_VALUE); 60 61 62 private final static BigNumber minBigNumShort = 63 BigNumber.fromInt(Short.MIN_VALUE); 64 65 66 private final static BigNumber maxBigNumInt = 67 BigNumber.fromInt(Integer.MAX_VALUE); 68 69 70 private final static BigNumber minBigNumInt = 71 BigNumber.fromInt(Integer.MIN_VALUE); 72 73 74 private final static BigNumber maxBigNumLong = 75 BigNumber.fromLong(Long.MAX_VALUE); 76 77 78 private final static BigNumber minBigNumLong = 79 BigNumber.fromLong(Long.MIN_VALUE); 80 81 82 private final static BigNumber maxBigNumFloat = 83 BigNumber.fromDouble(Float.MAX_VALUE); 84 85 86 private static BigNumber minBigNumFloat = 87 BigNumber.fromDouble(Float.MIN_VALUE); 88 89 90 private static BigNumber maxBigNumDouble = 91 BigNumber.fromDouble(Double.MAX_VALUE); 92 93 101 public static void deserializeJavaObjects(TObject[] args) { 102 for (int i = 0; i < args.length; i++) { 103 int sqlType = args[i].getTType().getSQLType(); 104 if (sqlType != SQLTypes.JAVA_OBJECT) { 105 continue; } 107 Object argVal = args[i].getObject(); 108 if (!(argVal instanceof ByteLongObject)) { 109 continue; } 111 Object javaObj = ObjectTranslator.deserialize((ByteLongObject)argVal); 112 args[i] = new TObject(args[i].getTType(), javaObj); 113 } 114 } 115 116 126 public static Constructor findBestConstructor( 127 Constructor [] constructs, TObject[] args) { 128 int bestCost = 0; Constructor bestConstructor = null; 130 int[] argSqlTypes = getSqlTypes(args); 131 for (int i = 0; i < constructs.length; ++i) { 132 Class [] targets = constructs[i].getParameterTypes(); 133 int cost = getCastingCost(args, argSqlTypes, targets); 134 if (cost < 0) { 135 continue; } 137 if (bestConstructor == null || cost < bestCost) { 138 bestCost = cost; bestConstructor = constructs[i]; 140 } 141 } 142 return bestConstructor; } 144 145 151 public static int[] getSqlTypes(TObject[] args) { 152 int[] sqlTypes = new int[args.length]; 153 for (int i = 0; i < args.length; i++) { 154 sqlTypes[i] = getSqlType(args[i]); 155 } 156 return sqlTypes; 157 } 158 159 167 public static int getSqlType(TObject arg) { 168 int sqlType = arg.getTType().getSQLType(); 169 Object argVal = arg.getObject(); 170 if (!(argVal instanceof BigNumber)) { 171 return sqlType; } 173 BigNumber b = (BigNumber)argVal; 174 BigNumber bAbs; 175 switch (sqlType) { 176 case SQLTypes.NUMERIC: 177 case SQLTypes.DECIMAL: 178 if (b.canBeRepresentedAsInt()) { 181 sqlType = SQLTypes.INTEGER; 182 } 183 else if (b.canBeRepresentedAsLong()) { 184 sqlType = SQLTypes.BIGINT; 185 } 186 else { 187 bAbs = b.abs(); 188 if (b.getScale() == 0) { 189 if (bAbs.compareTo(maxBigNumInt) <= 0) { 190 sqlType = SQLTypes.INTEGER; 191 } 192 else if (bAbs.compareTo(maxBigNumLong) <= 0) { 193 sqlType = SQLTypes.BIGINT; 194 } 195 } 196 else if (bAbs.compareTo(maxBigNumDouble) <= 0) { 197 sqlType = SQLTypes.DOUBLE; 198 } 199 } 200 break; 203 case SQLTypes.BIT: 204 if (b.canBeRepresentedAsInt()) { 205 int n = b.intValue(); 206 if (n == 0 || n == 1) { 207 return sqlType; } 209 } 210 sqlType = SQLTypes.TINYINT; 212 case SQLTypes.TINYINT: 214 if (b.compareTo(maxBigNumByte) <= 0 && 215 b.compareTo(minBigNumByte) >=0 ) { 216 return sqlType; } 218 sqlType = SQLTypes.SMALLINT; 220 case SQLTypes.SMALLINT: 222 if (b.compareTo(maxBigNumShort) <= 0 && 223 b.compareTo(minBigNumShort) >= 0) { 224 return sqlType; } 226 sqlType = SQLTypes.INTEGER; 228 case SQLTypes.INTEGER: 230 if (b.compareTo(maxBigNumInt) <= 0 && 231 b.compareTo(minBigNumInt) >= 0) { 232 return sqlType; } 234 sqlType = SQLTypes.BIGINT; 236 break; 238 case SQLTypes.REAL: 239 bAbs = b.abs(); 240 if (bAbs.compareTo(maxBigNumFloat) <= 0 && 241 (bAbs.compareTo(minBigNumFloat) >= 0 || 242 b.doubleValue() == 0.0)) { 243 return sqlType; } 245 sqlType = SQLTypes.DOUBLE; 247 break; 248 default: 249 break; 250 } 251 return sqlType; 252 } 253 254 262 public static String getArgTypesString(TObject[] args) { 263 StringBuffer sb = new StringBuffer (); 264 for (int n = 0; n < args.length; n++) { 265 if (n > 0) { 266 sb.append(","); 267 } 268 if (args[n] == null) { 269 sb.append("null"); 270 } 271 else { 272 int sqlType = getSqlType(args[n]); 273 String typeName; 274 if (sqlType == SQLTypes.JAVA_OBJECT) { 275 Object argObj = args[n].getObject(); 276 if (argObj == null) { 277 typeName = "null"; 278 } 279 else { 280 typeName = argObj.getClass().getName(); 281 } 282 } 283 else { 284 typeName = DataTableColumnDef.sqlTypeToString(sqlType); 285 } 286 sb.append(typeName); 287 } 288 } 289 return sb.toString(); 290 } 291 292 302 static int getCastingCost(TObject[] args, int[] argSqlTypes, 303 Class [] targets) { 304 if (targets.length != argSqlTypes.length) { 305 return -1; } 307 308 int totalCost = 0; 310 for (int n = 0; n < argSqlTypes.length; ++n) { 311 int argCost = getCastingCost(args[n], argSqlTypes[n], targets[n]); 312 if (argCost < 0) { 313 return -1; } 315 int positionalCost = argCost * n / 10000; 316 totalCost += argCost + positionalCost; 322 } 323 return totalCost; 324 } 325 326 private static String [] bitPrims = { "boolean" }; 328 private static Class [] bitClasses = { Boolean .class }; 329 330 private static String [] tinyPrims = { "byte", "short", "int", "long" }; 331 private static Class [] tinyClasses = { Byte .class, Short .class, 332 Integer .class, Long .class, Number .class }; 333 334 private static String [] smallPrims = { "short", "int", "long" }; 335 private static Class [] smallClasses = { Short .class, Integer .class, 336 Long .class, Number .class }; 337 338 private static String [] intPrims = { "int", "long" }; 339 private static Class [] intClasses = { Integer .class, Long .class, 340 Number .class }; 341 342 private static String [] bigPrims = { "long" }; 343 private static Class [] bigClasses = { Long .class, Number .class }; 344 345 private static String [] floatPrims = { "float", "double" }; 346 private static Class [] floatClasses = { Float .class, Double .class, 347 Number .class }; 348 349 private static String [] doublePrims = { "double" }; 350 private static Class [] doubleClasses = { Double .class, Number .class }; 351 352 private static String [] stringPrims = { }; 353 private static Class [] stringClasses = { String .class }; 354 355 private static String [] datePrims = { }; 356 private static Class [] dateClasses = { java.sql.Date .class, 357 java.util.Date .class }; 358 359 private static String [] timePrims = { }; 360 private static Class [] timeClasses = { java.sql.Time .class, 361 java.util.Date .class }; 362 363 private static String [] timestampPrims = { }; 364 private static Class [] timestampClasses = { java.sql.Timestamp .class, 365 java.util.Date .class }; 366 367 379 static int getCastingCost(TObject arg, int argSqlType, Class target) { 380 381 if (target == TObject.class) { 384 return 0; 385 } 386 387 switch (argSqlType) { 388 389 case SQLTypes.BIT: 390 return getCastingCost(arg, bitPrims, bitClasses, target); 391 392 case SQLTypes.TINYINT: 393 return getCastingCost(arg, tinyPrims, tinyClasses, target); 394 395 case SQLTypes.SMALLINT: 396 return getCastingCost(arg, smallPrims, smallClasses, target); 397 398 case SQLTypes.INTEGER: 399 return getCastingCost(arg, intPrims, intClasses, target); 400 401 case SQLTypes.BIGINT: 402 return getCastingCost(arg, bigPrims, bigClasses, target); 403 404 case SQLTypes.REAL: 405 return getCastingCost(arg, floatPrims, floatClasses, target); 406 407 case SQLTypes.FLOAT: 408 case SQLTypes.DOUBLE: 409 return getCastingCost(arg, doublePrims, doubleClasses, target); 410 411 case SQLTypes.NUMERIC: 417 case SQLTypes.DECIMAL: 418 return -1; 419 420 case SQLTypes.CHAR: 421 case SQLTypes.VARCHAR: 422 case SQLTypes.LONGVARCHAR: 423 return getCastingCost(arg, stringPrims, stringClasses, target); 424 425 case SQLTypes.DATE: 426 return getCastingCost(arg, datePrims, dateClasses, target); 427 428 case SQLTypes.TIME: 429 return getCastingCost(arg, timePrims, timeClasses, target); 430 431 case SQLTypes.TIMESTAMP: 432 return getCastingCost(arg, timestampPrims, timestampClasses, target); 433 434 case SQLTypes.BINARY: 435 case SQLTypes.VARBINARY: 436 case SQLTypes.LONGVARBINARY: 437 return -1; 439 case SQLTypes.JAVA_OBJECT: 442 Object argVal = arg.getObject(); 443 if (argVal == null || target.isAssignableFrom(argVal.getClass())) { 444 return OBJECT_COST; 445 } 446 return -1; 447 448 case SQLTypes.NULL: 451 return -1; 452 453 default: 454 return -1; } 456 } 457 458 472 static int getCastingCost(TObject arg, String [] prims, Class [] objects, 473 Class target) { 474 if (target.isPrimitive()) { 475 Object argVal = arg.getObject(); if (argVal == null) { 477 return -1; } 479 String targetName = target.getName(); 480 for (int i = 0; i < prims.length; i++) { 482 if (targetName.equals(prims[i])) 483 return PRIMITIVE_COST+i; 484 } 486 } else { 487 for (int i = 0; i < objects.length; i++) { 489 if (objects[i].isAssignableFrom(target)) 490 return OBJECT_COST+i; 491 } 493 } 494 return -1; } 496 497 506 public static Object [] castArgsToConstructor( 507 TObject[] args, Constructor constructor) { 508 Class [] targets = constructor.getParameterTypes(); 509 return castArgs(args, targets); 510 } 511 512 521 static Object [] castArgs(TObject[] args, Class [] targets) { 522 if (targets.length != args.length) { 523 throw new RuntimeException ("array length mismatch: arg="+args.length+ 525 ", targets="+targets.length); 526 } 527 Object [] castedArgs = new Object [args.length]; 528 for (int n = 0; n < args.length; ++n) { 529 castedArgs[n] = castArg(args[n], targets[n]); 530 } 531 return castedArgs; 532 } 533 534 541 static Object castArg(TObject arg, Class target) { 542 546 if (target == TObject.class) { 547 return arg; 548 } 549 550 Object argVal = arg.getObject(); 551 if (argVal == null) { 552 return null; 555 } 556 557 String targetName = target.getName(); 559 560 if (argVal instanceof Boolean ) { 561 if (targetName.equals("boolean") || 563 Boolean .class.isAssignableFrom(target)) { 564 return argVal; 565 } 566 } 567 568 else if (argVal instanceof Number ) { 569 Number num = (Number )argVal; 572 if (targetName.equals("byte") || Byte .class.isAssignableFrom(target)) { 573 return new Byte (num.byteValue()); 574 } 575 if (targetName.equals("short") || Short .class.isAssignableFrom(target)) { 576 return new Short (num.shortValue()); 577 } 578 if (targetName.equals("int") || Integer .class.isAssignableFrom(target)) { 579 return new Integer (num.intValue()); 580 } 581 if (targetName.equals("long") || Long .class.isAssignableFrom(target)) { 582 return new Long (num.longValue()); 583 } 584 if (targetName.equals("float") || Float .class.isAssignableFrom(target)) { 585 return new Float (num.floatValue()); 586 } 587 if (targetName.equals("double") || 588 Double .class.isAssignableFrom(target)) { 589 return new Float (num.doubleValue()); 590 } 591 } 592 593 else if (argVal instanceof java.util.Date ) { 594 java.util.Date date = (java.util.Date )argVal; 596 if (java.sql.Date .class.isAssignableFrom(target)) { 597 return new java.sql.Date (date.getTime()); 598 } 599 if (java.sql.Time .class.isAssignableFrom(target)) { 600 return new java.sql.Time (date.getTime()); 601 } 602 if (java.sql.Timestamp .class.isAssignableFrom(target)) { 603 return new java.sql.Timestamp (date.getTime()); 604 } 605 if (java.util.Date .class.isAssignableFrom(target)) { 606 return date; 607 } 608 } 609 610 else if (argVal instanceof String || 611 argVal instanceof StringObject) { 612 String s = argVal.toString(); 614 if (String .class.isAssignableFrom(target)) { 615 return s; 616 } 617 } 618 619 else if (getSqlType(arg) == SQLTypes.JAVA_OBJECT) { 620 if (target.isAssignableFrom(argVal.getClass())) { 622 return argVal; 623 } 624 } 625 626 else { 627 } 631 632 637 throw new RuntimeException ("Programming error: Can't cast from "+ 638 argVal.getClass().getName() + " to " + target.getName()); 639 } 640 641 } 642 | Popular Tags |