1 29 30 package com.caucho.amber.cfg; 31 32 import com.caucho.amber.AmberTableCache; 33 import com.caucho.amber.field.AmberField; 34 import com.caucho.amber.field.Id; 35 import com.caucho.amber.field.IdField; 36 import com.caucho.amber.field.KeyPropertyField; 37 import com.caucho.amber.field.PropertyField; 38 import com.caucho.amber.manager.AmberPersistenceUnit; 39 import com.caucho.amber.table.Column; 40 import com.caucho.amber.table.Table; 41 import com.caucho.amber.type.EntityType; 42 import com.caucho.amber.type.Type; 43 import com.caucho.bytecode.JAnnotation; 44 import com.caucho.bytecode.JClass; 45 import com.caucho.bytecode.JMethod; 46 import com.caucho.config.ConfigException; 47 import com.caucho.config.types.Period; 48 import com.caucho.util.L10N; 49 50 import javax.persistence.AttributeOverrides; 51 import javax.persistence.InheritanceType; 52 import javax.persistence.MappedSuperclass; 53 import java.sql.SQLException ; 54 import java.util.ArrayList ; 55 import java.util.HashMap ; 56 import java.util.logging.Logger ; 57 58 61 public class EntityIntrospector extends BaseConfigIntrospector { 62 private static final L10N L = new L10N(EntityIntrospector.class); 63 private static final Logger log 64 = Logger.getLogger(EntityIntrospector.class.getName()); 65 66 HashMap <String , EntityType> _entityMap 67 = new HashMap <String , EntityType>(); 68 69 72 public EntityIntrospector(AmberPersistenceUnit persistenceUnit) 73 { 74 super(persistenceUnit); 75 } 76 77 80 public boolean isEntity(JClass type) 81 { 82 getInternalEntityConfig(type); 83 JAnnotation entityAnn = _annotationCfg.getAnnotation(); 84 EntityConfig entityConfig = _annotationCfg.getEntityConfig(); 85 86 return (! _annotationCfg.isNull()); 87 } 88 89 92 public EntityType introspect(JClass type) 93 throws ConfigException, SQLException 94 { 95 EntityType entityType = null; 96 97 try { 98 getInternalEntityConfig(type); 99 JAnnotation entityAnn = _annotationCfg.getAnnotation(); 100 EntityConfig entityConfig = _annotationCfg.getEntityConfig(); 101 102 boolean isEntity = ! _annotationCfg.isNull(); 103 104 String typeName; 105 106 if (isEntity) { 107 if (entityConfig != null) 108 typeName = entityConfig.getClassName(); 109 else 110 typeName = entityAnn.getString("name"); 111 } 112 else { 113 getInternalMappedSuperclassConfig(type); 114 JAnnotation mappedSuperAnn = _annotationCfg.getAnnotation(); 115 MappedSuperclassConfig mappedSuperConfig = _annotationCfg.getMappedSuperclassConfig(); 116 117 boolean isMappedSuperclass = ! _annotationCfg.isNull(); 118 119 if (isMappedSuperclass) { 120 if (mappedSuperConfig != null) 121 typeName = mappedSuperConfig.getClassName(); 122 else 123 typeName = mappedSuperAnn.getString("name"); 124 } 125 else 126 throw new ConfigException(L.l("'{0}' is not an @Entity or @MappedSuperclass.", 127 type)); 128 } 129 130 introspectNamedQueries(type, typeName); 132 introspectNamedNativeQueries(type, typeName); 133 134 String entityName; 136 EntityType parentType = null; 137 JAnnotation inheritanceAnn = null; 138 InheritanceConfig inheritanceConfig = null; 139 JClass rootClass = type; 140 JAnnotation rootEntityAnn = null; 141 EntityConfig rootEntityConfig = null; 142 143 if (isEntity) { 144 validateType(type); 145 146 150 getInternalInheritanceConfig(type); 151 inheritanceAnn = _annotationCfg.getAnnotation(); 152 inheritanceConfig = _annotationCfg.getInheritanceConfig(); 153 154 boolean hasInheritance = ! _annotationCfg.isNull(); 155 156 for (JClass parentClass = type.getSuperClass(); 157 parentClass != null; 158 parentClass = parentClass.getSuperClass()) { 159 160 getInternalEntityConfig(parentClass); 161 162 if (_annotationCfg.isNull()) 163 break; 164 165 rootEntityAnn = _annotationCfg.getAnnotation(); 166 rootEntityConfig = _annotationCfg.getEntityConfig(); 167 168 rootClass = parentClass; 169 170 if (hasInheritance) 171 throw new ConfigException(L.l("'{0}' cannot have @Inheritance. It must be specified on the entity class that is the root of the entity class hierarchy.", 172 type)); 173 174 getInternalInheritanceConfig(rootClass); 175 inheritanceAnn = _annotationCfg.getAnnotation(); 176 inheritanceConfig = _annotationCfg.getInheritanceConfig(); 177 178 hasInheritance = ! _annotationCfg.isNull(); 179 } 180 181 if (hasInheritance) { 182 183 for (JClass parentClass = type.getSuperClass(); 184 parentClass != null; 185 parentClass = parentClass.getSuperClass()) { 186 187 getInternalEntityConfig(parentClass); 188 JAnnotation parentEntity = _annotationCfg.getAnnotation(); 189 EntityConfig superEntityConfig = _annotationCfg.getEntityConfig(); 190 191 if (! _annotationCfg.isNull()) { 192 parentType = introspect(parentClass); 193 break; 194 } 195 196 } 205 } 206 207 if (entityAnn != null) 208 entityName = entityAnn.getString("name"); 209 else { 210 entityName = entityConfig.getClassName(); 211 212 int p = entityName.lastIndexOf('.'); 213 214 if (p > 0) 215 entityName = entityName.substring(p + 1); 216 } 217 } 218 else { 219 entityName = type.getName(); 220 } 221 222 if (entityName.equals("")) { 223 entityName = type.getName(); 224 int p = entityName.lastIndexOf('.'); 225 if (p > 0) 226 entityName = entityName.substring(p + 1); 227 } 228 229 entityType = _entityMap.get(entityName); 230 231 if (entityType != null) 232 return entityType; 233 234 entityType = _persistenceUnit.createEntity(entityName, type); 235 _entityMap.put(entityName, entityType); 236 237 introspectEntityListeners(type, entityType, _persistenceUnit); 239 240 introspectSqlResultSetMappings(type, entityType, typeName); 242 243 boolean isField = isField(type, entityConfig, false); 244 245 if (isField) 246 entityType.setFieldAccess(true); 247 248 entityType.setInstanceClassName(type.getName() + "__ResinExt"); 249 entityType.setEnhanced(true); 250 251 Table table = null; 252 253 getInternalTableConfig(type); 254 JAnnotation tableAnn = _annotationCfg.getAnnotation(); 255 TableConfig tableConfig = _annotationCfg.getTableConfig(); 256 257 String tableName = null; 258 259 if (tableAnn != null) 260 tableName = (String ) tableAnn.get("name"); 261 else if (tableConfig != null) 262 tableName = tableConfig.getName(); 263 264 if (tableName == null || tableName.equals("")) 265 tableName = entityName.toUpperCase(); 266 267 if (isEntity) { 268 269 InheritanceType strategy = null; 270 271 if (inheritanceAnn != null) 272 strategy = (InheritanceType) inheritanceAnn.get("strategy"); 273 else if (inheritanceConfig != null) 274 strategy = inheritanceConfig.getStrategy(); 275 276 if (parentType == null) 277 entityType.setTable(_persistenceUnit.createTable(tableName)); 278 else if (strategy == InheritanceType.JOINED) { 279 entityType.setTable(_persistenceUnit.createTable(tableName)); 280 281 getInternalTableConfig(rootClass); 282 JAnnotation rootTableAnn = _annotationCfg.getAnnotation(); 283 TableConfig rootTableConfig = _annotationCfg.getTableConfig(); 284 285 String rootTableName = null; 286 287 if (rootTableAnn != null) 288 rootTableName = (String ) rootTableAnn.get("name"); 289 else if (rootTableConfig != null) 290 rootTableName = rootTableConfig.getName(); 291 292 if (rootTableName == null || rootTableName.equals("")) { 293 294 String rootEntityName; 295 296 if (rootEntityAnn != null) 297 rootEntityName = rootEntityAnn.getString("name"); 298 else { 299 rootEntityName = rootEntityConfig.getClassName(); 300 301 int p = rootEntityName.lastIndexOf('.'); 302 303 if (p > 0) 304 rootEntityName = rootEntityName.substring(p + 1); 305 } 306 307 if (rootEntityName.equals("")) { 308 rootEntityName = rootClass.getName(); 309 310 int p = rootEntityName.lastIndexOf('.'); 311 312 if (p > 0) 313 rootEntityName = rootEntityName.substring(p + 1); 314 } 315 316 rootTableName = rootEntityName.toUpperCase(); 317 } 318 319 entityType.setRootTableName(rootTableName); 320 } 321 else 322 entityType.setTable(parentType.getTable()); 323 } 324 325 JAnnotation tableCache = type.getAnnotation(AmberTableCache.class); 326 327 if (tableCache != null) { 328 entityType.getTable().setReadOnly(tableCache.getBoolean("readOnly")); 329 330 long cacheTimeout = Period.toPeriod(tableCache.getString("timeout")); 331 entityType.getTable().setCacheTimeout(cacheTimeout); 332 } 333 334 getInternalSecondaryTableConfig(type); 335 JAnnotation secondaryTableAnn = _annotationCfg.getAnnotation(); 336 SecondaryTableConfig secondaryTableConfig = _annotationCfg.getSecondaryTableConfig(); 337 338 Table secondaryTable = null; 339 340 if ((inheritanceAnn != null) || (inheritanceConfig != null)) 341 introspectInheritance(_persistenceUnit, entityType, type, 342 inheritanceAnn, inheritanceConfig); 343 344 if ((secondaryTableAnn != null) || (secondaryTableConfig != null)) { 345 String secondaryName; 346 347 if (secondaryTableAnn != null) 348 secondaryName = secondaryTableAnn.getString("name"); 349 else 350 secondaryName = secondaryTableConfig.getName(); 351 352 secondaryTable = _persistenceUnit.createTable(secondaryName); 353 354 entityType.addSecondaryTable(secondaryTable); 355 356 } 358 359 getInternalIdClassConfig(type); 360 JAnnotation idClassAnn = _annotationCfg.getAnnotation(); 361 IdClassConfig idClassConfig = _annotationCfg.getIdClassConfig(); 362 363 JClass idClass = null; 364 if (! _annotationCfg.isNull()) { 365 366 if (idClassAnn != null) 367 idClass = idClassAnn.getClass("value"); 368 else { 369 String s = idClassConfig.getClassName(); 370 idClass = _persistenceUnit.getJClassLoader().forName(s); 371 } 372 373 _persistenceUnit.getEmbeddableIntrospector().introspect(idClass); 375 } 376 377 if (entityType.getId() != null) { 378 } 379 else if (isField) 380 introspectIdField(_persistenceUnit, entityType, parentType, 381 type, idClass, entityConfig); 382 else 383 introspectIdMethod(_persistenceUnit, entityType, parentType, 384 type, idClass, entityConfig); 385 386 HashMap <String , IdConfig> idMap = null; 387 388 AttributesConfig attributes = null; 389 390 if (entityConfig != null) { 391 attributes = entityConfig.getAttributes(); 392 393 if (attributes != null) 394 idMap = attributes.getIdMap(); 395 } 396 397 401 if (isEntity && (entityType.getId() == null) && ((idMap == null) || (idMap.size() == 0))) 402 throw new ConfigException(L.l("{0} does not have any primary keys. Entities must have at least one @Id or exactly one @EmbeddedId field.", 403 entityType.getName())); 404 405 introspectAttributeOverrides(type, entityType); 407 408 if (isField) 409 introspectFields(_persistenceUnit, entityType, parentType, type, entityConfig, false); 410 else 411 introspectMethods(_persistenceUnit, entityType, parentType, type, entityConfig); 412 413 if (isEntity) { 414 introspectCallbacks(type, entityType); 415 416 if (secondaryTableAnn != null) { 417 Object []join = (Object []) secondaryTableAnn.get("pkJoinColumns"); 418 419 JAnnotation []joinAnn = null; 420 421 if (join != null) { 422 joinAnn = new JAnnotation[join.length]; 423 System.arraycopy(join, 0, joinAnn, 0, join.length); 424 } 425 426 linkSecondaryTable(entityType.getTable(), 427 secondaryTable, 428 joinAnn); 429 } 430 } 431 } catch (ConfigException e) { 432 if (entityType != null) 433 entityType.setConfigException(e); 434 435 throw e; 436 } catch (SQLException e) { 437 if (entityType != null) 438 entityType.setConfigException(e); 439 440 throw e; 441 } catch (RuntimeException e) { 442 if (entityType != null) 443 entityType.setConfigException(e); 444 445 throw e; 446 } 447 448 return entityType; 449 } 450 451 private void introspectAttributeOverrides(JClass type, 452 EntityType entityType) 453 { 454 getInternalAttributeOverrideConfig(type); 455 JAnnotation attributeOverrideAnn = _annotationCfg.getAnnotation(); 456 AttributeOverrideConfig attributeOverrideConfig 457 = _annotationCfg.getAttributeOverrideConfig(); 458 459 boolean hasAttributeOverride = ! _annotationCfg.isNull(); 460 461 JAnnotation attributeOverridesAnn = type.getAnnotation(AttributeOverrides.class); 462 463 boolean hasAttributeOverrides = (attributeOverridesAnn != null); 464 465 if (hasAttributeOverride && hasAttributeOverrides) 466 throw new ConfigException(L.l("{0} may not have both @AttributeOverride and @AttributeOverrides", 467 type)); 468 469 Object attOverridesAnn[] = null; 470 471 if (attributeOverrideAnn != null) { 472 attOverridesAnn = new Object [] { attributeOverrideAnn }; 473 } 474 else if (attributeOverridesAnn != null) { 475 attOverridesAnn = (Object []) attributeOverridesAnn.get("value"); 476 } 477 else 478 return; 479 480 Table sourceTable = entityType.getTable(); 481 482 for (int j=0; j < attOverridesAnn.length; j++) { 483 484 JAnnotation attOverrideAnn = (JAnnotation) attOverridesAnn[j]; 485 486 String entityFieldName; 487 String columnName; 488 boolean notNull = false; 489 boolean unique = false; 490 491 Type amberType = null; 492 493 ArrayList <AmberField> fields = entityType.getFields(); 494 495 for (int i=0; i < fields.size(); i++) { 496 497 AmberField field = fields.get(i); 498 499 if (! (field instanceof PropertyField)) 502 continue; 503 504 entityFieldName = field.getName(); 505 506 columnName = toSqlName(entityFieldName); 507 508 if (entityFieldName.equals(attOverrideAnn.getString("name"))) { 509 510 JAnnotation columnAnn = attOverrideAnn.getAnnotation("column"); 511 512 if (columnAnn != null) { 513 columnName = columnAnn.getString("name"); 514 notNull = ! columnAnn.getBoolean("nullable"); 515 unique = columnAnn.getBoolean("unique"); 516 amberType = _persistenceUnit.createType(field.getJavaType().getName()); 517 518 Column column = sourceTable.createColumn(columnName, amberType); 519 520 column.setNotNull(notNull); 521 column.setUnique(unique); 522 523 ((PropertyField) field).setColumn(column); 524 } 525 } 526 } 527 528 if (entityType.getId() != null) { 529 ArrayList <IdField> keys = entityType.getId().getKeys(); 530 531 for (int i=0; i < keys.size(); i++) { 532 533 IdField field = keys.get(i); 534 535 entityFieldName = field.getName(); 536 537 columnName = toSqlName(entityFieldName); 538 539 if (entityFieldName.equals(attOverrideAnn.getString("name"))) { 540 541 JAnnotation columnAnn = attOverrideAnn.getAnnotation("column"); 542 543 if (columnAnn != null) { 544 columnName = columnAnn.getString("name"); 545 notNull = ! columnAnn.getBoolean("nullable"); 546 unique = columnAnn.getBoolean("unique"); 547 amberType = _persistenceUnit.createType(field.getJavaType().getName()); 548 549 Column column = sourceTable.createColumn(columnName, amberType); 550 551 column.setNotNull(notNull); 552 column.setUnique(unique); 553 554 ArrayList <Column> columns = field.getColumns(); 555 556 if (field instanceof KeyPropertyField) { 557 if (columns.size() > 0) { 558 sourceTable.removeColumn(columns.get(0)); 559 columns.remove(0); 560 } 561 562 columns.add(column); 563 564 ((KeyPropertyField) field).setColumn(column); 565 } 566 } 567 } 568 } 569 } 570 } 571 } 572 } 573 | Popular Tags |