1 23 24 30 31 package com.sun.jdo.spi.persistence.support.sqlstore.model; 32 33 34 import com.sun.jdo.api.persistence.support.JDOUserException; 35 import com.sun.jdo.api.persistence.support.JDOFatalUserException; 36 import com.sun.jdo.spi.persistence.support.sqlstore.*; 37 import com.sun.jdo.spi.persistence.support.sqlstore.sco.SqlTimestamp; 38 import com.sun.jdo.spi.persistence.utility.FieldTypeEnumeration; 39 import com.sun.jdo.spi.persistence.utility.I18NHelper; 40 import com.sun.jdo.spi.persistence.utility.logging.Logger; 41 import org.netbeans.modules.dbschema.ColumnElement; 42 43 import java.lang.reflect.Field ; 44 import java.math.BigDecimal ; 45 import java.math.BigInteger ; 46 import java.util.ArrayList ; 47 import java.util.Date ; 48 import java.util.ResourceBundle ; 49 50 53 public abstract class FieldDesc implements java.io.Serializable { 54 55 public static final int GROUP_DEFAULT = 1; 56 57 public static final int GROUP_NONE = 0; 58 59 60 public static final int PROP_IN_CONCURRENCY_CHECK = 0x1; 61 62 63 public static final int PROP_LOG_ON_UPDATE = 0x2; 64 65 66 public static final int PROP_READ_ONLY = 0x4; 67 68 69 public static final int PROP_RECORD_ON_UPDATE = 0x8; 70 71 72 public static final int PROP_REF_INTEGRITY_UPDATES = 0x10; 73 74 89 public static final int PROP_PRIMARY_TRACKED_FIELD = 0x20; 90 91 104 public static final int PROP_SECONDARY_TRACKED_FIELD = 0x40; 105 106 110 public static final int PROP_TRACK_RELATIONSHIP_FIELD = 0x80; 111 112 113 public static final int PROP_PRIMARY_KEY_FIELD = 0x100; 114 115 116 public static final int PROP_VERSION_FIELD = 0x200; 117 118 private static final BigDecimal LONG_MIN_VALUE = 119 new BigDecimal (String.valueOf(Long.MIN_VALUE)); 120 121 private static final BigDecimal LONG_MAX_VALUE = 122 new BigDecimal (String.valueOf(Long.MAX_VALUE)); 123 124 public int absoluteID; 125 126 public int fetchGroup; 127 128 public int concurrencyGroup; 129 130 public int sqlProperties; 131 132 private Field field; 133 134 private Class fieldType; 135 136 140 private int enumFieldType; 141 142 private String fieldName; 143 144 private Class declaringClass; 145 146 private Class componentType; 148 149 private ArrayList trackedFields; 150 151 152 protected final ClassDesc classDesc; 153 154 155 protected final static Logger logger = LogHelperSQLStore.getLogger(); 156 157 158 protected final static ResourceBundle messages = I18NHelper.loadBundle( 159 "com.sun.jdo.spi.persistence.support.sqlstore.Bundle", FieldDesc.class.getClassLoader()); 161 162 FieldDesc(ClassDesc classDesc) { 163 sqlProperties |= FieldDesc.PROP_REF_INTEGRITY_UPDATES; 165 sqlProperties |= FieldDesc.PROP_IN_CONCURRENCY_CHECK; 166 sqlProperties |= FieldDesc.PROP_LOG_ON_UPDATE; 167 168 concurrencyGroup = -1; 171 172 this.classDesc = classDesc; 173 } 174 175 public String toString() { 176 return classDesc.getName() + "." + getName(); } 178 179 public Class getComponentType() { 180 return componentType; 181 } 182 183 public Class getDeclaringClass() { 184 return declaringClass; 185 } 186 187 public Class getType() { 188 if (fieldType != null) return fieldType; 189 190 return Object .class; 191 } 192 193 public int getEnumType() { 194 return enumFieldType; 195 } 196 197 public String getName() { 198 if (fieldName == null) 199 fieldName = "hidden" + -absoluteID; 201 return fieldName; 202 } 203 204 public Object getValue(StateManager sm) { 205 if (sm == null) return null; 206 207 if (absoluteID >= 0) { 208 return ((PersistenceCapable) sm.getPersistent()).jdoGetField(absoluteID); 209 } else { 210 return sm.getHiddenValue(absoluteID); 211 } 212 } 213 214 public void setValue(StateManager sm, Object value) { 215 boolean debug = logger.isLoggable(Logger.FINEST); 216 217 if (sm == null) return; 218 219 if (absoluteID >= 0) { 220 if (debug) { 221 if ((value != null) && 222 ((value instanceof com.sun.jdo.api.persistence.support.PersistenceCapable) || 223 (value instanceof java.util.Collection ))) { 224 Object [] items = new Object [] {field.getName(),value.getClass()}; 225 logger.finest("sqlstore.model.fielddesc.fieldname",items); } else { 227 Object [] items = new Object [] {field.getName(),value}; 228 logger.finest("sqlstore.model.fielddesc.fieldname",items); } 230 } 231 232 if (value == null) { 239 switch (enumFieldType) { 240 case FieldTypeEnumeration.BOOLEAN_PRIMITIVE: 241 value = new Boolean (false); 242 break; 243 case FieldTypeEnumeration.CHARACTER_PRIMITIVE: 244 value = new Character ('\0'); 245 break; 246 case FieldTypeEnumeration.BYTE_PRIMITIVE: 247 case FieldTypeEnumeration.SHORT_PRIMITIVE: 248 case FieldTypeEnumeration.INTEGER_PRIMITIVE: 249 case FieldTypeEnumeration.LONG_PRIMITIVE: 250 case FieldTypeEnumeration.FLOAT_PRIMITIVE: 251 case FieldTypeEnumeration.DOUBLE_PRIMITIVE: 252 value = convertValue(new Integer (0), sm); 254 break; 255 } 256 } 257 258 ((PersistenceCapable) sm.getPersistent()).jdoSetField(absoluteID, value); 263 } else { 264 if (debug) { 265 Object [] items = new Object [] {getName(),value}; 266 logger.finest("sqlstore.model.fielddesc.fieldname",items); } 268 269 sm.setHiddenValue(absoluteID, value); 270 } 271 } 272 273 public ArrayList getTrackedFields() { 274 return trackedFields; 275 } 276 277 280 public boolean isKeyField() { 281 return ((sqlProperties & PROP_PRIMARY_KEY_FIELD) > 0); 282 } 283 284 287 public boolean isRelationshipField() { 288 return false; 289 } 290 291 public Object convertValue(Object value, StateManager sm) { 292 boolean debug = logger.isLoggable(Logger.FINEST); 293 if (value == null) { 294 if (debug) 295 logger.finest("sqlstore.model.fielddesc.convertvalue"); return value; 297 } 298 299 if (absoluteID < 0) { 300 if (debug) 302 logger.finest("sqlstore.model.fielddesc.convertvalue.hidden",new Integer (absoluteID)); return value; 304 } 305 306 if (debug) { 307 Object [] items = new Object [] {value,value.getClass().getName(),fieldType}; 308 logger.finest("sqlstore.model.fielddesc.convertvalue.from_to",items); } 310 311 if (value instanceof Number ) { 314 Number number = (Number ) value; 315 316 switch (enumFieldType) { 317 case FieldTypeEnumeration.BOOLEAN_PRIMITIVE: 318 case FieldTypeEnumeration.BOOLEAN: 319 if (number.doubleValue() == 0) { 326 value = new Boolean (false); 327 } else { 328 value = new Boolean (true); 329 } 330 break; 331 case FieldTypeEnumeration.BYTE_PRIMITIVE: 332 case FieldTypeEnumeration.BYTE: 333 if (!(value instanceof Byte )) { 334 assertIsValid(number, Byte.MIN_VALUE, Byte.MAX_VALUE); 335 value = new Byte (number.byteValue()); 336 } 337 break; 338 case FieldTypeEnumeration.SHORT_PRIMITIVE: 339 case FieldTypeEnumeration.SHORT: 340 if (!(value instanceof Short )) { 341 assertIsValid(number, Short.MIN_VALUE, Short.MAX_VALUE); 342 value = new Short (number.shortValue()); 343 } 344 break; 345 case FieldTypeEnumeration.INTEGER_PRIMITIVE: 346 case FieldTypeEnumeration.INTEGER: 347 if (!(value instanceof Integer )) { 348 assertIsValid(number, Integer.MIN_VALUE, Integer.MAX_VALUE); 349 value = new Integer (number.intValue()); 350 } 351 break; 352 case FieldTypeEnumeration.LONG_PRIMITIVE: 353 case FieldTypeEnumeration.LONG: 354 if (!(value instanceof Long )) { 355 assertIsValidLong(number); 356 value = new Long (number.longValue()); 357 } 358 break; 359 case FieldTypeEnumeration.FLOAT_PRIMITIVE: 360 case FieldTypeEnumeration.FLOAT: 361 if (!(value instanceof Float )) 362 value = new Float (number.floatValue()); 363 break; 364 case FieldTypeEnumeration.DOUBLE_PRIMITIVE: 365 case FieldTypeEnumeration.DOUBLE: 366 if (!(value instanceof Double )) { 367 if (value instanceof Float ) 369 value = new Double (number.toString()); 370 else 371 value = new Double (number.doubleValue()); 372 } 373 break; 374 case FieldTypeEnumeration.BIGDECIMAL: 375 if (!(value instanceof BigDecimal )) { 376 if (value instanceof Double ) 377 value = new BigDecimal (number.doubleValue()); 378 else if (value instanceof BigInteger ) 379 value = new BigDecimal ((java.math.BigInteger ) value); 380 else 381 value = new BigDecimal (number.toString()); 382 } 383 break; 384 case FieldTypeEnumeration.BIGINTEGER: 385 if (!(value instanceof BigInteger )) { 386 if (value instanceof BigDecimal ) 387 value = ((BigDecimal ) value).toBigInteger(); 388 else 389 value = new BigInteger (number.toString()); 390 } 391 break; 392 } 393 } else { 394 395 switch (enumFieldType) { 396 case FieldTypeEnumeration.STRING: 397 if (!(value instanceof String )) { 400 value = value.toString(); 401 } 402 break; 403 404 case FieldTypeEnumeration.UTIL_DATE: 405 case FieldTypeEnumeration.SQL_DATE: 406 case FieldTypeEnumeration.SQL_TIME: 407 case FieldTypeEnumeration.SQL_TIMESTAMP: 408 value = convertToDateFieldType(value, sm); 409 break; 410 411 case FieldTypeEnumeration.CHARACTER_PRIMITIVE: 412 case FieldTypeEnumeration.CHARACTER: 413 if (!(value instanceof Character )) { 416 String str = value.toString(); 417 value = getCharFromString(str); 418 } 419 break; 420 421 case FieldTypeEnumeration.BOOLEAN_PRIMITIVE: 422 case FieldTypeEnumeration.BOOLEAN: 423 if (!(value instanceof Boolean )) { 426 if ((value instanceof String ) && 427 (value).equals("1")) value = "true"; 430 value = new Boolean (value.toString()); 431 } 432 break; 433 } 434 } 435 436 return value; 437 } 438 439 449 public Object createSCO(Object value, StateManager sm) { 450 Object retVal = null; 451 452 PersistenceManager pm = null; 453 if (sm != null) { 454 pm = (PersistenceManager) sm.getPersistenceManagerInternal(); 455 } 456 457 if (pm != null && pm.getRequireTrackedSCO()) { 458 retVal = pm.newSCOInstanceInternal(fieldType, 460 sm.getPersistent(), 461 getName()); 462 463 initializeSCO(retVal, value); 464 } 465 466 return retVal; 467 } 468 469 public static Character getCharFromString(String str) { 470 Character retVal = null; 471 if (str.length() == 0) { 472 retVal = new Character ('\0'); 473 } else { 474 retVal = new Character (str.charAt(0)); 475 } 476 return retVal; 477 } 478 479 489 private Object convertToDateFieldType(Object value, StateManager sm) { 490 if (value instanceof SCO) { 491 ((SCO) value).unsetOwner(); 492 } 493 494 Object retVal = createSCO(value, sm); 495 496 if (retVal == null) { 497 retVal = convertToDateFieldType(value); 502 } 503 504 return retVal; 505 } 506 507 516 private Object convertToDateFieldType(Object value) { 517 Object retVal = value; 518 519 if (!fieldType.equals(value.getClass())) { 520 522 if (value instanceof Date ) { 523 switch (enumFieldType) { 524 case FieldTypeEnumeration.UTIL_DATE: 525 retVal = new java.util.Date (((Date ) value).getTime()); 526 break; 527 case FieldTypeEnumeration.SQL_DATE: 528 retVal = new java.sql.Date (((Date ) value).getTime()); 529 break; 530 case FieldTypeEnumeration.SQL_TIME: 531 retVal = new java.sql.Time (((Date ) value).getTime()); 532 break; 533 case FieldTypeEnumeration.SQL_TIMESTAMP: 534 retVal = new java.sql.Timestamp (((Date ) value).getTime()); 535 536 if (value instanceof java.sql.Timestamp ) { 542 ((java.sql.Timestamp ) retVal).setNanos(((java.sql.Timestamp ) value).getNanos()); 544 } 545 break; 546 default: 547 } 548 } 549 } 550 551 return retVal; 552 } 553 554 561 private void initializeSCO(Object scoVal, Object value) { 562 switch(enumFieldType) { 563 case FieldTypeEnumeration.UTIL_DATE: 564 case FieldTypeEnumeration.SQL_DATE: 565 case FieldTypeEnumeration.SQL_TIME: 566 case FieldTypeEnumeration.SQL_TIMESTAMP: 567 if (value instanceof Date ) { 569 ((SCODate) scoVal).setTimeInternal(((Date ) value).getTime()); 571 572 if (enumFieldType == FieldTypeEnumeration.SQL_TIMESTAMP 578 && value instanceof java.sql.Timestamp ) { 579 ((SqlTimestamp) scoVal).setNanosInternal(((java.sql.Timestamp ) value).getNanos()); 581 } 582 } 583 break; 584 default: 585 } 586 } 587 588 private void assertIsValid(Number number, double min_value, double max_value) { 589 double x = number.doubleValue(); 590 if (x < min_value) 591 throw new JDOUserException(I18NHelper.getMessage(messages, 592 "core.fielddesc.minvalue", new Object []{number, String.valueOf(min_value), fieldType.getName()})); 594 if (x > max_value) 595 throw new JDOUserException(I18NHelper.getMessage(messages, 596 "core.fielddesc.maxvalue", new Object []{number, String.valueOf(max_value), fieldType.getName()})); 598 } 599 600 private void assertIsValidLong(Number number) { 601 BigDecimal bd = null; 602 if (number instanceof BigDecimal ) { 603 bd = (BigDecimal ) number; 604 } else { 605 bd = new BigDecimal (number.toString()); 606 } 607 if (bd.compareTo(LONG_MIN_VALUE) < 0) { 608 throw new JDOUserException(I18NHelper.getMessage(messages, 609 "core.fielddesc.minvalue", new Object []{number, String.valueOf(Long.MIN_VALUE), 611 fieldType.getName()})); 612 613 } else if (bd.compareTo(LONG_MAX_VALUE) > 0) { 614 throw new JDOUserException(I18NHelper.getMessage(messages, 615 "core.fielddesc.maxvalue", new Object []{number, String.valueOf(Long.MAX_VALUE), 617 fieldType.getName()})); 618 } 619 } 620 621 625 void setupDesc(final Class classType, final String name) { 626 627 Field f = (Field ) java.security.AccessController.doPrivileged( 628 new java.security.PrivilegedAction () { 629 public Object run() { 630 try { 631 return classType.getDeclaredField(name); 632 } catch (NoSuchFieldException e) { 633 throw new JDOFatalUserException(I18NHelper.getMessage(messages, 634 "core.configuration.loadfailed.field", name, classType.getName()), e); 636 } 637 } 638 }); 639 640 setupDesc(f); 641 } 642 643 protected void setupDesc(Field f) { 644 field = f; 645 fieldName = f.getName(); 646 declaringClass = field.getDeclaringClass(); 647 648 fieldType = field.getType(); 649 enumFieldType = translateToEnumType(fieldType); 650 651 if (logger.isLoggable(Logger.FINEST)) { 652 Object [] items= new Object [] {fieldName,fieldType}; 653 logger.finest("sqlstore.model.fielddesc.setupdesc",items); } 655 } 656 657 private static int translateToEnumType(Class fldType) { 658 659 int retVal = FieldTypeEnumeration.NOT_ENUMERATED; 660 661 if(fldType == Boolean.TYPE ) retVal = FieldTypeEnumeration.BOOLEAN_PRIMITIVE; 662 else if(fldType == Character.TYPE ) retVal = FieldTypeEnumeration.CHARACTER_PRIMITIVE; 663 else if(fldType == Byte.TYPE ) retVal = FieldTypeEnumeration.BYTE_PRIMITIVE; 664 else if(fldType == Short.TYPE ) retVal = FieldTypeEnumeration.SHORT_PRIMITIVE; 665 else if(fldType == Integer.TYPE ) retVal = FieldTypeEnumeration.INTEGER_PRIMITIVE; 666 else if(fldType == Long.TYPE ) retVal = FieldTypeEnumeration.LONG_PRIMITIVE ; 667 else if(fldType == Float.TYPE ) retVal = FieldTypeEnumeration.FLOAT_PRIMITIVE; 668 else if(fldType == Double.TYPE ) retVal = FieldTypeEnumeration.DOUBLE_PRIMITIVE; 669 else if(fldType == Boolean .class ) retVal = FieldTypeEnumeration.BOOLEAN; 670 else if(fldType == Character .class ) retVal = FieldTypeEnumeration.CHARACTER; 671 else if(fldType == Byte .class ) retVal = FieldTypeEnumeration.BYTE; 672 else if(fldType == Short .class ) retVal = FieldTypeEnumeration.SHORT; 673 else if(fldType == Integer .class ) retVal = FieldTypeEnumeration.INTEGER; 674 else if(fldType == Long .class ) retVal = FieldTypeEnumeration.LONG; 675 else if(fldType == Float .class ) retVal = FieldTypeEnumeration.FLOAT; 676 else if(fldType == Double .class ) retVal = FieldTypeEnumeration.DOUBLE; 677 else if(fldType == java.math.BigDecimal .class) retVal = FieldTypeEnumeration.BIGDECIMAL; 678 else if(fldType == java.math.BigInteger .class) retVal = FieldTypeEnumeration.BIGINTEGER; 679 else if(fldType == String .class ) retVal = FieldTypeEnumeration.STRING; 680 else if(fldType == java.util.Date .class ) retVal = FieldTypeEnumeration.UTIL_DATE; 681 else if(fldType == java.sql.Date .class ) retVal = FieldTypeEnumeration.SQL_DATE; 682 else if(fldType == java.sql.Time .class ) retVal = FieldTypeEnumeration.SQL_TIME; 683 else if(fldType == java.sql.Timestamp .class ) retVal = FieldTypeEnumeration.SQL_TIMESTAMP; 684 else if(fldType.isArray()) { 685 if(fldType.getComponentType() == Byte.TYPE) { 686 retVal = FieldTypeEnumeration.ARRAY_BYTE_PRIMITIVE; 687 } 688 } 689 690 return retVal; 691 } 692 693 void setComponentType(Class type) { 694 this.componentType = type; 695 } 696 697 protected void addTrackedField(FieldDesc f) { 698 if (trackedFields == null) 699 trackedFields = new ArrayList (); 700 701 if (logger.isLoggable(Logger.FINEST)) { 702 Object [] items = new Object [] {f.getName(),getName()}; 703 logger.finest("sqlstore.model.fielddesc.addingfield",items); } 705 706 trackedFields.add(f); 707 } 708 709 abstract void computeTrackedRelationshipFields(); 710 711 718 static boolean compareColumns(FieldDesc f1, FieldDesc f2) { 719 ArrayList columnList1 = null; 720 ArrayList columnList2 = null; 721 ArrayList columnList3 = null; 722 ArrayList columnList4 = null; 723 boolean exactMatch = false; 724 725 if (f1 instanceof LocalFieldDesc) { 728 columnList1 = ((LocalFieldDesc) f1).columnDescs; 729 730 if (f2 instanceof LocalFieldDesc) { 731 columnList2 = ((LocalFieldDesc) f2).columnDescs; 732 733 exactMatch = true; 736 } else { 737 columnList2 = ((ForeignFieldDesc) f2).localColumns; 741 } 742 } else { 743 if (f2 instanceof LocalFieldDesc) { 744 return false; 745 } else { 746 ForeignFieldDesc ff1 = (ForeignFieldDesc) f1; 747 ForeignFieldDesc ff2 = (ForeignFieldDesc) f2; 748 749 if (ff1.useJoinTable() && ff2.useJoinTable()) { 750 columnList1 = ff1.assocLocalColumns; 751 columnList2 = ff2.assocLocalColumns; 752 columnList3 = ff1.assocForeignColumns; 753 columnList4 = ff2.assocForeignColumns; 754 } else if (!ff1.useJoinTable() && !ff2.useJoinTable()) { 755 columnList1 = ff1.localColumns; 756 columnList2 = ff2.localColumns; 757 columnList3 = ff1.foreignColumns; 758 columnList4 = ff2.foreignColumns; 759 } else { 760 return false; 761 } 762 763 exactMatch = true; 764 } 765 } 766 767 boolean found = false; 768 769 for (int k = 0; k < 2; k++) { 770 if (k == 1) { 771 if (columnList3 != null) { 772 columnList1 = columnList3; 773 columnList2 = columnList4; 774 } else { 775 break; 776 } 777 } 778 779 int size1 = columnList1.size(); 780 int size2 = columnList2.size(); 781 782 if (exactMatch && (size1 != size2)) { 783 return false; 784 } 785 786 for (int i = 0; i < size1; i++) { 787 found = false; 788 789 ColumnElement c1 = (ColumnElement) columnList1.get(i); 790 791 for (int j = 0; j < size2; j++) { 793 ColumnElement c2 = (ColumnElement) columnList2.get(j); 794 795 if (c1.getName().getFullName().equals(c2.getName().getFullName())) { 796 found = true; 797 } 798 } 799 800 if (exactMatch && !found) { 803 return false; 804 } 805 806 if (!exactMatch && found) { 809 return true; 810 } 811 } 812 } 813 814 return found; 817 } 818 819 } 820 | Popular Tags |