1 package org.hibernate.tuple; 3 4 import java.io.Serializable ; 5 import java.util.ArrayList ; 6 import java.util.HashMap ; 7 import java.util.HashSet ; 8 import java.util.Iterator ; 9 import java.util.List ; 10 import java.util.Map ; 11 import java.util.Set ; 12 13 import net.sf.cglib.transform.impl.InterceptFieldEnabled; 14 15 import org.apache.commons.logging.Log; 16 import org.apache.commons.logging.LogFactory; 17 import org.hibernate.EntityMode; 18 import org.hibernate.HibernateException; 19 import org.hibernate.MappingException; 20 import org.hibernate.engine.CascadeStyle; 21 import org.hibernate.engine.SessionFactoryImplementor; 22 import org.hibernate.engine.Versioning; 23 import org.hibernate.mapping.Component; 24 import org.hibernate.mapping.PersistentClass; 25 import org.hibernate.mapping.Property; 26 import org.hibernate.type.AbstractComponentType; 27 import org.hibernate.type.AssociationType; 28 import org.hibernate.type.EntityType; 29 import org.hibernate.type.Type; 30 import org.hibernate.type.TypeFactory; 31 import org.hibernate.util.ArrayHelper; 32 import org.hibernate.util.ReflectHelper; 33 34 39 public class EntityMetamodel implements Serializable { 40 41 private static final Log log = LogFactory.getLog(EntityMetamodel.class); 42 43 private static final int NO_VERSION_INDX = -66; 44 45 private final SessionFactoryImplementor sessionFactory; 46 47 private final String name; 48 private final String rootName; 49 private final EntityType entityType; 50 51 private final IdentifierProperty identifierProperty; 52 private final boolean versioned; 53 54 private final int propertySpan; 55 private final int versionPropertyIndex; 56 private final StandardProperty[] properties; 57 private final String [] propertyNames; 59 private final Type[] propertyTypes; 60 private final boolean[] propertyLaziness; 61 private final boolean[] propertyUpdateability; 62 private final boolean[] nonlazyPropertyUpdateability; 63 private final boolean[] propertyCheckability; 64 private final boolean[] propertyInsertability; 65 private final boolean[] propertyNullability; 66 private final boolean[] propertyVersionability; 67 private final CascadeStyle[] cascadeStyles; 68 private final Map propertyIndexes = new HashMap (); 70 private final boolean hasCollections; 71 private final boolean hasMutableProperties; 72 private final boolean hasLazyProperties; 73 74 private final int[] naturalIdPropertyNumbers; 75 76 private final boolean lazy; 77 private final boolean hasCascades; 78 private final boolean mutable; 79 private final boolean isAbstract; 80 private final boolean selectBeforeUpdate; 81 private final boolean dynamicUpdate; 82 private final boolean dynamicInsert; 83 private final int optimisticLockMode; 84 85 private final boolean polymorphic; 86 private final String superclass; private final boolean explicitPolymorphism; 88 private final boolean inherited; 89 private final boolean hasSubclasses; 90 private final Set subclassEntityNames = new HashSet (); 91 92 private final TuplizerLookup tuplizers; 93 94 public EntityTuplizer getTuplizer(EntityMode entityMode) { 95 return (EntityTuplizer) tuplizers.getTuplizer(entityMode); 96 } 97 98 public EntityTuplizer getTuplizerOrNull(EntityMode entityMode) { 99 return (EntityTuplizer) tuplizers.getTuplizerOrNull(entityMode); 100 } 101 102 public EntityMode guessEntityMode(Object object) { 103 return tuplizers.guessEntityMode(object); 104 } 105 106 public EntityMetamodel(PersistentClass persistentClass, SessionFactoryImplementor sessionFactory) { 107 this.sessionFactory = sessionFactory; 108 109 name = persistentClass.getEntityName(); 110 rootName = persistentClass.getRootClass().getEntityName(); 111 entityType = TypeFactory.manyToOne( name ); 112 113 identifierProperty = PropertyFactory.buildIdentifierProperty( 114 persistentClass, 115 sessionFactory.getIdentifierGenerator( rootName ) 116 ); 117 118 versioned = persistentClass.isVersioned(); 119 120 boolean lazyAvailable = persistentClass.hasPojoRepresentation() && 121 InterceptFieldEnabled.class.isAssignableFrom( persistentClass.getMappedClass() ); 122 boolean hasLazy = false; 123 124 propertySpan = persistentClass.getPropertyClosureSpan(); 125 properties = new StandardProperty[propertySpan]; 126 List naturalIdNumbers = new ArrayList (); 127 propertyNames = new String [propertySpan]; 129 propertyTypes = new Type[propertySpan]; 130 propertyUpdateability = new boolean[propertySpan]; 131 propertyInsertability = new boolean[propertySpan]; 132 nonlazyPropertyUpdateability = new boolean[propertySpan]; 133 propertyCheckability = new boolean[propertySpan]; 134 propertyNullability = new boolean[propertySpan]; 135 propertyVersionability = new boolean[propertySpan]; 136 propertyLaziness = new boolean[propertySpan]; 137 cascadeStyles = new CascadeStyle[propertySpan]; 138 140 141 Iterator iter = persistentClass.getPropertyClosureIterator(); 142 int i = 0; 143 int tempVersionProperty = NO_VERSION_INDX; 144 boolean foundCascade = false; 145 boolean foundCollection = false; 146 boolean foundMutable = false; 147 148 while ( iter.hasNext() ) { 149 Property prop = ( Property ) iter.next(); 150 151 if ( prop == persistentClass.getVersion() ) { 152 tempVersionProperty = i; 153 properties[i] = PropertyFactory.buildVersionProperty( prop, lazyAvailable ); 154 } 155 else { 156 properties[i] = PropertyFactory.buildStandardProperty( prop, lazyAvailable ); 157 } 158 159 if ( prop.isNaturalIdentifier() ) { 160 naturalIdNumbers.add( new Integer (i) ); 161 } 162 163 boolean lazy = prop.isLazy() && lazyAvailable; 165 if ( lazy ) hasLazy = true; 166 propertyLaziness[i] = lazy; 167 168 propertyNames[i] = properties[i].getName(); 169 propertyTypes[i] = properties[i].getType(); 170 propertyNullability[i] = properties[i].isNullable(); 171 propertyUpdateability[i] = properties[i].isUpdateable(); 172 propertyInsertability[i] = properties[i].isInsertable(); 173 propertyVersionability[i] = properties[i].isVersionable(); 174 nonlazyPropertyUpdateability[i] = properties[i].isUpdateable() && !lazy; 175 propertyCheckability[i] = propertyUpdateability[i] || 176 ( propertyTypes[i].isAssociationType() && ( (AssociationType) propertyTypes[i] ).isAlwaysDirtyChecked() ); 177 178 cascadeStyles[i] = properties[i].getCascadeStyle(); 179 181 if ( properties[i].isLazy() ) { 182 hasLazy = true; 183 } 184 185 if ( properties[i].getCascadeStyle() != CascadeStyle.NONE ) { 186 foundCascade = true; 187 } 188 189 if ( indicatesCollection( properties[i].getType() ) ) { 190 foundCollection = true; 191 } 192 193 if ( propertyTypes[i].isMutable() && propertyCheckability[i] ) { 194 foundMutable = true; 195 } 196 197 mapPropertyToIndex(prop, i); 198 i++; 199 } 200 201 if (naturalIdNumbers.size()==0) { 202 naturalIdPropertyNumbers = null; 203 } 204 else { 205 naturalIdPropertyNumbers = ArrayHelper.toIntArray(naturalIdNumbers); 206 } 207 208 hasCascades = foundCascade; 209 versionPropertyIndex = tempVersionProperty; 210 hasLazyProperties = hasLazy; 211 if (hasLazyProperties) log.info("lazy property fetching available for: " + name); 212 213 lazy = persistentClass.isLazy() && ( 214 !persistentClass.hasPojoRepresentation() || 216 !ReflectHelper.isFinalClass( persistentClass.getProxyInterface() ) 217 ); 218 mutable = persistentClass.isMutable(); 219 isAbstract = persistentClass.isAbstract() || ( 220 persistentClass.hasPojoRepresentation() && 221 ReflectHelper.isAbstractClass( persistentClass.getMappedClass() ) 222 ); 223 selectBeforeUpdate = persistentClass.hasSelectBeforeUpdate(); 224 dynamicUpdate = persistentClass.useDynamicUpdate(); 225 dynamicInsert = persistentClass.useDynamicInsert(); 226 227 polymorphic = persistentClass.isPolymorphic(); 228 explicitPolymorphism = persistentClass.isExplicitPolymorphism(); 229 inherited = persistentClass.isInherited(); 230 superclass = inherited ? 231 persistentClass.getSuperclass().getEntityName() : 232 null; 233 hasSubclasses = persistentClass.hasSubclasses(); 234 235 optimisticLockMode = persistentClass.getOptimisticLockMode(); 236 if ( optimisticLockMode > Versioning.OPTIMISTIC_LOCK_VERSION && !dynamicUpdate ) { 237 throw new MappingException( "optimistic-lock setting requires dynamic-update=\"true\": " + name ); 238 } 239 240 hasCollections = foundCollection; 241 hasMutableProperties = foundMutable; 242 243 tuplizers = TuplizerLookup.create(persistentClass, this); 244 245 iter = persistentClass.getSubclassIterator(); 246 while ( iter.hasNext() ) { 247 subclassEntityNames.add( ( (PersistentClass) iter.next() ).getEntityName() ); 248 } 249 subclassEntityNames.add( name ); 250 251 } 252 253 private void mapPropertyToIndex(Property prop, int i) { 254 propertyIndexes.put( prop.getName(), new Integer (i) ); 255 if ( prop.getValue() instanceof Component ) { 256 Iterator iter = ( (Component) prop.getValue() ).getPropertyIterator(); 257 while ( iter.hasNext() ) { 258 Property subprop = (Property) iter.next(); 259 propertyIndexes.put( 260 prop.getName() + '.' + subprop.getName(), 261 new Integer (i) 262 ); 263 } 264 } 265 } 266 267 public int[] getNaturalIdentifierProperties() { 268 return naturalIdPropertyNumbers; 269 } 270 271 public boolean hasNaturalIdentifier() { 272 return naturalIdPropertyNumbers!=null; 273 } 274 275 public Set getSubclassEntityNames() { 276 return subclassEntityNames; 277 } 278 279 private boolean indicatesCollection(Type type) { 280 if ( type.isCollectionType() ) { 281 return true; 282 } 283 else if ( type.isComponentType() ) { 284 Type[] subtypes = ( ( AbstractComponentType ) type ).getSubtypes(); 285 for ( int i = 0; i < subtypes.length; i++ ) { 286 if ( indicatesCollection( subtypes[i] ) ) { 287 return true; 288 } 289 } 290 } 291 return false; 292 } 293 294 public SessionFactoryImplementor getSessionFactory() { 295 return sessionFactory; 296 } 297 298 public String getName() { 299 return name; 300 } 301 302 public String getRootName() { 303 return rootName; 304 } 305 306 public EntityType getEntityType() { 307 return entityType; 308 } 309 310 public IdentifierProperty getIdentifierProperty() { 311 return identifierProperty; 312 } 313 314 public int getPropertySpan() { 315 return propertySpan; 316 } 317 318 public int getVersionPropertyIndex() { 319 return versionPropertyIndex; 320 } 321 322 public VersionProperty getVersionProperty() { 323 if ( NO_VERSION_INDX == versionPropertyIndex ) { 324 return null; 325 } 326 else { 327 return ( VersionProperty ) properties[ versionPropertyIndex ]; 328 } 329 } 330 331 public StandardProperty[] getProperties() { 332 return properties; 333 } 334 335 public int getPropertyIndex(String propertyName) { 336 Integer index = getPropertyIndexOrNull(propertyName); 337 if ( index == null ) { 338 throw new HibernateException("Unable to resolve property: " + propertyName); 339 } 340 return index.intValue(); 341 } 342 343 public Integer getPropertyIndexOrNull(String propertyName) { 344 return (Integer ) propertyIndexes.get( propertyName ); 345 } 346 347 public boolean hasCollections() { 348 return hasCollections; 349 } 350 351 public boolean hasMutableProperties() { 352 return hasMutableProperties; 353 } 354 355 public boolean hasLazyProperties() { 356 return hasLazyProperties; 357 } 358 359 public boolean hasCascades() { 360 return hasCascades; 361 } 362 363 public boolean isMutable() { 364 return mutable; 365 } 366 367 public boolean isSelectBeforeUpdate() { 368 return selectBeforeUpdate; 369 } 370 371 public boolean isDynamicUpdate() { 372 return dynamicUpdate; 373 } 374 375 public boolean isDynamicInsert() { 376 return dynamicInsert; 377 } 378 379 public int getOptimisticLockMode() { 380 return optimisticLockMode; 381 } 382 383 public boolean isPolymorphic() { 384 return polymorphic; 385 } 386 387 public String getSuperclass() { 388 return superclass; 389 } 390 391 public boolean isExplicitPolymorphism() { 392 return explicitPolymorphism; 393 } 394 395 public boolean isInherited() { 396 return inherited; 397 } 398 399 public boolean hasSubclasses() { 400 return hasSubclasses; 401 } 402 403 public boolean isLazy() { 404 return lazy; 405 } 406 407 public boolean isVersioned() { 408 return versioned; 409 } 410 411 public boolean isAbstract() { 412 return isAbstract; 413 } 414 415 public String toString() { 416 return "EntityMetamodel(" + name + ':' + ArrayHelper.toString(properties) + ')'; 417 } 418 419 public String [] getPropertyNames() { 421 return propertyNames; 422 } 423 424 public Type[] getPropertyTypes() { 425 return propertyTypes; 426 } 427 428 public boolean[] getPropertyLaziness() { 429 return propertyLaziness; 430 } 431 432 public boolean[] getPropertyUpdateability() { 433 return propertyUpdateability; 434 } 435 436 public boolean[] getPropertyCheckability() { 437 return propertyCheckability; 438 } 439 440 public boolean[] getNonlazyPropertyUpdateability() { 441 return nonlazyPropertyUpdateability; 442 } 443 444 public boolean[] getPropertyInsertability() { 445 return propertyInsertability; 446 } 447 448 public boolean[] getPropertyNullability() { 449 return propertyNullability; 450 } 451 452 public boolean[] getPropertyVersionability() { 453 return propertyVersionability; 454 } 455 456 public CascadeStyle[] getCascadeStyles() { 457 return cascadeStyles; 458 } 459 } 461 | Popular Tags |