1 23 24 30 31 package com.sun.jdo.spi.persistence.support.sqlstore.model; 32 33 import org.netbeans.modules.dbschema.ColumnElement; 34 import com.sun.jdo.spi.persistence.utility.FieldTypeEnumeration; 35 import com.sun.jdo.spi.persistence.utility.logging.Logger; 36 import com.sun.jdo.spi.persistence.support.sqlstore.StateManager; 37 38 import java.util.ArrayList ; 39 import java.util.Iterator ; 40 import java.lang.reflect.Field ; 41 import java.sql.Types ; 42 import java.math.BigInteger ; 43 import java.math.BigDecimal ; 44 45 46 49 public class LocalFieldDesc extends FieldDesc { 50 51 52 final ArrayList columnDescs; 53 54 55 private Boolean primitiveMappedToNullableColumn; 56 57 58 private final int primaryColumnType; 59 60 LocalFieldDesc(ClassDesc config, ArrayList columnDescs) { 61 super(config); 62 this.columnDescs = columnDescs; 63 64 primaryColumnType = getPrimaryColumn().getType(); 66 67 sqlProperties |= FieldDesc.PROP_RECORD_ON_UPDATE; 68 } 69 70 public boolean isPrimitiveMappedToNullableColumn() { 71 if (primitiveMappedToNullableColumn == null) { 72 boolean rc = getType().isPrimitive(); 73 74 for (Iterator iter = columnDescs.iterator(); iter.hasNext() && rc; ) { 75 ColumnElement c = (ColumnElement) iter.next(); 76 rc = c.isNullable(); 77 } 78 primitiveMappedToNullableColumn = new Boolean (rc); 79 } 80 81 return primitiveMappedToNullableColumn.booleanValue(); 82 } 83 84 90 public boolean isMappedToLob() { 91 return 92 primaryColumnType == Types.BLOB || 93 94 98 isCharLobType(primaryColumnType) || 99 getEnumType() == FieldTypeEnumeration.ARRAY_BYTE_PRIMITIVE; 102 } 103 104 110 public static boolean isCharLobType(int sqlType) { 111 return 113 sqlType == Types.LONGVARCHAR || 114 sqlType == Types.CLOB; 115 } 116 117 125 public static boolean isFixedCharType(int sqlType) { 126 return sqlType == Types.CHAR; 127 } 128 129 133 public ColumnElement getPrimaryColumn() { 134 return ((ColumnElement) columnDescs.get(0)); 135 } 136 137 141 public Iterator getColumnElements() { 142 return columnDescs.iterator(); 143 } 144 145 148 public boolean isVersion() { 149 return ((sqlProperties & FieldDesc.PROP_VERSION_FIELD) > 0); 150 } 151 152 158 public void incrementValue(StateManager sm) { 159 assert isVersion(); 160 161 Long val = (Long ) getValue(sm); 162 long value = (val != null) ? val.longValue() : 0; 163 164 setValue(sm, new Long (++value)); 165 } 166 167 171 175 protected void setupDesc(Field f) { 176 super.setupDesc(f); 177 178 if (isMappedToLob() ) { 180 sqlProperties = sqlProperties & ~PROP_IN_CONCURRENCY_CHECK; 181 } 182 183 switch (getEnumType()) { 185 case FieldTypeEnumeration.FLOAT_PRIMITIVE: 186 case FieldTypeEnumeration.FLOAT: 187 case FieldTypeEnumeration.DOUBLE_PRIMITIVE: 188 case FieldTypeEnumeration.DOUBLE: 189 case FieldTypeEnumeration.BIGDECIMAL: 190 sqlProperties &= ~PROP_IN_CONCURRENCY_CHECK; 191 } 192 } 193 194 200 private static final Class [] nonNullableNonScaledTypes = 201 { 202 Long.TYPE, Integer.TYPE, Short.TYPE, Byte.TYPE, Double.TYPE, 203 Float.TYPE, BigInteger .class, BigDecimal .class, Long .class, 204 Integer .class, Short .class, Byte .class, Double .class, Float .class 205 }; 206 207 213 private static final Class [] nullableNonScaledTypes = 214 { 215 BigInteger .class, BigDecimal .class, Long .class, Integer .class, Short .class, 216 Byte .class, Double .class, Float .class, Long.TYPE, Integer.TYPE, 217 Short.TYPE, Byte.TYPE, Double.TYPE, Float.TYPE 218 }; 219 220 226 private static final Class [] nonNullableScaledTypes = 227 { 228 Double.TYPE, Float.TYPE, Long.TYPE, Integer.TYPE, Short.TYPE, 229 Byte.TYPE, BigDecimal .class, Double .class, BigInteger .class, 230 Long .class, Integer .class, Short .class, Byte .class 231 }; 232 233 239 private static final Class [] nullableScaledTypes = 240 { 241 BigDecimal .class, Double .class, Float .class, BigInteger .class, 242 Long .class, Integer .class, Short .class, Byte .class, Double.TYPE, 243 Float.TYPE, Long.TYPE, Integer.TYPE, Short.TYPE, Byte.TYPE 244 }; 245 246 256 private static int lookupTypePrecedence(Class type, Class typePrecedence[]) { 257 for (int i = 0; i < typePrecedence.length; i++) { 258 if (type == typePrecedence[i]) { 259 return i; 260 } 261 } 262 263 return Integer.MAX_VALUE; 264 } 265 266 271 private int computeTypePrecedence() { 272 ColumnElement c = (ColumnElement) columnDescs.get(0); 273 int sqlType = c.getType(); 274 Class type = getType(); 275 boolean isNullable = c.isNullable(); 276 int precedence = Integer.MAX_VALUE; 277 278 switch (sqlType) { 279 case Types.TINYINT: 280 case Types.SMALLINT: 281 case Types.INTEGER: 282 case Types.BIGINT: 283 if (isNullable) { 284 precedence = lookupTypePrecedence(type, nullableNonScaledTypes); 285 } else { 286 precedence = lookupTypePrecedence(type, nonNullableNonScaledTypes); 287 } 288 break; 289 case Types.REAL: 290 case Types.FLOAT: 291 case Types.DOUBLE: 292 if (isNullable) { 293 precedence = lookupTypePrecedence(type, nullableScaledTypes); 294 } else { 295 precedence = lookupTypePrecedence(type, nonNullableScaledTypes); 296 } 297 break; 298 case Types.NUMERIC: 299 case Types.DECIMAL: 300 int scale = -1; 301 if ((scale = c.getScale().intValue()) == 0) { 302 if (isNullable) { 304 precedence = lookupTypePrecedence(type, nullableNonScaledTypes); 305 } else { 306 precedence = lookupTypePrecedence(type, nonNullableNonScaledTypes); 307 } 308 } else if (scale > 0) { 309 if (isNullable) { 311 precedence = lookupTypePrecedence(type, nullableScaledTypes); 312 } else { 313 precedence = lookupTypePrecedence(type, nonNullableScaledTypes); 314 } 315 } 316 break; 317 case Types.CHAR: 318 case Types.VARCHAR: 319 case Types.LONGVARCHAR: 320 if (type == String .class) { 321 precedence = 0; 322 } 323 break; 324 case Types.DATE: 325 case Types.TIMESTAMP: 326 if (java.util.Date .class.isAssignableFrom(type)) { 327 precedence = 0; 328 } 329 break; 330 case Types.BIT: 331 if (type == Boolean .class) { 332 if (isNullable) { 333 precedence = 0; 334 } else { 335 precedence = 1; 336 } 337 } else if (type == Boolean.TYPE) { 338 if (isNullable) { 339 precedence = 1; 340 } else { 341 precedence = 0; 342 } 343 } 344 break; 345 } 346 347 return precedence; 348 } 349 350 void computeTrackedPrimitiveFields() { 351 for (int i = 0; i < classDesc.fields.size(); i++) { 352 FieldDesc tf = (FieldDesc) classDesc.fields.get(i); 353 354 if ((tf instanceof LocalFieldDesc) && (this != tf) && (compareColumns(this, tf) == true)) { 355 addTrackedField(tf); 356 } 357 } 358 } 359 360 363 void computePrimaryTrackedPrimitiveField() { 364 ArrayList trackedFields = null; 365 366 if (((trackedFields = getTrackedFields()) == null) || 368 (sqlProperties & (FieldDesc.PROP_PRIMARY_TRACKED_FIELD | 369 FieldDesc.PROP_SECONDARY_TRACKED_FIELD | 370 FieldDesc.PROP_READ_ONLY)) > 0) { 371 return; 372 } 373 374 sqlProperties |= FieldDesc.PROP_SECONDARY_TRACKED_FIELD; 377 378 FieldDesc primaryTrackedField = null; 379 int currentPrecedence = Integer.MAX_VALUE; 380 int precedence = 0; 381 382 if ((precedence = computeTypePrecedence()) < currentPrecedence) { 383 primaryTrackedField = this; 384 currentPrecedence = precedence; 385 } 386 387 for (int j = 0; j < trackedFields.size(); j++) { 388 FieldDesc tf = (FieldDesc) trackedFields.get(j); 389 390 if (tf instanceof ForeignFieldDesc) { 393 continue; 394 } 395 396 tf.sqlProperties |= FieldDesc.PROP_SECONDARY_TRACKED_FIELD; 399 400 if ((precedence = ((LocalFieldDesc) tf).computeTypePrecedence()) < currentPrecedence) { 401 primaryTrackedField = tf; 402 currentPrecedence = precedence; 403 } 404 } 405 406 if (primaryTrackedField == null) { 409 primaryTrackedField = this; 410 } 411 412 if (logger.isLoggable(Logger.FINEST)) { 413 logger.finest("sqlstore.model.classdesc.primarytrackedfield", primaryTrackedField.getName()); } 415 416 primaryTrackedField.sqlProperties |= FieldDesc.PROP_PRIMARY_TRACKED_FIELD; 417 primaryTrackedField.sqlProperties &= ~FieldDesc.PROP_SECONDARY_TRACKED_FIELD; 418 } 419 420 void computeTrackedRelationshipFields() { 421 422 if (((sqlProperties & FieldDesc.PROP_REF_INTEGRITY_UPDATES) == 0) && 423 ((sqlProperties & FieldDesc.PROP_PRIMARY_KEY_FIELD) == 0)) { 424 return; 425 } 426 427 for (int k = 0; k < classDesc.foreignFields.size(); k++) { 428 ForeignFieldDesc tf = (ForeignFieldDesc) classDesc.foreignFields.get(k); 429 430 if (compareColumns(this, tf) == true) { 431 if (((sqlProperties & FieldDesc.PROP_PRIMARY_KEY_FIELD) > 0) && 436 ((tf.cardinalityUPB > 1) || (tf.cardinalityLWB == 0))) { 437 continue; 438 } 439 440 if (getTrackedFields() == null) { 444 sqlProperties |= FieldDesc.PROP_PRIMARY_TRACKED_FIELD; 445 } 446 447 addTrackedField(tf); 448 449 sqlProperties |= FieldDesc.PROP_TRACK_RELATIONSHIP_FIELD; 451 } 452 } 453 } 454 455 void cleanupTrackedFields() { 456 ArrayList trackedFields = getTrackedFields(); 457 458 if (trackedFields != null) { 459 for (int j = 1; ; j++) { 460 int index = trackedFields.size() - j; 461 462 if (index < 0) { 463 break; 464 } 465 466 FieldDesc tf = (FieldDesc) trackedFields.get(index); 467 468 if (tf instanceof LocalFieldDesc) { 469 break; 470 } 471 472 ArrayList foreignTrackedFields = tf.getTrackedFields(); 473 474 if (foreignTrackedFields != null) { 475 trackedFields.removeAll(foreignTrackedFields); 476 } 477 } 478 } 479 } 480 481 } 482 | Popular Tags |