1 package org.hibernate.type; 3 4 import java.io.Serializable ; 5 import java.lang.reflect.Method ; 6 import java.sql.PreparedStatement ; 7 import java.sql.ResultSet ; 8 import java.sql.SQLException ; 9 import java.util.HashMap ; 10 import java.util.Map ; 11 12 import org.dom4j.Element; 13 import org.dom4j.Node; 14 import org.hibernate.EntityMode; 15 import org.hibernate.FetchMode; 16 import org.hibernate.HibernateException; 17 import org.hibernate.MappingException; 18 import org.hibernate.engine.CascadeStyle; 19 import org.hibernate.engine.Mapping; 20 import org.hibernate.engine.SessionFactoryImplementor; 21 import org.hibernate.engine.SessionImplementor; 22 import org.hibernate.tuple.ComponentTuplizer; 23 import org.hibernate.tuple.TuplizerLookup; 24 import org.hibernate.util.ArrayHelper; 25 import org.hibernate.util.StringHelper; 26 27 32 public class ComponentType extends AbstractType implements AbstractComponentType { 33 34 private final Type[] propertyTypes; 35 private final String [] propertyNames; 36 private final boolean[] propertyNullability; 37 protected final int propertySpan; 38 private final CascadeStyle[] cascade; 39 private final FetchMode[] joinedFetch; 40 private final boolean isKey; 41 42 protected TuplizerLookup tuplizers; 43 44 public int[] sqlTypes(Mapping mapping) throws MappingException { 45 int[] sqlTypes = new int[getColumnSpan( mapping )]; 47 int n = 0; 48 for ( int i = 0; i < propertySpan; i++ ) { 49 int[] subtypes = propertyTypes[i].sqlTypes( mapping ); 50 for ( int j = 0; j < subtypes.length; j++ ) { 51 sqlTypes[n++] = subtypes[j]; 52 } 53 } 54 return sqlTypes; 55 } 56 57 public int getColumnSpan(Mapping mapping) throws MappingException { 58 int span = 0; 59 for ( int i = 0; i < propertySpan; i++ ) { 60 span += propertyTypes[i].getColumnSpan( mapping ); 61 } 62 return span; 63 } 64 65 public ComponentType( 66 final String [] propertyNames, 67 final Type[] propertyTypes, 68 final boolean[] nullabilities, 69 final FetchMode[] joinedFetch, 70 final CascadeStyle[] cascade, 71 final boolean key, 72 final TuplizerLookup tuplizers) 73 throws MappingException { 74 75 this.propertyTypes = propertyTypes; 76 this.propertyNullability = nullabilities; 77 this.propertyNames = propertyNames; 78 this.cascade = cascade; 79 this.joinedFetch = joinedFetch; 80 isKey = key; 81 propertySpan = propertyTypes.length; 82 this.tuplizers = tuplizers; 83 } 84 85 public final boolean isComponentType() { 86 return true; 87 } 88 89 public Class getReturnedClass() { 90 return tuplizers.getTuplizer(EntityMode.POJO).getMappedClass(); } 92 93 public boolean isSame(Object x, Object y, EntityMode entityMode) throws HibernateException { 94 if ( x == y ) return true; 95 if ( x == null || y == null ) return false; 96 Object [] xvalues = getPropertyValues(x, entityMode); 97 Object [] yvalues = getPropertyValues(y, entityMode); 98 for ( int i = 0; i < propertySpan; i++ ) { 99 if ( !propertyTypes[i].isSame( xvalues[i], yvalues[i], entityMode ) ) { 100 return false; 101 } 102 } 103 return true; 104 } 105 106 public boolean isEqual(Object x, Object y, EntityMode entityMode) 107 throws HibernateException { 108 if ( x == y ) return true; 109 if ( x == null || y == null ) return false; 110 Object [] xvalues = getPropertyValues(x, entityMode); 111 Object [] yvalues = getPropertyValues(y, entityMode); 112 for ( int i = 0; i < propertySpan; i++ ) { 113 if ( !propertyTypes[i].isEqual( xvalues[i], yvalues[i], entityMode ) ) return false; 114 } 115 return true; 116 } 117 118 public boolean isEqual(Object x, Object y, EntityMode entityMode, SessionFactoryImplementor factory) 119 throws HibernateException { 120 if ( x == y ) return true; 121 if ( x == null || y == null ) return false; 122 Object [] xvalues = getPropertyValues(x, entityMode); 123 Object [] yvalues = getPropertyValues(y, entityMode); 124 for ( int i = 0; i < propertySpan; i++ ) { 125 if ( !propertyTypes[i].isEqual( xvalues[i], yvalues[i], entityMode, factory ) ) return false; 126 } 127 return true; 128 } 129 130 public int compare(Object x, Object y, EntityMode entityMode) { 131 if ( x == y ) return 0; 132 Object [] xvalues = getPropertyValues(x, entityMode); 133 Object [] yvalues = getPropertyValues(y, entityMode); 134 for ( int i = 0; i < propertySpan; i++ ) { 135 int propertyCompare = propertyTypes[i].compare( xvalues[i], yvalues[i], entityMode ); 136 if ( propertyCompare != 0 ) return propertyCompare; 137 } 138 return 0; 139 } 140 141 public boolean isMethodOf(Method method) { 142 return false; 143 } 144 145 public int getHashCode(Object x, EntityMode entityMode) { 146 int result = 17; 147 Object [] values = getPropertyValues(x, entityMode); 148 for ( int i = 0; i < propertySpan; i++ ) { 149 Object y = values[i]; 150 result *= 37; 151 if ( y != null ) result += propertyTypes[i].getHashCode( y, entityMode ); 152 } 153 return result; 154 } 155 156 public int getHashCode(Object x, EntityMode entityMode, SessionFactoryImplementor factory) { 157 int result = 17; 158 Object [] values = getPropertyValues(x, entityMode); 159 for ( int i = 0; i < propertySpan; i++ ) { 160 Object y = values[i]; 161 result *= 37; 162 if ( y != null ) result += propertyTypes[i].getHashCode( y, entityMode, factory ); 163 } 164 return result; 165 } 166 167 public boolean isDirty(Object x, Object y, SessionImplementor session) 168 throws HibernateException { 169 if ( x == y ) return false; 170 if ( x == null || y == null ) return true; 171 EntityMode entityMode = session.getEntityMode(); 172 Object [] xvalues = getPropertyValues(x, entityMode); 173 Object [] yvalues = getPropertyValues(y, entityMode); 174 for ( int i = 0; i < xvalues.length; i++ ) { 175 if ( propertyTypes[i].isDirty( xvalues[i], yvalues[i], session ) ) return true; 176 } 177 return false; 178 } 179 180 public Object nullSafeGet(ResultSet rs, String [] names, SessionImplementor session, Object owner) 181 throws HibernateException, SQLException { 182 return resolve( hydrate( rs, names, session, owner ), session, owner ); 183 } 184 185 public void nullSafeSet(PreparedStatement st, Object value, int begin, SessionImplementor session) 186 throws HibernateException, SQLException { 187 188 Object [] subvalues = nullSafeGetValues( value, session.getEntityMode() ); 189 190 for ( int i = 0; i < propertySpan; i++ ) { 191 propertyTypes[i].nullSafeSet( st, subvalues[i], begin, session ); 192 begin += propertyTypes[i].getColumnSpan( session.getFactory() ); 193 } 194 } 195 196 public void nullSafeSet( 197 PreparedStatement st, 198 Object value, 199 int begin, 200 boolean[] settable, 201 SessionImplementor session) 202 throws HibernateException, SQLException { 203 204 Object [] subvalues = nullSafeGetValues( value, session.getEntityMode() ); 205 206 int loc = 0; 207 for ( int i = 0; i < propertySpan; i++ ) { 208 int len = propertyTypes[i].getColumnSpan( session.getFactory() ); 209 if (len==1) { 210 if ( settable[loc] ) { 211 propertyTypes[i].nullSafeSet( st, subvalues[i], begin, session ); 212 begin++; 213 } 214 } 215 else { 216 boolean[] subsettable = new boolean[len]; 217 System.arraycopy(settable, loc, subsettable, 0, len); 218 propertyTypes[i].nullSafeSet( st, subvalues[i], begin, subsettable, session ); 219 begin += ArrayHelper.countTrue(subsettable); 220 } 221 loc += len; 222 } 223 } 224 225 private Object [] nullSafeGetValues(Object value, EntityMode entityMode) throws HibernateException { 226 if ( value == null ) { 227 return new Object [propertySpan]; 228 } 229 else { 230 return getPropertyValues( value, entityMode ); 231 } 232 } 233 234 public Object nullSafeGet(ResultSet rs, String name, SessionImplementor session, Object owner) 235 throws HibernateException, SQLException { 236 237 return nullSafeGet( rs, new String []{name}, session, owner ); 238 } 239 240 public Object getPropertyValue(Object component, int i, SessionImplementor session) 241 throws HibernateException { 242 return getPropertyValue( component, i, session.getEntityMode() ); 243 } 244 245 public Object getPropertyValue(Object component, int i, EntityMode entityMode) 246 throws HibernateException { 247 return tuplizers.getTuplizer(entityMode).getPropertyValue( component, i ); 248 } 249 250 public Object [] getPropertyValues(Object component, SessionImplementor session) 251 throws HibernateException { 252 return getPropertyValues( component, session.getEntityMode() ); 253 } 254 255 public Object [] getPropertyValues(Object component, EntityMode entityMode) 256 throws HibernateException { 257 return tuplizers.getTuplizer(entityMode).getPropertyValues(component); 258 } 259 260 public void setPropertyValues(Object component, Object [] values, EntityMode entityMode) 261 throws HibernateException { 262 tuplizers.getTuplizer(entityMode).setPropertyValues(component, values); 263 } 264 265 public Type[] getSubtypes() { 266 return propertyTypes; 267 } 268 269 public String getName() { 270 return "component" + ArrayHelper.toString(propertyNames); 271 } 272 273 public String toLoggableString(Object value, SessionFactoryImplementor factory) 274 throws HibernateException { 275 if ( value == null ) return "null"; 276 Map result = new HashMap (); 277 EntityMode entityMode = tuplizers.guessEntityMode(value); 278 if (entityMode==null) { 279 throw new ClassCastException ( value.getClass().getName() ); 280 } 281 Object [] values = getPropertyValues( value, entityMode ); 282 for ( int i = 0; i < propertyTypes.length; i++ ) { 283 result.put( propertyNames[i], propertyTypes[i].toLoggableString( values[i], factory ) ); 284 } 285 return StringHelper.unqualify( getName() ) + result.toString(); 286 } 287 288 public String [] getPropertyNames() { 289 return propertyNames; 290 } 291 292 public Object deepCopy(Object component, EntityMode entityMode, SessionFactoryImplementor factory) 293 throws HibernateException { 294 if ( component == null ) return null; 295 296 Object [] values = getPropertyValues( component, entityMode ); 297 for ( int i = 0; i < propertySpan; i++ ) { 298 values[i] = propertyTypes[i].deepCopy( values[i], entityMode, factory ); 299 } 300 301 Object result = instantiate(entityMode); 302 setPropertyValues( result, values, entityMode ); 303 304 ComponentTuplizer ct = (ComponentTuplizer) tuplizers.getTuplizer(entityMode); 307 if ( ct.hasParentProperty() ) { 308 ct.setParent( result, ct.getParent(component), factory ); 309 } 310 311 return result; 312 } 313 314 public Object replace( 315 Object original, 316 Object target, 317 SessionImplementor session, 318 Object owner, 319 Map copyCache) 320 throws HibernateException { 321 322 if ( original == null ) return null; 323 325 final Object result = target == null ? 326 instantiate( owner, session ) : 327 target; 328 329 final EntityMode entityMode = session.getEntityMode(); 330 Object [] values = TypeFactory.replace( 331 getPropertyValues( original, entityMode ), 332 getPropertyValues( result, entityMode ), 333 propertyTypes, 334 session, 335 owner, 336 copyCache 337 ); 338 339 setPropertyValues( result, values, entityMode ); 340 return result; 341 } 342 343 public Object replace( 344 Object original, 345 Object target, 346 SessionImplementor session, 347 Object owner, 348 Map copyCache, 349 ForeignKeyDirection foreignKeyDirection) 350 throws HibernateException { 351 352 if ( original == null ) return null; 353 355 final Object result = target == null ? 356 instantiate( owner, session ) : 357 target; 358 359 final EntityMode entityMode = session.getEntityMode(); 360 Object [] values = TypeFactory.replace( 361 getPropertyValues( original, entityMode ), 362 getPropertyValues( result, entityMode ), 363 propertyTypes, 364 session, 365 owner, 366 copyCache, 367 foreignKeyDirection 368 ); 369 370 setPropertyValues( result, values, entityMode ); 371 return result; 372 } 373 374 377 public Object instantiate(EntityMode entityMode) throws HibernateException { 378 return tuplizers.getTuplizer(entityMode).instantiate(); 379 } 380 381 public Object instantiate(Object parent, SessionImplementor session) 382 throws HibernateException { 383 384 Object result = instantiate( session.getEntityMode() ); 385 386 ComponentTuplizer ct = (ComponentTuplizer) tuplizers.getTuplizer( session.getEntityMode() ); 387 if ( ct.hasParentProperty() && parent != null ) { 388 ct.setParent( 389 result, 390 session.getPersistenceContext().proxyFor( parent ), 391 session.getFactory() 392 ); 393 } 394 395 return result; 396 } 397 398 public CascadeStyle getCascadeStyle(int i) { 399 return cascade[i]; 400 } 401 402 public boolean isMutable() { 403 return true; 404 } 405 406 public Serializable disassemble(Object value, SessionImplementor session, Object owner) 407 throws HibernateException { 408 409 if ( value == null ) { 410 return null; 411 } 412 else { 413 Object [] values = getPropertyValues( value, session.getEntityMode() ); 414 for ( int i = 0; i < propertyTypes.length; i++ ) { 415 values[i] = propertyTypes[i].disassemble( values[i], session, owner ); 416 } 417 return values; 418 } 419 } 420 421 public Object assemble(Serializable object, SessionImplementor session, Object owner) 422 throws HibernateException { 423 424 if ( object == null ) { 425 return null; 426 } 427 else { 428 Object [] values = (Object []) object; 429 Object [] assembled = new Object [values.length]; 430 for ( int i = 0; i < propertyTypes.length; i++ ) { 431 assembled[i] = propertyTypes[i].assemble( ( Serializable ) values[i], session, owner ); 432 } 433 Object result = instantiate( owner, session ); 434 setPropertyValues( result, assembled, session.getEntityMode() ); 435 return result; 436 } 437 } 438 439 public FetchMode getFetchMode(int i) { 440 return joinedFetch[i]; 441 } 442 443 public Object hydrate( 444 final ResultSet rs, 445 final String [] names, 446 final SessionImplementor session, 447 final Object owner) 448 throws HibernateException, SQLException { 449 450 int begin = 0; 451 boolean notNull = false; 452 Object [] values = new Object [propertySpan]; 453 for ( int i = 0; i < propertySpan; i++ ) { 454 int length = propertyTypes[i].getColumnSpan( session.getFactory() ); 455 String [] range = ArrayHelper.slice( names, begin, length ); Object val = propertyTypes[i].hydrate( rs, range, session, owner ); 457 if ( val == null ) { 458 if (isKey) return null; } 460 else { 461 notNull = true; 462 } 463 values[i] = val; 464 begin += length; 465 } 466 467 return notNull ? values : null; 468 } 469 470 public Object resolve(Object value, SessionImplementor session, Object owner) 471 throws HibernateException { 472 473 if ( value != null ) { 474 Object result = instantiate( owner, session ); 475 Object [] values = ( Object [] ) value; 476 Object [] resolvedValues = new Object [values.length]; for ( int i = 0; i < values.length; i++ ) { 478 resolvedValues[i] = propertyTypes[i].resolve( values[i], session, owner ); 479 } 480 setPropertyValues( result, resolvedValues, session.getEntityMode() ); 481 return result; 482 } 483 else { 484 return null; 485 } 486 } 487 488 public Object semiResolve(Object value, SessionImplementor session, Object owner) 489 throws HibernateException { 490 return resolve( value, session, owner ); 493 } 494 495 public boolean isModified(Object old, Object current, SessionImplementor session) 496 throws HibernateException { 497 498 if ( current == null ) return old != null; 499 if ( old == null ) return current != null; 500 Object [] currentValues = getPropertyValues( current, session ); 501 Object [] oldValues = ( Object [] ) old; 502 for ( int i = 0; i < currentValues.length; i++ ) { 503 if ( propertyTypes[i].isModified( oldValues[i], currentValues[i], session ) ) { 504 return true; 505 } 506 } 507 return false; 508 509 } 510 511 public boolean[] getPropertyNullability() { 512 return propertyNullability; 513 } 514 515 public boolean isXMLElement() { 516 return true; 517 } 518 519 public Object fromXMLNode(Node xml, Mapping factory) throws HibernateException { 520 return xml; 521 } 522 523 public void setToXMLNode(Node node, Object value, SessionFactoryImplementor factory) throws HibernateException { 524 replaceNode( node, (Element) value ); 525 } 526 527 public boolean[] toColumnNullness(Object value, Mapping mapping) { 528 boolean[] result = new boolean[ getColumnSpan(mapping) ]; 529 if (value==null) return result; 530 Object [] values = getPropertyValues(value, EntityMode.POJO); int loc = 0; 532 for ( int i=0; i<propertyTypes.length; i++ ) { 533 boolean[] propertyNullness = propertyTypes[i].toColumnNullness( values[i], mapping ); 534 System.arraycopy(propertyNullness, 0, result, loc, propertyNullness.length); 535 loc += propertyNullness.length; 536 } 537 return result; 538 } 539 540 } 541 | Popular Tags |