HHH-8159 - Apply fixups indicated by analysis tools

This commit is contained in:
Steve Ebersole 2013-04-22 17:14:29 -05:00
parent 11464ea097
commit 63093dbfd9
27 changed files with 2269 additions and 1439 deletions

View File

@ -48,7 +48,6 @@ import org.hibernate.persister.entity.EntityPersister;
* @see EntityIdentityInsertAction * @see EntityIdentityInsertAction
*/ */
public final class EntityInsertAction extends AbstractEntityInsertAction { public final class EntityInsertAction extends AbstractEntityInsertAction {
private Object version; private Object version;
private Object cacheEntry; private Object cacheEntry;
@ -130,7 +129,7 @@ public final class EntityInsertAction extends AbstractEntityInsertAction {
version, version,
session session
); );
cacheEntry = persister.getCacheEntryStructure().structure(ce); cacheEntry = persister.getCacheEntryStructure().structure( ce );
final CacheKey ck = session.generateCacheKey( id, persister.getIdentifierType(), persister.getRootEntityName() ); final CacheKey ck = session.generateCacheKey( id, persister.getIdentifierType(), persister.getRootEntityName() );
final boolean put = persister.getCacheAccessStrategy().insert( ck, cacheEntry, version ); final boolean put = persister.getCacheAccessStrategy().insert( ck, cacheEntry, version );

View File

@ -63,7 +63,7 @@ public class TransformingClassLoader extends ClassLoader {
try { try {
final CtClass cc = classPool.get( name ); final CtClass cc = classPool.get( name );
// todo : modify the class definition if not already transformed... // todo : modify the class definition if not already transformed...
byte[] b = cc.toBytecode(); final byte[] b = cc.toBytecode();
return defineClass( name, b, 0, b.length ); return defineClass( name, b, 0, b.length );
} }
catch (NotFoundException e) { catch (NotFoundException e) {

View File

@ -30,10 +30,11 @@ import org.hibernate.mapping.Collection;
import org.hibernate.mapping.PersistentClass; import org.hibernate.mapping.PersistentClass;
import org.hibernate.metamodel.binding.EntityBinding; import org.hibernate.metamodel.binding.EntityBinding;
import org.hibernate.metamodel.binding.PluralAttributeBinding; import org.hibernate.metamodel.binding.PluralAttributeBinding;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.VersionType; import org.hibernate.type.VersionType;
/** /**
* Standard CacheDataDescription implementation.
*
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class CacheDataDescriptionImpl implements CacheDataDescription { public class CacheDataDescriptionImpl implements CacheDataDescription {
@ -41,48 +42,87 @@ public class CacheDataDescriptionImpl implements CacheDataDescription {
private final boolean versioned; private final boolean versioned;
private final Comparator versionComparator; private final Comparator versionComparator;
/**
* Constructs a CacheDataDescriptionImpl instance. Generally speaking, code should use one of the
* overloaded {@link #decode} methods rather than direct instantiation.
*
* @param mutable Is the described data mutable?
* @param versioned Is the described data versioned?
* @param versionComparator The described data's version value comparator (if versioned).
*/
public CacheDataDescriptionImpl(boolean mutable, boolean versioned, Comparator versionComparator) { public CacheDataDescriptionImpl(boolean mutable, boolean versioned, Comparator versionComparator) {
this.mutable = mutable; this.mutable = mutable;
this.versioned = versioned; this.versioned = versioned;
this.versionComparator = versionComparator; this.versionComparator = versionComparator;
} }
@Override
public boolean isMutable() { public boolean isMutable() {
return mutable; return mutable;
} }
@Override
public boolean isVersioned() { public boolean isVersioned() {
return versioned; return versioned;
} }
@Override
public Comparator getVersionComparator() { public Comparator getVersionComparator() {
return versionComparator; return versionComparator;
} }
/**
* Builds a CacheDataDescriptionImpl from the mapping model of an entity class.
*
* @param model The mapping model.
*
* @return The constructed CacheDataDescriptionImpl
*/
public static CacheDataDescriptionImpl decode(PersistentClass model) { public static CacheDataDescriptionImpl decode(PersistentClass model) {
return new CacheDataDescriptionImpl( return new CacheDataDescriptionImpl(
model.isMutable(), model.isMutable(),
model.isVersioned(), model.isVersioned(),
model.isVersioned() ? ( ( VersionType ) model.getVersion().getType() ).getComparator() : null model.isVersioned()
? ( (VersionType) model.getVersion().getType() ).getComparator()
: null
); );
} }
/**
* Builds a CacheDataDescriptionImpl from the mapping model of an entity class (using the new metamodel code).
*
* @param model The mapping model.
*
* @return The constructed CacheDataDescriptionImpl
*/
public static CacheDataDescriptionImpl decode(EntityBinding model) { public static CacheDataDescriptionImpl decode(EntityBinding model) {
return new CacheDataDescriptionImpl( return new CacheDataDescriptionImpl( model.isMutable(), model.isVersioned(), getVersionComparator( model ) );
model.isMutable(),
model.isVersioned(),
getVersionComparator( model )
);
} }
/**
* Builds a CacheDataDescriptionImpl from the mapping model of a collection
*
* @param model The mapping model.
*
* @return The constructed CacheDataDescriptionImpl
*/
public static CacheDataDescriptionImpl decode(Collection model) { public static CacheDataDescriptionImpl decode(Collection model) {
return new CacheDataDescriptionImpl( return new CacheDataDescriptionImpl(
model.isMutable(), model.isMutable(),
model.getOwner().isVersioned(), model.getOwner().isVersioned(),
model.getOwner().isVersioned() ? ( ( VersionType ) model.getOwner().getVersion().getType() ).getComparator() : null model.getOwner().isVersioned()
? ( (VersionType) model.getOwner().getVersion().getType() ).getComparator()
: null
); );
} }
/**
* Builds a CacheDataDescriptionImpl from the mapping model of a collection (using the new metamodel code).
*
* @param model The mapping model.
*
* @return The constructed CacheDataDescriptionImpl
*/
public static CacheDataDescriptionImpl decode(PluralAttributeBinding model) { public static CacheDataDescriptionImpl decode(PluralAttributeBinding model) {
return new CacheDataDescriptionImpl( return new CacheDataDescriptionImpl(
model.isMutable(), model.isMutable(),
@ -91,24 +131,16 @@ public class CacheDataDescriptionImpl implements CacheDataDescription {
); );
} }
public static CacheDataDescriptionImpl decode(EntityPersister persister) {
return new CacheDataDescriptionImpl(
!persister.getEntityMetamodel().hasImmutableNaturalId(),
false,
null
);
}
private static Comparator getVersionComparator(EntityBinding model ) { private static Comparator getVersionComparator(EntityBinding model ) {
Comparator versionComparator = null;
if ( model.isVersioned() ) { if ( model.isVersioned() ) {
versionComparator = ( final VersionType versionType = (VersionType) model.getHierarchyDetails()
( VersionType ) model.getHierarchyDetails() .getVersioningAttributeBinding()
.getVersioningAttributeBinding() .getHibernateTypeDescriptor()
.getHibernateTypeDescriptor() .getResolvedTypeMapping();
.getResolvedTypeMapping()
).getComparator(); return versionType.getComparator();
} }
return versionComparator;
return null;
} }
} }

View File

@ -43,48 +43,64 @@ import org.hibernate.cfg.Settings;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class NoCachingRegionFactory implements RegionFactory { public class NoCachingRegionFactory implements RegionFactory {
/**
* Singleton access
*/
public static final NoCachingRegionFactory INSTANCE = new NoCachingRegionFactory(); public static final NoCachingRegionFactory INSTANCE = new NoCachingRegionFactory();
/**
* Constructs a NoCachingRegionFactory. Although access should generally use {@link #INSTANCE}
*/
public NoCachingRegionFactory() { public NoCachingRegionFactory() {
} }
@Override
public void start(Settings settings, Properties properties) throws CacheException { public void start(Settings settings, Properties properties) throws CacheException {
} }
@Override
public void stop() { public void stop() {
} }
@Override
public boolean isMinimalPutsEnabledByDefault() { public boolean isMinimalPutsEnabledByDefault() {
return false; return false;
} }
@Override
public AccessType getDefaultAccessType() { public AccessType getDefaultAccessType() {
return null; return null;
} }
@Override
public long nextTimestamp() { public long nextTimestamp() {
return System.currentTimeMillis() / 100; return System.currentTimeMillis() / 100;
} }
@Override
public EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata) public EntityRegion buildEntityRegion(String regionName, Properties properties, CacheDataDescription metadata)
throws CacheException { throws CacheException {
throw new NoCacheRegionFactoryAvailableException(); throw new NoCacheRegionFactoryAvailableException();
} }
@Override
public NaturalIdRegion buildNaturalIdRegion(String regionName, Properties properties, CacheDataDescription metadata) public NaturalIdRegion buildNaturalIdRegion(String regionName, Properties properties, CacheDataDescription metadata)
throws CacheException { throws CacheException {
throw new NoCacheRegionFactoryAvailableException(); throw new NoCacheRegionFactoryAvailableException();
} }
@Override
public CollectionRegion buildCollectionRegion(String regionName, Properties properties, CacheDataDescription metadata) public CollectionRegion buildCollectionRegion(String regionName, Properties properties, CacheDataDescription metadata)
throws CacheException { throws CacheException {
throw new NoCacheRegionFactoryAvailableException(); throw new NoCacheRegionFactoryAvailableException();
} }
@Override
public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties) throws CacheException { public QueryResultsRegion buildQueryResultsRegion(String regionName, Properties properties) throws CacheException {
throw new NoCacheRegionFactoryAvailableException(); throw new NoCacheRegionFactoryAvailableException();
} }
@Override
public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties) throws CacheException { public TimestampsRegion buildTimestampsRegion(String regionName, Properties properties) throws CacheException {
throw new NoCacheRegionFactoryAvailableException(); throw new NoCacheRegionFactoryAvailableException();
} }

View File

@ -28,8 +28,6 @@ import java.util.Map;
import org.hibernate.boot.registry.StandardServiceInitiator; import org.hibernate.boot.registry.StandardServiceInitiator;
import org.hibernate.boot.registry.selector.spi.StrategySelector; import org.hibernate.boot.registry.selector.spi.StrategySelector;
import org.hibernate.cache.spi.RegionFactory; import org.hibernate.cache.spi.RegionFactory;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.service.spi.ServiceException;
import org.hibernate.service.spi.ServiceRegistryImplementor; import org.hibernate.service.spi.ServiceRegistryImplementor;
/** /**
@ -38,6 +36,9 @@ import org.hibernate.service.spi.ServiceRegistryImplementor;
* @author Hardy Ferentschik * @author Hardy Ferentschik
*/ */
public class RegionFactoryInitiator implements StandardServiceInitiator<RegionFactory> { public class RegionFactoryInitiator implements StandardServiceInitiator<RegionFactory> {
/**
* Singleton access
*/
public static final RegionFactoryInitiator INSTANCE = new RegionFactoryInitiator(); public static final RegionFactoryInitiator INSTANCE = new RegionFactoryInitiator();
/** /**
@ -59,35 +60,17 @@ public class RegionFactoryInitiator implements StandardServiceInitiator<RegionFa
setting, setting,
NoCachingRegionFactory.INSTANCE NoCachingRegionFactory.INSTANCE
); );
// if ( setting == null ) {
// return new NoCachingRegionFactory();
// }
//
// if ( getServiceInitiated().isInstance( setting ) ) {
// return (RegionFactory) setting;
// }
//
// Class<? extends RegionFactory> customImplClass = null;
// if ( Class.class.isInstance( setting ) ) {
// customImplClass = (Class<? extends RegionFactory>) setting;
// }
// else {
// customImplClass = registry.getService( ClassLoaderService.class )
// .classForName( mapLegacyNames( setting.toString() ) );
// }
//
// try {
// return customImplClass.newInstance();
// }
// catch ( Exception e ) {
// throw new ServiceException(
// "Could not initialize custom RegionFactory impl [" + customImplClass.getName() + "]", e
// );
// }
} }
// todo this shouldn't be public (nor really static): /**
// hack for org.hibernate.cfg.SettingsFactory.createRegionFactory() * Map legacy names unto the new corollary.
*
* todo this shouldn't be public, nor really static. hack for org.hibernate.cfg.SettingsFactory.createRegionFactory()
*
* @param name The (possibly legacy) factory name
*
* @return The factory name to use.
*/
public static String mapLegacyNames(final String name) { public static String mapLegacyNames(final String name) {
if ( "org.hibernate.cache.EhCacheRegionFactory".equals( name ) ) { if ( "org.hibernate.cache.EhCacheRegionFactory".equals( name ) ) {
return "org.hibernate.cache.ehcache.EhCacheRegionFactory"; return "org.hibernate.cache.ehcache.EhCacheRegionFactory";

View File

@ -48,14 +48,13 @@ import org.hibernate.type.TypeHelper;
/** /**
* The standard implementation of the Hibernate QueryCache interface. This * The standard implementation of the Hibernate QueryCache interface. This
* implementation is very good at recognizing stale query results and * implementation is very good at recognizing stale query results and
* and re-running queries when it detects this condition, recaching the new * and re-running queries when it detects this condition, re-caching the new
* results. * results.
* *
* @author Gavin King * @author Gavin King
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class StandardQueryCache implements QueryCache { public class StandardQueryCache implements QueryCache {
private static final CoreMessageLogger LOG = Logger.getMessageLogger( private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class, CoreMessageLogger.class,
StandardQueryCache.class.getName() StandardQueryCache.class.getName()
@ -67,28 +66,54 @@ public class StandardQueryCache implements QueryCache {
private QueryResultsRegion cacheRegion; private QueryResultsRegion cacheRegion;
private UpdateTimestampsCache updateTimestampsCache; private UpdateTimestampsCache updateTimestampsCache;
public void clear() throws CacheException { /**
cacheRegion.evictAll(); * Constructs a StandardQueryCache instance
} *
* @param settings The SessionFactory settings.
* @param props Any properties
* @param updateTimestampsCache The update-timestamps cache to use.
* @param regionName The base query cache region name
*/
public StandardQueryCache( public StandardQueryCache(
final Settings settings, final Settings settings,
final Properties props, final Properties props,
final UpdateTimestampsCache updateTimestampsCache, final UpdateTimestampsCache updateTimestampsCache,
String regionName) throws HibernateException { final String regionName) {
if ( regionName == null ) { String regionNameToUse = regionName;
regionName = StandardQueryCache.class.getName(); if ( regionNameToUse == null ) {
regionNameToUse = StandardQueryCache.class.getName();
} }
String prefix = settings.getCacheRegionPrefix(); final String prefix = settings.getCacheRegionPrefix();
if ( prefix != null ) { if ( prefix != null ) {
regionName = prefix + '.' + regionName; regionNameToUse = prefix + '.' + regionNameToUse;
} }
LOG.startingQueryCache( regionName ); LOG.startingQueryCache( regionNameToUse );
this.cacheRegion = settings.getRegionFactory().buildQueryResultsRegion( regionName, props ); this.cacheRegion = settings.getRegionFactory().buildQueryResultsRegion( regionNameToUse, props );
this.updateTimestampsCache = updateTimestampsCache; this.updateTimestampsCache = updateTimestampsCache;
} }
@Override
public QueryResultsRegion getRegion() {
return cacheRegion;
}
@Override
public void destroy() {
try {
cacheRegion.destroy();
}
catch ( Exception e ) {
LOG.unableToDestroyQueryCache( cacheRegion.getName(), e.getMessage() );
}
}
@Override
public void clear() throws CacheException {
cacheRegion.evictAll();
}
@Override
@SuppressWarnings({ "unchecked" }) @SuppressWarnings({ "unchecked" })
public boolean put( public boolean put(
final QueryKey key, final QueryKey key,
@ -99,20 +124,21 @@ public class StandardQueryCache implements QueryCache {
if ( isNaturalKeyLookup && result.isEmpty() ) { if ( isNaturalKeyLookup && result.isEmpty() ) {
return false; return false;
} }
long ts = cacheRegion.nextTimestamp(); final long ts = cacheRegion.nextTimestamp();
if ( DEBUGGING ) LOG.debugf( "Caching query results in region: %s; timestamp=%s", cacheRegion.getName(), ts ); if ( DEBUGGING ) {
LOG.debugf( "Caching query results in region: %s; timestamp=%s", cacheRegion.getName(), ts );
}
List cacheable = new ArrayList( result.size() + 1 ); final List cacheable = new ArrayList( result.size() + 1 );
logCachedResultDetails( key, null, returnTypes, cacheable ); logCachedResultDetails( key, null, returnTypes, cacheable );
cacheable.add( ts ); cacheable.add( ts );
final boolean singleResult = returnTypes.length == 1;
final boolean isSingleResult = returnTypes.length == 1;
for ( Object aResult : result ) { for ( Object aResult : result ) {
Serializable cacheItem = singleResult ? returnTypes[0].disassemble( final Serializable cacheItem = isSingleResult
aResult, ? returnTypes[0].disassemble( aResult, session, null )
session, : TypeHelper.disassemble( (Object[]) aResult, returnTypes, null, session, null );
null
) : TypeHelper.disassemble( (Object[]) aResult, returnTypes, null, session, null );
cacheable.add( cacheItem ); cacheable.add( cacheItem );
logCachedResultRowDetails( returnTypes, aResult ); logCachedResultRowDetails( returnTypes, aResult );
} }
@ -121,6 +147,7 @@ public class StandardQueryCache implements QueryCache {
return true; return true;
} }
@Override
@SuppressWarnings({ "unchecked" }) @SuppressWarnings({ "unchecked" })
public List get( public List get(
final QueryKey key, final QueryKey key,
@ -128,23 +155,31 @@ public class StandardQueryCache implements QueryCache {
final boolean isNaturalKeyLookup, final boolean isNaturalKeyLookup,
final Set spaces, final Set spaces,
final SessionImplementor session) throws HibernateException { final SessionImplementor session) throws HibernateException {
if ( DEBUGGING ) LOG.debugf( "Checking cached query results in region: %s", cacheRegion.getName() ); if ( DEBUGGING ) {
LOG.debugf( "Checking cached query results in region: %s", cacheRegion.getName() );
}
List cacheable = (List) cacheRegion.get( key ); final List cacheable = (List) cacheRegion.get( key );
logCachedResultDetails( key, spaces, returnTypes, cacheable ); logCachedResultDetails( key, spaces, returnTypes, cacheable );
if ( cacheable == null ) { if ( cacheable == null ) {
if ( DEBUGGING ) LOG.debug( "Query results were not found in cache" ); if ( DEBUGGING ) {
LOG.debug( "Query results were not found in cache" );
}
return null; return null;
} }
Long timestamp = (Long) cacheable.get( 0 ); final Long timestamp = (Long) cacheable.get( 0 );
if ( !isNaturalKeyLookup && !isUpToDate( spaces, timestamp ) ) { if ( !isNaturalKeyLookup && !isUpToDate( spaces, timestamp ) ) {
if ( DEBUGGING ) LOG.debug( "Cached query results were not up-to-date" ); if ( DEBUGGING ) {
LOG.debug( "Cached query results were not up-to-date" );
}
return null; return null;
} }
if ( DEBUGGING ) LOG.debug( "Returning cached query results" ); if ( DEBUGGING ) {
LOG.debug( "Returning cached query results" );
}
final boolean singleResult = returnTypes.length == 1; final boolean singleResult = returnTypes.length == 1;
for ( int i = 1; i < cacheable.size(); i++ ) { for ( int i = 1; i < cacheable.size(); i++ ) {
if ( singleResult ) { if ( singleResult ) {
@ -154,7 +189,8 @@ public class StandardQueryCache implements QueryCache {
TypeHelper.beforeAssemble( (Serializable[]) cacheable.get( i ), returnTypes, session ); TypeHelper.beforeAssemble( (Serializable[]) cacheable.get( i ), returnTypes, session );
} }
} }
List result = new ArrayList( cacheable.size() - 1 );
final List result = new ArrayList( cacheable.size() - 1 );
for ( int i = 1; i < cacheable.size(); i++ ) { for ( int i = 1; i < cacheable.size(); i++ ) {
try { try {
if ( singleResult ) { if ( singleResult ) {
@ -168,16 +204,18 @@ public class StandardQueryCache implements QueryCache {
logCachedResultRowDetails( returnTypes, result.get( i - 1 ) ); logCachedResultRowDetails( returnTypes, result.get( i - 1 ) );
} }
catch ( RuntimeException ex ) { catch ( RuntimeException ex ) {
if ( isNaturalKeyLookup && if ( isNaturalKeyLookup ) {
( UnresolvableObjectException.class.isInstance( ex ) || // potentially perform special handling for natural-id look ups.
EntityNotFoundException.class.isInstance( ex ) ) ) { if ( UnresolvableObjectException.class.isInstance( ex )
//TODO: not really completely correct, since || EntityNotFoundException.class.isInstance( ex ) ) {
// the uoe could occur while resolving if ( DEBUGGING ) {
// associations, leaving the PC in an LOG.debug( "Unable to reassemble cached natural-id query result" );
// inconsistent state }
if ( DEBUGGING ) LOG.debug( "Unable to reassemble cached result set" ); cacheRegion.evict( key );
cacheRegion.evict( key );
return null; // EARLY EXIT !!!!!
return null;
}
} }
throw ex; throw ex;
} }
@ -186,23 +224,12 @@ public class StandardQueryCache implements QueryCache {
} }
protected boolean isUpToDate(final Set spaces, final Long timestamp) { protected boolean isUpToDate(final Set spaces, final Long timestamp) {
if ( DEBUGGING ) LOG.debugf( "Checking query spaces are up-to-date: %s", spaces ); if ( DEBUGGING ) {
LOG.debugf( "Checking query spaces are up-to-date: %s", spaces );
}
return updateTimestampsCache.isUpToDate( spaces, timestamp ); return updateTimestampsCache.isUpToDate( spaces, timestamp );
} }
public void destroy() {
try {
cacheRegion.destroy();
}
catch ( Exception e ) {
LOG.unableToDestroyQueryCache( cacheRegion.getName(), e.getMessage() );
}
}
public QueryResultsRegion getRegion() {
return cacheRegion;
}
@Override @Override
public String toString() { public String toString() {
return "StandardQueryCache(" + cacheRegion.getName() + ')'; return "StandardQueryCache(" + cacheRegion.getName() + ')';
@ -222,12 +249,13 @@ public class StandardQueryCache implements QueryCache {
); );
} }
else { else {
StringBuilder returnTypeInfo = new StringBuilder(); final StringBuilder returnTypeInfo = new StringBuilder();
for ( int i = 0; i < returnTypes.length; i++ ) { for ( Type returnType : returnTypes ) {
returnTypeInfo.append( "typename=" ) returnTypeInfo.append( "typename=" )
.append( returnTypes[i].getName() ) .append( returnType.getName() )
.append( " class=" ) .append( " class=" )
.append( returnTypes[i].getReturnedClass().getName() ).append( ' ' ); .append( returnType.getReturnedClass().getName() )
.append( ' ' );
} }
LOG.trace( "unexpected returnTypes is " + returnTypeInfo.toString() + "! result" ); LOG.trace( "unexpected returnTypes is " + returnTypeInfo.toString() + "! result" );
} }
@ -248,7 +276,10 @@ public class StandardQueryCache implements QueryCache {
return; return;
} }
if ( tuple == null ) { if ( tuple == null ) {
LOG.trace( " tuple is null; returnTypes is " + returnTypes == null ? "null" : "Type[" + returnTypes.length + "]" ); LOG.tracef(
"tuple is null; returnTypes is %s",
returnTypes == null ? "null" : "Type[" + returnTypes.length + "]"
);
if ( returnTypes != null && returnTypes.length > 1 ) { if ( returnTypes != null && returnTypes.length > 1 ) {
LOG.trace( LOG.trace(
"Unexpected result tuple! tuple is null; should be Object[" "Unexpected result tuple! tuple is null; should be Object["
@ -263,8 +294,12 @@ public class StandardQueryCache implements QueryCache {
+ ( returnTypes == null ? "null" : "empty" ) + ( returnTypes == null ? "null" : "empty" )
); );
} }
LOG.trace( " tuple is Object[" + tuple.length + "]; returnTypes is Type[" + returnTypes.length + "]" ); LOG.tracef(
if ( tuple.length != returnTypes.length ) { "tuple is Object[%s]; returnTypes is %s",
tuple.length,
returnTypes == null ? "null" : "Type[" + returnTypes.length + "]"
);
if ( returnTypes != null && tuple.length != returnTypes.length ) {
LOG.trace( LOG.trace(
"Unexpected tuple length! transformer= expected=" "Unexpected tuple length! transformer= expected="
+ returnTypes.length + " got=" + tuple.length + returnTypes.length + " got=" + tuple.length
@ -272,7 +307,8 @@ public class StandardQueryCache implements QueryCache {
} }
else { else {
for ( int j = 0; j < tuple.length; j++ ) { for ( int j = 0; j < tuple.length; j++ ) {
if ( tuple[j] != null && !returnTypes[j].getReturnedClass().isInstance( tuple[j] ) ) { if ( tuple[j] != null && returnTypes != null
&& ! returnTypes[j].getReturnedClass().isInstance( tuple[j] ) ) {
LOG.trace( LOG.trace(
"Unexpected tuple value type! transformer= expected=" "Unexpected tuple value type! transformer= expected="
+ returnTypes[j].getReturnedClass().getName() + returnTypes[j].getReturnedClass().getName()

View File

@ -38,10 +38,10 @@ import org.hibernate.cfg.Settings;
public class StandardQueryCacheFactory implements QueryCacheFactory { public class StandardQueryCacheFactory implements QueryCacheFactory {
@Override @Override
public QueryCache getQueryCache( public QueryCache getQueryCache(
final String regionName, final String regionName,
final UpdateTimestampsCache updateTimestampsCache, final UpdateTimestampsCache updateTimestampsCache,
final Settings settings, final Settings settings,
final Properties props) throws HibernateException { final Properties props) throws HibernateException {
return new StandardQueryCache(settings, props, updateTimestampsCache, regionName); return new StandardQueryCache(settings, props, updateTimestampsCache, regionName);
} }
} }

View File

@ -0,0 +1,28 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
/**
* Internal implementations and support for second-level caching.
*/
package org.hibernate.cache.internal;

View File

@ -29,7 +29,6 @@ import java.util.Set;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
import org.hibernate.HibernateException;
import org.hibernate.cache.CacheException; import org.hibernate.cache.CacheException;
import org.hibernate.cfg.Settings; import org.hibernate.cfg.Settings;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;

View File

@ -45,8 +45,9 @@ public class StructuredMapCacheEntry implements CacheEntryStructure {
public Object structure(Object item) { public Object structure(Object item) {
final CollectionCacheEntry entry = (CollectionCacheEntry) item; final CollectionCacheEntry entry = (CollectionCacheEntry) item;
final Serializable[] state = entry.getState(); final Serializable[] state = entry.getState();
final Map map = new HashMap(state.length); final Map map = new HashMap( state.length );
for ( int i=0; i<state.length; ) { int i = 0;
while ( i < state.length ) {
map.put( state[i++], state[i++] ); map.put( state[i++], state[i++] );
} }
return map; return map;

View File

@ -75,7 +75,7 @@ public interface Lifecycle {
* Called when an entity is saved. * Called when an entity is saved.
* @param s the session * @param s the session
* @return true to veto save * @return true to veto save
* @throws CallbackException * @throws CallbackException Indicates a problem happened during callback
*/ */
public boolean onSave(Session s) throws CallbackException; public boolean onSave(Session s) throws CallbackException;
@ -85,7 +85,7 @@ public interface Lifecycle {
* state is persisted during a flush. * state is persisted during a flush.
* @param s the session * @param s the session
* @return true to veto update * @return true to veto update
* @throws CallbackException * @throws CallbackException Indicates a problem happened during callback
*/ */
public boolean onUpdate(Session s) throws CallbackException; public boolean onUpdate(Session s) throws CallbackException;
@ -93,7 +93,7 @@ public interface Lifecycle {
* Called when an entity is deleted. * Called when an entity is deleted.
* @param s the session * @param s the session
* @return true to veto delete * @return true to veto delete
* @throws CallbackException * @throws CallbackException Indicates a problem happened during callback
*/ */
public boolean onDelete(Session s) throws CallbackException; public boolean onDelete(Session s) throws CallbackException;
@ -108,9 +108,3 @@ public interface Lifecycle {
*/ */
public void onLoad(Session s, Serializable id); public void onLoad(Session s, Serializable id);
} }

View File

@ -80,41 +80,57 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
private Serializable storedSnapshot; private Serializable storedSnapshot;
private String sessionFactoryUuid; private String sessionFactoryUuid;
private boolean specjLazyLoad = false; private boolean specjLazyLoad;
/**
* Not called by Hibernate, but used by non-JDK serialization,
* eg. SOAP libraries.
*/
public AbstractPersistentCollection() {
}
protected AbstractPersistentCollection(SessionImplementor session) {
this.session = session;
}
@Override
public final String getRole() { public final String getRole() {
return role; return role;
} }
@Override
public final Serializable getKey() { public final Serializable getKey() {
return key; return key;
} }
@Override
public final boolean isUnreferenced() { public final boolean isUnreferenced() {
return role == null; return role == null;
} }
@Override
public final boolean isDirty() { public final boolean isDirty() {
return dirty; return dirty;
} }
@Override
public final void clearDirty() { public final void clearDirty() {
dirty = false; dirty = false;
} }
@Override
public final void dirty() { public final void dirty() {
dirty = true; dirty = true;
} }
@Override
public final Serializable getStoredSnapshot() { public final Serializable getStoredSnapshot() {
return storedSnapshot; return storedSnapshot;
} }
//Careful: these methods do not initialize the collection. //Careful: these methods do not initialize the collection.
/** @Override
* Is the initialized collection empty?
*/
public abstract boolean empty(); public abstract boolean empty();
/** /**
@ -134,14 +150,14 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
return true; return true;
} }
else { else {
boolean isExtraLazy = withTemporarySessionIfNeeded( final boolean isExtraLazy = withTemporarySessionIfNeeded(
new LazyInitializationWork<Boolean>() { new LazyInitializationWork<Boolean>() {
@Override @Override
public Boolean doWork() { public Boolean doWork() {
CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this ); final CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
if ( entry != null ) { if ( entry != null ) {
CollectionPersister persister = entry.getLoadedPersister(); final CollectionPersister persister = entry.getLoadedPersister();
if ( persister.isExtraLazy() ) { if ( persister.isExtraLazy() ) {
if ( hasQueuedOperations() ) { if ( hasQueuedOperations() ) {
session.flush(); session.flush();
@ -168,7 +184,17 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
return false; return false;
} }
/**
* TBH not sure why this is public
*
* @param <T> The java type of the return for this LazyInitializationWork
*/
public static interface LazyInitializationWork<T> { public static interface LazyInitializationWork<T> {
/**
* Do the represented work and return the result.
*
* @return The result
*/
public T doWork(); public T doWork();
} }
@ -221,7 +247,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
// be created even if a current session and transaction are // be created even if a current session and transaction are
// open (ex: session.clear() was used). We must prevent // open (ex: session.clear() was used). We must prevent
// multiple transactions. // multiple transactions.
( ( Session) session ).beginTransaction(); ( (Session) session ).beginTransaction();
} }
session.getPersistenceContext().addUninitializedDetachedCollection( session.getPersistenceContext().addUninitializedDetachedCollection(
@ -238,7 +264,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
// make sure the just opened temp session gets closed! // make sure the just opened temp session gets closed!
try { try {
if ( !isJTA ) { if ( !isJTA ) {
( ( Session) session ).getTransaction().commit(); ( (Session) session ).getTransaction().commit();
} }
( (Session) session ).close(); ( (Session) session ).close();
} }
@ -255,19 +281,19 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
throwLazyInitializationException( "SessionFactory UUID not known to create temporary Session for loading" ); throwLazyInitializationException( "SessionFactory UUID not known to create temporary Session for loading" );
} }
SessionFactoryImplementor sf = (SessionFactoryImplementor) final SessionFactoryImplementor sf = (SessionFactoryImplementor)
SessionFactoryRegistry.INSTANCE.getSessionFactory( sessionFactoryUuid ); SessionFactoryRegistry.INSTANCE.getSessionFactory( sessionFactoryUuid );
return (SessionImplementor) sf.openSession(); return (SessionImplementor) sf.openSession();
} }
protected Boolean readIndexExistence(final Object index) { protected Boolean readIndexExistence(final Object index) {
if ( !initialized ) { if ( !initialized ) {
Boolean extraLazyExistenceCheck = withTemporarySessionIfNeeded( final Boolean extraLazyExistenceCheck = withTemporarySessionIfNeeded(
new LazyInitializationWork<Boolean>() { new LazyInitializationWork<Boolean>() {
@Override @Override
public Boolean doWork() { public Boolean doWork() {
CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this ); final CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
CollectionPersister persister = entry.getLoadedPersister(); final CollectionPersister persister = entry.getLoadedPersister();
if ( persister.isExtraLazy() ) { if ( persister.isExtraLazy() ) {
if ( hasQueuedOperations() ) { if ( hasQueuedOperations() ) {
session.flush(); session.flush();
@ -290,12 +316,12 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
protected Boolean readElementExistence(final Object element) { protected Boolean readElementExistence(final Object element) {
if ( !initialized ) { if ( !initialized ) {
Boolean extraLazyExistenceCheck = withTemporarySessionIfNeeded( final Boolean extraLazyExistenceCheck = withTemporarySessionIfNeeded(
new LazyInitializationWork<Boolean>() { new LazyInitializationWork<Boolean>() {
@Override @Override
public Boolean doWork() { public Boolean doWork() {
CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this ); final CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
CollectionPersister persister = entry.getLoadedPersister(); final CollectionPersister persister = entry.getLoadedPersister();
if ( persister.isExtraLazy() ) { if ( persister.isExtraLazy() ) {
if ( hasQueuedOperations() ) { if ( hasQueuedOperations() ) {
session.flush(); session.flush();
@ -326,8 +352,8 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
@Override @Override
public Object doWork() { public Object doWork() {
CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this ); final CollectionEntry entry = session.getPersistenceContext().getCollectionEntry( AbstractPersistentCollection.this );
CollectionPersister persister = entry.getLoadedPersister(); final CollectionPersister persister = entry.getLoadedPersister();
isExtraLazy = persister.isExtraLazy(); isExtraLazy = persister.isExtraLazy();
if ( isExtraLazy ) { if ( isExtraLazy ) {
if ( hasQueuedOperations() ) { if ( hasQueuedOperations() ) {
@ -342,7 +368,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
} }
} }
ExtraLazyElementByIndexReader reader = new ExtraLazyElementByIndexReader(); final ExtraLazyElementByIndexReader reader = new ExtraLazyElementByIndexReader();
//noinspection unchecked //noinspection unchecked
withTemporarySessionIfNeeded( reader ); withTemporarySessionIfNeeded( reader );
if ( reader.isExtraLazy ) { if ( reader.isExtraLazy ) {
@ -358,9 +384,9 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
} }
private boolean isConnectedToSession() { private boolean isConnectedToSession() {
return session != null && return session != null
session.isOpen() && && session.isOpen()
session.getPersistenceContext().containsCollection( this ); && session.getPersistenceContext().containsCollection( this );
} }
/** /**
@ -377,9 +403,9 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
*/ */
@SuppressWarnings({"JavaDoc"}) @SuppressWarnings({"JavaDoc"})
protected boolean isOperationQueueEnabled() { protected boolean isOperationQueueEnabled() {
return !initialized && return !initialized
isConnectedToSession() && && isConnectedToSession()
isInverseCollection(); && isInverseCollection();
} }
/** /**
@ -389,9 +415,9 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
*/ */
@SuppressWarnings({"JavaDoc"}) @SuppressWarnings({"JavaDoc"})
protected boolean isPutQueueEnabled() { protected boolean isPutQueueEnabled() {
return !initialized && return !initialized
isConnectedToSession() && && isConnectedToSession()
isInverseOneToManyOrNoOrphanDelete(); && isInverseOneToManyOrNoOrphanDelete();
} }
/** /**
@ -401,9 +427,9 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
*/ */
@SuppressWarnings({"JavaDoc"}) @SuppressWarnings({"JavaDoc"})
protected boolean isClearQueueEnabled() { protected boolean isClearQueueEnabled() {
return !initialized && return !initialized
isConnectedToSession() && && isConnectedToSession()
isInverseCollectionNoOrphanDelete(); && isInverseCollectionNoOrphanDelete();
} }
/** /**
@ -411,7 +437,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
*/ */
@SuppressWarnings({"JavaDoc"}) @SuppressWarnings({"JavaDoc"})
private boolean isInverseCollection() { private boolean isInverseCollection() {
CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this ); final CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
return ce != null && ce.getLoadedPersister().isInverse(); return ce != null && ce.getLoadedPersister().isInverse();
} }
@ -421,8 +447,9 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
*/ */
@SuppressWarnings({"JavaDoc"}) @SuppressWarnings({"JavaDoc"})
private boolean isInverseCollectionNoOrphanDelete() { private boolean isInverseCollectionNoOrphanDelete() {
CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this ); final CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
return ce != null && return ce != null
&&
ce.getLoadedPersister().isInverse() && ce.getLoadedPersister().isInverse() &&
!ce.getLoadedPersister().hasOrphanDelete(); !ce.getLoadedPersister().hasOrphanDelete();
} }
@ -433,11 +460,10 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
*/ */
@SuppressWarnings({"JavaDoc"}) @SuppressWarnings({"JavaDoc"})
private boolean isInverseOneToManyOrNoOrphanDelete() { private boolean isInverseOneToManyOrNoOrphanDelete() {
CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this ); final CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
return ce != null && ce.getLoadedPersister().isInverse() && ( return ce != null
ce.getLoadedPersister().isOneToMany() || && ce.getLoadedPersister().isInverse()
!ce.getLoadedPersister().hasOrphanDelete() && ( ce.getLoadedPersister().isOneToMany() || !ce.getLoadedPersister().hasOrphanDelete() );
);
} }
/** /**
@ -449,7 +475,8 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
operationQueue = new ArrayList<DelayedOperation>( 10 ); operationQueue = new ArrayList<DelayedOperation>( 10 );
} }
operationQueue.add( operation ); operationQueue.add( operation );
dirty = true; //needed so that we remove this collection from the second-level cache //needed so that we remove this collection from the second-level cache
dirty = true;
} }
/** /**
@ -462,59 +489,38 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
} }
} }
/** @Override
* After flushing, re-init snapshot state.
*/
public void setSnapshot(Serializable key, String role, Serializable snapshot) { public void setSnapshot(Serializable key, String role, Serializable snapshot) {
this.key = key; this.key = key;
this.role = role; this.role = role;
this.storedSnapshot = snapshot; this.storedSnapshot = snapshot;
} }
/** @Override
* After flushing, clear any "queued" additions, since the
* database state is now synchronized with the memory state.
*/
public void postAction() { public void postAction() {
operationQueue = null; operationQueue = null;
cachedSize = -1; cachedSize = -1;
clearDirty(); clearDirty();
} }
/** @Override
* Not called by Hibernate, but used by non-JDK serialization,
* eg. SOAP libraries.
*/
public AbstractPersistentCollection() {
}
protected AbstractPersistentCollection(SessionImplementor session) {
this.session = session;
}
/**
* return the user-visible collection (or array) instance
*/
public Object getValue() { public Object getValue() {
return this; return this;
} }
/** @Override
* Called just before reading any rows from the JDBC result set
*/
public void beginRead() { public void beginRead() {
// override on some subclasses // override on some subclasses
initializing = true; initializing = true;
} }
/** @Override
* Called after reading all rows from the JDBC result set
*/
public boolean endRead() { public boolean endRead() {
//override on some subclasses //override on some subclasses
return afterInitialize(); return afterInitialize();
} }
@Override
public boolean afterInitialize() { public boolean afterInitialize() {
setInitialized(); setInitialized();
//do this bit after setting initialized to true or it will recurse //do this bit after setting initialized to true or it will recurse
@ -579,19 +585,12 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
this.directlyAccessible = directlyAccessible; this.directlyAccessible = directlyAccessible;
} }
/** @Override
* Could the application possibly have a direct reference to
* the underlying collection implementation?
*/
public boolean isDirectlyAccessible() { public boolean isDirectlyAccessible() {
return directlyAccessible; return directlyAccessible;
} }
/** @Override
* Disassociate this collection from the given session.
*
* @return true if this was currently associated with the given session
*/
public final boolean unsetSession(SessionImplementor currentSession) { public final boolean unsetSession(SessionImplementor currentSession) {
prepareForPossibleSpecialSpecjInitialization(); prepareForPossibleSpecialSpecjInitialization();
if ( currentSession == this.session ) { if ( currentSession == this.session ) {
@ -619,21 +618,14 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
} }
/** @Override
* Associate the collection with the given session.
*
* @return false if the collection was already associated with the session
*
* @throws HibernateException if the collection was already associated
* with another open session
*/
public final boolean setCurrentSession(SessionImplementor session) throws HibernateException { public final boolean setCurrentSession(SessionImplementor session) throws HibernateException {
if ( session == this.session ) { if ( session == this.session ) {
return false; return false;
} }
else { else {
if ( isConnectedToSession() ) { if ( isConnectedToSession() ) {
CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this ); final CollectionEntry ce = session.getPersistenceContext().getCollectionEntry( this );
if ( ce == null ) { if ( ce == null ) {
throw new HibernateException( throw new HibernateException(
"Illegal attempt to associate a collection with two open sessions" "Illegal attempt to associate a collection with two open sessions"
@ -656,17 +648,12 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
} }
} }
/** @Override
* Do we need to completely recreate this collection when it changes?
*/
public boolean needsRecreate(CollectionPersister persister) { public boolean needsRecreate(CollectionPersister persister) {
return false; return false;
} }
/** @Override
* To be called internally by the session, forcing
* immediate initialization.
*/
public final void forceInitialization() throws HibernateException { public final void forceInitialization() throws HibernateException {
if ( !initialized ) { if ( !initialized ) {
if ( initializing ) { if ( initializing ) {
@ -691,40 +678,38 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
return session.getPersistenceContext().getSnapshot( this ); return session.getPersistenceContext().getSnapshot( this );
} }
/** @Override
* Is this instance initialized?
*/
public final boolean wasInitialized() { public final boolean wasInitialized() {
return initialized; return initialized;
} }
@Override
public boolean isRowUpdatePossible() { public boolean isRowUpdatePossible() {
return true; return true;
} }
/** @Override
* Does this instance have any "queued" additions?
*/
public final boolean hasQueuedOperations() { public final boolean hasQueuedOperations() {
return operationQueue != null; return operationQueue != null;
} }
/** @Override
* Iterate the "queued" additions
*/
public final Iterator queuedAdditionIterator() { public final Iterator queuedAdditionIterator() {
if ( hasQueuedOperations() ) { if ( hasQueuedOperations() ) {
return new Iterator() { return new Iterator() {
int i = 0; private int index;
@Override
public Object next() { public Object next() {
return operationQueue.get( i++ ).getAddedInstance(); return operationQueue.get( index++ ).getAddedInstance();
} }
@Override
public boolean hasNext() { public boolean hasNext() {
return i < operationQueue.size(); return index < operationQueue.size();
} }
@Override
public void remove() { public void remove() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@ -735,14 +720,12 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
} }
} }
/** @Override
* Iterate the "queued" additions
*/
@SuppressWarnings({"unchecked"}) @SuppressWarnings({"unchecked"})
public final Collection getQueuedOrphans(String entityName) { public final Collection getQueuedOrphans(String entityName) {
if ( hasQueuedOperations() ) { if ( hasQueuedOperations() ) {
Collection additions = new ArrayList( operationQueue.size() ); final Collection additions = new ArrayList( operationQueue.size() );
Collection removals = new ArrayList( operationQueue.size() ); final Collection removals = new ArrayList( operationQueue.size() );
for ( DelayedOperation operation : operationQueue ) { for ( DelayedOperation operation : operationQueue ) {
additions.add( operation.getAddedInstance() ); additions.add( operation.getAddedInstance() );
removals.add( operation.getOrphan() ); removals.add( operation.getOrphan() );
@ -754,28 +737,22 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
} }
} }
/** @Override
* Called before inserting rows, to ensure that any surrogate keys
* are fully generated
*/
public void preInsert(CollectionPersister persister) throws HibernateException { public void preInsert(CollectionPersister persister) throws HibernateException {
} }
/** @Override
* Called after inserting a row, to fetch the natively generated id
*/
public void afterRowInsert(CollectionPersister persister, Object entry, int i) throws HibernateException { public void afterRowInsert(CollectionPersister persister, Object entry, int i) throws HibernateException {
} }
/** @Override
* get all "orphaned" elements
*/
public abstract Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException; public abstract Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException;
/** /**
* Get the current session * Get the session currently associated with this collection.
*
* @return The session
*/ */
@SuppressWarnings({"JavaDoc"})
public final SessionImplementor getSession() { public final SessionImplementor getSession() {
return session; return session;
} }
@ -787,19 +764,21 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
this.itr = itr; this.itr = itr;
} }
@Override
public boolean hasNext() { public boolean hasNext() {
return itr.hasNext(); return itr.hasNext();
} }
@Override
public Object next() { public Object next() {
return itr.next(); return itr.next();
} }
@Override
public void remove() { public void remove() {
write(); write();
itr.remove(); itr.remove();
} }
} }
protected final class ListIteratorProxy implements ListIterator { protected final class ListIteratorProxy implements ListIterator {
@ -809,47 +788,55 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
this.itr = itr; this.itr = itr;
} }
@Override
@SuppressWarnings({"unchecked"}) @SuppressWarnings({"unchecked"})
public void add(Object o) { public void add(Object o) {
write(); write();
itr.add( o ); itr.add( o );
} }
@Override
public boolean hasNext() { public boolean hasNext() {
return itr.hasNext(); return itr.hasNext();
} }
@Override
public boolean hasPrevious() { public boolean hasPrevious() {
return itr.hasPrevious(); return itr.hasPrevious();
} }
@Override
public Object next() { public Object next() {
return itr.next(); return itr.next();
} }
@Override
public int nextIndex() { public int nextIndex() {
return itr.nextIndex(); return itr.nextIndex();
} }
@Override
public Object previous() { public Object previous() {
return itr.previous(); return itr.previous();
} }
@Override
public int previousIndex() { public int previousIndex() {
return itr.previousIndex(); return itr.previousIndex();
} }
@Override
public void remove() { public void remove() {
write(); write();
itr.remove(); itr.remove();
} }
@Override
@SuppressWarnings({"unchecked"}) @SuppressWarnings({"unchecked"})
public void set(Object o) { public void set(Object o) {
write(); write();
itr.set( o ); itr.set( o );
} }
} }
protected class SetProxy implements java.util.Set { protected class SetProxy implements java.util.Set {
@ -859,67 +846,82 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
this.set = set; this.set = set;
} }
@Override
@SuppressWarnings({"unchecked"}) @SuppressWarnings({"unchecked"})
public boolean add(Object o) { public boolean add(Object o) {
write(); write();
return set.add( o ); return set.add( o );
} }
@Override
@SuppressWarnings({"unchecked"}) @SuppressWarnings({"unchecked"})
public boolean addAll(Collection c) { public boolean addAll(Collection c) {
write(); write();
return set.addAll( c ); return set.addAll( c );
} }
@Override
public void clear() { public void clear() {
write(); write();
set.clear(); set.clear();
} }
@Override
public boolean contains(Object o) { public boolean contains(Object o) {
return set.contains( o ); return set.contains( o );
} }
@Override
@SuppressWarnings("unchecked")
public boolean containsAll(Collection c) { public boolean containsAll(Collection c) {
return set.containsAll( c ); return set.containsAll( c );
} }
@Override
public boolean isEmpty() { public boolean isEmpty() {
return set.isEmpty(); return set.isEmpty();
} }
@Override
public Iterator iterator() { public Iterator iterator() {
return new IteratorProxy( set.iterator() ); return new IteratorProxy( set.iterator() );
} }
@Override
public boolean remove(Object o) { public boolean remove(Object o) {
write(); write();
return set.remove( o ); return set.remove( o );
} }
@Override
@SuppressWarnings("unchecked")
public boolean removeAll(Collection c) { public boolean removeAll(Collection c) {
write(); write();
return set.removeAll( c ); return set.removeAll( c );
} }
@Override
@SuppressWarnings("unchecked")
public boolean retainAll(Collection c) { public boolean retainAll(Collection c) {
write(); write();
return set.retainAll( c ); return set.retainAll( c );
} }
@Override
public int size() { public int size() {
return set.size(); return set.size();
} }
@Override
public Object[] toArray() { public Object[] toArray() {
return set.toArray(); return set.toArray();
} }
@Override
@SuppressWarnings({"unchecked"}) @SuppressWarnings({"unchecked"})
public Object[] toArray(Object[] array) { public Object[] toArray(Object[] array) {
return set.toArray( array ); return set.toArray( array );
} }
} }
protected final class ListProxy implements java.util.List { protected final class ListProxy implements java.util.List {
@ -969,6 +971,7 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
} }
@Override @Override
@SuppressWarnings("unchecked")
public boolean containsAll(Collection c) { public boolean containsAll(Collection c) {
return list.containsAll( c ); return list.containsAll( c );
} }
@ -1021,12 +1024,14 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
} }
@Override @Override
@SuppressWarnings("unchecked")
public boolean removeAll(Collection c) { public boolean removeAll(Collection c) {
write(); write();
return list.removeAll( c ); return list.removeAll( c );
} }
@Override @Override
@SuppressWarnings("unchecked")
public boolean retainAll(Collection c) { public boolean retainAll(Collection c) {
write(); write();
return list.retainAll( c ); return list.retainAll( c );
@ -1087,34 +1092,36 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
// short-circuit(s) // short-circuit(s)
if ( currentElements.size() == 0 ) { if ( currentElements.size() == 0 ) {
return oldElements; // no new elements, the old list contains only Orphans // no new elements, the old list contains only Orphans
return oldElements;
} }
if ( oldElements.size() == 0 ) { if ( oldElements.size() == 0 ) {
return oldElements; // no old elements, so no Orphans neither // no old elements, so no Orphans neither
return oldElements;
} }
final EntityPersister entityPersister = session.getFactory().getEntityPersister( entityName ); final EntityPersister entityPersister = session.getFactory().getEntityPersister( entityName );
final Type idType = entityPersister.getIdentifierType(); final Type idType = entityPersister.getIdentifierType();
// create the collection holding the Orphans // create the collection holding the Orphans
Collection res = new ArrayList(); final Collection res = new ArrayList();
// collect EntityIdentifier(s) of the *current* elements - add them into a HashSet for fast access // collect EntityIdentifier(s) of the *current* elements - add them into a HashSet for fast access
java.util.Set currentIds = new HashSet(); final java.util.Set currentIds = new HashSet();
java.util.Set currentSaving = new IdentitySet(); final java.util.Set currentSaving = new IdentitySet();
for ( Object current : currentElements ) { for ( Object current : currentElements ) {
if ( current != null && ForeignKeys.isNotTransient( entityName, current, null, session ) ) { if ( current != null && ForeignKeys.isNotTransient( entityName, current, null, session ) ) {
EntityEntry ee = session.getPersistenceContext().getEntry( current ); final EntityEntry ee = session.getPersistenceContext().getEntry( current );
if ( ee != null && ee.getStatus() == Status.SAVING ) { if ( ee != null && ee.getStatus() == Status.SAVING ) {
currentSaving.add( current ); currentSaving.add( current );
} }
else { else {
Serializable currentId = ForeignKeys.getEntityIdentifierIfNotUnsaved( final Serializable currentId = ForeignKeys.getEntityIdentifierIfNotUnsaved(
entityName, entityName,
current, current,
session session
); );
currentIds.add( new TypedValue( idType, currentId, entityPersister.getEntityMode() ) ); currentIds.add( new TypedValue( idType, currentId ) );
} }
} }
} }
@ -1122,8 +1129,8 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
// iterate over the *old* list // iterate over the *old* list
for ( Object old : oldElements ) { for ( Object old : oldElements ) {
if ( !currentSaving.contains( old ) ) { if ( !currentSaving.contains( old ) ) {
Serializable oldId = ForeignKeys.getEntityIdentifierIfNotUnsaved( entityName, old, session ); final Serializable oldId = ForeignKeys.getEntityIdentifierIfNotUnsaved( entityName, old, session );
if ( !currentIds.contains( new TypedValue( idType, oldId, entityPersister.getEntityMode() ) ) ) { if ( !currentIds.contains( new TypedValue( idType, oldId ) ) ) {
res.add( old ); res.add( old );
} }
} }
@ -1132,20 +1139,28 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
return res; return res;
} }
/**
* Removes entity entries that have an equal identifier with the incoming entity instance
*
* @param list The list containing the entity instances
* @param entityInstance The entity instance to match elements.
* @param entityName The entity name
* @param session The session
*/
public static void identityRemove( public static void identityRemove(
Collection list, Collection list,
Object object, Object entityInstance,
String entityName, String entityName,
SessionImplementor session) throws HibernateException { SessionImplementor session) {
if ( object != null && ForeignKeys.isNotTransient( entityName, object, null, session ) ) { if ( entityInstance != null && ForeignKeys.isNotTransient( entityName, entityInstance, null, session ) ) {
final EntityPersister entityPersister = session.getFactory().getEntityPersister( entityName ); final EntityPersister entityPersister = session.getFactory().getEntityPersister( entityName );
Type idType = entityPersister.getIdentifierType(); final Type idType = entityPersister.getIdentifierType();
Serializable idOfCurrent = ForeignKeys.getEntityIdentifierIfNotUnsaved( entityName, object, session ); final Serializable idOfCurrent = ForeignKeys.getEntityIdentifierIfNotUnsaved( entityName, entityInstance, session );
Iterator itr = list.iterator(); final Iterator itr = list.iterator();
while ( itr.hasNext() ) { while ( itr.hasNext() ) {
Serializable idOfOld = ForeignKeys.getEntityIdentifierIfNotUnsaved( entityName, itr.next(), session ); final Serializable idOfOld = ForeignKeys.getEntityIdentifierIfNotUnsaved( entityName, itr.next(), session );
if ( idType.isEqual( idOfCurrent, idOfOld, session.getFactory() ) ) { if ( idType.isEqual( idOfCurrent, idOfOld, session.getFactory() ) ) {
itr.remove(); itr.remove();
break; break;
@ -1155,14 +1170,17 @@ public abstract class AbstractPersistentCollection implements Serializable, Pers
} }
} }
@Override
public Object getIdentifier(Object entry, int i) { public Object getIdentifier(Object entry, int i) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
public Object getOwner() { public Object getOwner() {
return owner; return owner;
} }
@Override
public void setOwner(Object owner) { public void setOwner(Object owner) {
this.owner = owner; this.owner = owner;
} }

View File

@ -29,6 +29,7 @@ import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections;
import java.util.Iterator; import java.util.Iterator;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -48,27 +49,52 @@ import org.hibernate.type.Type;
* @author Gavin King * @author Gavin King
*/ */
public class PersistentArrayHolder extends AbstractPersistentCollection { public class PersistentArrayHolder extends AbstractPersistentCollection {
protected Object array; private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
PersistentArrayHolder.class.getName()
);
private static final CoreMessageLogger LOG = Logger.getMessageLogger(CoreMessageLogger.class, PersistentArrayHolder.class.getName()); protected Object array;
//just to help out during the load (ugly, i know) //just to help out during the load (ugly, i know)
private transient Class elementClass; private transient Class elementClass;
private transient java.util.List tempList; private transient java.util.List tempList;
/**
* Constructs a PersistentCollection instance for holding an array.
*
* @param session The session
* @param array The array (the persistent "collection").
*/
public PersistentArrayHolder(SessionImplementor session, Object array) { public PersistentArrayHolder(SessionImplementor session, Object array) {
super(session); super( session );
this.array = array; this.array = array;
setInitialized(); setInitialized();
} }
/**
* Constructs a PersistentCollection instance for holding an array.
*
* @param session The session
* @param persister The persister for the array
*/
public PersistentArrayHolder(SessionImplementor session, CollectionPersister persister) {
super( session );
elementClass = persister.getElementClass();
}
@Override
public Serializable getSnapshot(CollectionPersister persister) throws HibernateException { public Serializable getSnapshot(CollectionPersister persister) throws HibernateException {
int length = /*(array==null) ? tempList.size() :*/ Array.getLength(array); // final int length = (array==null) ? tempList.size() : Array.getLength( array );
Serializable result = (Serializable) Array.newInstance( persister.getElementClass(), length ); final int length = Array.getLength( array );
final Serializable result = (Serializable) Array.newInstance( persister.getElementClass(), length );
for ( int i=0; i<length; i++ ) { for ( int i=0; i<length; i++ ) {
Object elt = /*(array==null) ? tempList.get(i) :*/ Array.get(array, i); // final Object elt = (array==null) ? tempList.get( i ) : Array.get( array, i );
final Object elt = Array.get( array, i );
try { try {
Array.set( result, i, persister.getElementType().deepCopy(elt, persister.getFactory()) ); Array.set( result, i, persister.getElementType().deepCopy( elt, persister.getFactory() ) );
} }
catch (IllegalArgumentException iae) { catch (IllegalArgumentException iae) {
LOG.invalidArrayElementType( iae.getMessage() ); LOG.invalidArrayElementType( iae.getMessage() );
@ -78,70 +104,84 @@ public class PersistentArrayHolder extends AbstractPersistentCollection {
return result; return result;
} }
@Override
public boolean isSnapshotEmpty(Serializable snapshot) { public boolean isSnapshotEmpty(Serializable snapshot) {
return Array.getLength( snapshot ) == 0; return Array.getLength( snapshot ) == 0;
} }
@Override @Override
public Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException { public Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException {
Object[] sn = (Object[]) snapshot; final Object[] sn = (Object[]) snapshot;
Object[] arr = (Object[]) array; final Object[] arr = (Object[]) array;
ArrayList result = new ArrayList(); final ArrayList result = new ArrayList();
for (int i=0; i<sn.length; i++) result.add( sn[i] ); Collections.addAll( result, sn );
for (int i=0; i<sn.length; i++) identityRemove( result, arr[i], entityName, getSession() ); for ( int i=0; i<sn.length; i++ ) {
identityRemove( result, arr[i], entityName, getSession() );
}
return result; return result;
} }
public PersistentArrayHolder(SessionImplementor session, CollectionPersister persister) throws HibernateException { @SuppressWarnings("UnusedDeclaration")
super(session);
elementClass = persister.getElementClass();
}
public Object getArray() { public Object getArray() {
return array; return array;
} }
@Override
public boolean isWrapper(Object collection) { public boolean isWrapper(Object collection) {
return array==collection; return array==collection;
} }
@Override
public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException { public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException {
Type elementType = persister.getElementType(); final Type elementType = persister.getElementType();
Serializable snapshot = getSnapshot(); final Serializable snapshot = getSnapshot();
int xlen = Array.getLength(snapshot); final int xlen = Array.getLength( snapshot );
if ( xlen!= Array.getLength(array) ) return false; if ( xlen!= Array.getLength( array ) ) {
return false;
}
for ( int i=0; i<xlen; i++) { for ( int i=0; i<xlen; i++) {
if ( elementType.isDirty( Array.get(snapshot, i), Array.get(array, i), getSession() ) ) return false; if ( elementType.isDirty( Array.get( snapshot, i ), Array.get( array, i ), getSession() ) ) {
return false;
}
} }
return true; return true;
} }
/**
* Get an iterator over the array elements
*
* @return The iterator
*/
@SuppressWarnings("unchecked")
public Iterator elements() { public Iterator elements() {
//if (array==null) return tempList.iterator(); final int length = Array.getLength( array );
int length = Array.getLength(array); final java.util.List list = new ArrayList( length );
java.util.List list = new ArrayList(length); for ( int i=0; i<length; i++ ) {
for (int i=0; i<length; i++) { list.add( Array.get( array, i ) );
list.add( Array.get(array, i) );
} }
return list.iterator(); return list.iterator();
} }
@Override @Override
public boolean empty() { public boolean empty() {
return false; return false;
} }
@Override
@SuppressWarnings("unchecked")
public Object readFrom(ResultSet rs, CollectionPersister persister, CollectionAliases descriptor, Object owner) public Object readFrom(ResultSet rs, CollectionPersister persister, CollectionAliases descriptor, Object owner)
throws HibernateException, SQLException { throws HibernateException, SQLException {
final Object element = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() );
Object element = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() ); final int index = (Integer) persister.readIndex( rs, descriptor.getSuffixedIndexAliases(), getSession() );
int index = (Integer) persister.readIndex( rs, descriptor.getSuffixedIndexAliases(), getSession() );
for ( int i = tempList.size(); i<=index; i++) { for ( int i = tempList.size(); i<=index; i++) {
tempList.add(i, null); tempList.add( i, null );
} }
tempList.set(index, element); tempList.set( index, element );
return element; return element;
} }
@Override
@SuppressWarnings("unchecked")
public Iterator entries(CollectionPersister persister) { public Iterator entries(CollectionPersister persister) {
return elements(); return elements();
} }
@ -151,30 +191,32 @@ public class PersistentArrayHolder extends AbstractPersistentCollection {
super.beginRead(); super.beginRead();
tempList = new ArrayList(); tempList = new ArrayList();
} }
@Override @Override
public boolean endRead() { public boolean endRead() {
setInitialized(); setInitialized();
array = Array.newInstance( elementClass, tempList.size() ); array = Array.newInstance( elementClass, tempList.size() );
for ( int i=0; i<tempList.size(); i++) { for ( int i=0; i<tempList.size(); i++ ) {
Array.set(array, i, tempList.get(i) ); Array.set( array, i, tempList.get( i ) );
} }
tempList=null; tempList = null;
return true; return true;
} }
@Override
public void beforeInitialize(CollectionPersister persister, int anticipatedSize) { public void beforeInitialize(CollectionPersister persister, int anticipatedSize) {
//if (tempList==null) throw new UnsupportedOperationException("Can't lazily initialize arrays"); //if (tempList==null) throw new UnsupportedOperationException("Can't lazily initialize arrays");
} }
@Override @Override
public boolean isDirectlyAccessible() { public boolean isDirectlyAccessible() {
return true; return true;
} }
@Override
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner) public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner)
throws HibernateException { throws HibernateException {
Serializable[] cached = (Serializable[]) disassembled; final Serializable[] cached = (Serializable[]) disassembled;
array = Array.newInstance( persister.getElementClass(), cached.length ); array = Array.newInstance( persister.getElementClass(), cached.length );
for ( int i=0; i<cached.length; i++ ) { for ( int i=0; i<cached.length; i++ ) {
@ -182,74 +224,79 @@ public class PersistentArrayHolder extends AbstractPersistentCollection {
} }
} }
@Override
public Serializable disassemble(CollectionPersister persister) throws HibernateException { public Serializable disassemble(CollectionPersister persister) throws HibernateException {
int length = Array.getLength(array); final int length = Array.getLength( array );
Serializable[] result = new Serializable[length]; final Serializable[] result = new Serializable[length];
for ( int i=0; i<length; i++ ) { for ( int i=0; i<length; i++ ) {
result[i] = persister.getElementType().disassemble( Array.get(array,i), getSession(), null ); result[i] = persister.getElementType().disassemble( Array.get( array,i ), getSession(), null );
} }
/*int length = tempList.size();
Serializable[] result = new Serializable[length];
for ( int i=0; i<length; i++ ) {
result[i] = persister.getElementType().disassemble( tempList.get(i), session );
}*/
return result; return result;
} }
@Override @Override
public Object getValue() { public Object getValue() {
return array; return array;
} }
@Override
public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) throws HibernateException { public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) throws HibernateException {
java.util.List<Integer> deletes = new ArrayList<Integer>(); final java.util.List<Integer> deletes = new ArrayList<Integer>();
Serializable sn = getSnapshot(); final Serializable sn = getSnapshot();
int snSize = Array.getLength(sn); final int snSize = Array.getLength( sn );
int arraySize = Array.getLength(array); final int arraySize = Array.getLength( array );
int end; int end;
if ( snSize > arraySize ) { if ( snSize > arraySize ) {
for ( int i=arraySize; i<snSize; i++ ) deletes.add( i ); for ( int i=arraySize; i<snSize; i++ ) {
deletes.add( i );
}
end = arraySize; end = arraySize;
} }
else { else {
end = snSize; end = snSize;
} }
for ( int i=0; i<end; i++ ) { for ( int i=0; i<end; i++ ) {
if ( Array.get(array, i)==null && Array.get(sn, i)!=null ) deletes.add( i ); if ( Array.get( array, i ) == null && Array.get( sn, i ) != null ) {
deletes.add( i );
}
} }
return deletes.iterator(); return deletes.iterator();
} }
@Override
public boolean needsInserting(Object entry, int i, Type elemType) throws HibernateException { public boolean needsInserting(Object entry, int i, Type elemType) throws HibernateException {
Serializable sn = getSnapshot(); final Serializable sn = getSnapshot();
return Array.get(array, i)!=null && ( i >= Array.getLength(sn) || Array.get(sn, i)==null ); return Array.get( array, i ) != null && ( i >= Array.getLength( sn ) || Array.get( sn, i ) == null );
} }
@Override
public boolean needsUpdating(Object entry, int i, Type elemType) throws HibernateException { public boolean needsUpdating(Object entry, int i, Type elemType) throws HibernateException {
Serializable sn = getSnapshot(); final Serializable sn = getSnapshot();
return i<Array.getLength(sn) && return i < Array.getLength( sn )
Array.get(sn, i)!=null && && Array.get( sn, i ) != null
Array.get(array, i)!=null && && Array.get( array, i ) != null
elemType.isDirty( Array.get(array, i), Array.get(sn, i), getSession() ); && elemType.isDirty( Array.get( array, i ), Array.get( sn, i ), getSession() );
} }
@Override
public Object getIndex(Object entry, int i, CollectionPersister persister) { public Object getIndex(Object entry, int i, CollectionPersister persister) {
return i; return i;
} }
@Override
public Object getElement(Object entry) { public Object getElement(Object entry) {
return entry; return entry;
} }
@Override
public Object getSnapshotElement(Object entry, int i) { public Object getSnapshotElement(Object entry, int i) {
Serializable sn = getSnapshot(); final Serializable sn = getSnapshot();
return Array.get(sn, i); return Array.get( sn, i );
} }
@Override
public boolean entryExists(Object entry, int i) { public boolean entryExists(Object entry, int i) {
return entry!=null; return entry != null;
} }
} }

View File

@ -50,59 +50,86 @@ public class PersistentBag extends AbstractPersistentCollection implements List
protected List bag; protected List bag;
public PersistentBag(SessionImplementor session) { /**
super(session); * Constructs a PersistentBag. Needed for SOAP libraries, etc
*/
@SuppressWarnings("UnusedDeclaration")
public PersistentBag() {
} }
/**
* Constructs a PersistentBag
*
* @param session The session
*/
public PersistentBag(SessionImplementor session) {
super( session );
}
/**
* Constructs a PersistentBag
*
* @param session The session
* @param coll The base elements.
*/
@SuppressWarnings("unchecked")
public PersistentBag(SessionImplementor session, Collection coll) { public PersistentBag(SessionImplementor session, Collection coll) {
super(session); super( session );
if (coll instanceof List) { if ( coll instanceof List ) {
bag = (List) coll; bag = (List) coll;
} }
else { else {
bag = new ArrayList(); bag = new ArrayList();
Iterator iter = coll.iterator(); for ( Object element : coll ) {
while ( iter.hasNext() ) { bag.add( element );
bag.add( iter.next() );
} }
} }
setInitialized(); setInitialized();
setDirectlyAccessible(true); setDirectlyAccessible( true );
} }
public PersistentBag() {} //needed for SOAP libraries, etc @Override
public boolean isWrapper(Object collection) { public boolean isWrapper(Object collection) {
return bag==collection; return bag==collection;
} }
@Override
public boolean empty() { public boolean empty() {
return bag.isEmpty(); return bag.isEmpty();
} }
@Override
public Iterator entries(CollectionPersister persister) { public Iterator entries(CollectionPersister persister) {
return bag.iterator(); return bag.iterator();
} }
@Override
@SuppressWarnings("unchecked")
public Object readFrom(ResultSet rs, CollectionPersister persister, CollectionAliases descriptor, Object owner) public Object readFrom(ResultSet rs, CollectionPersister persister, CollectionAliases descriptor, Object owner)
throws HibernateException, SQLException { throws HibernateException, SQLException {
// note that if we load this collection from a cartesian product // note that if we load this collection from a cartesian product
// the multiplicity would be broken ... so use an idbag instead // the multiplicity would be broken ... so use an idbag instead
Object element = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() ) ; final Object element = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() ) ;
if (element!=null) bag.add(element); if ( element != null ) {
bag.add( element );
}
return element; return element;
} }
@Override
public void beforeInitialize(CollectionPersister persister, int anticipatedSize) { public void beforeInitialize(CollectionPersister persister, int anticipatedSize) {
this.bag = ( List ) persister.getCollectionType().instantiate( anticipatedSize ); this.bag = (List) persister.getCollectionType().instantiate( anticipatedSize );
} }
@Override
public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException { public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException {
Type elementType = persister.getElementType(); final Type elementType = persister.getElementType();
List sn = (List) getSnapshot(); final List sn = (List) getSnapshot();
if ( sn.size()!=bag.size() ) return false; if ( sn.size() != bag.size() ) {
return false;
}
for ( Object elt : bag ) { for ( Object elt : bag ) {
final boolean unequal = countOccurrences( elt, bag, elementType ) final boolean unequal = countOccurrences( elt, bag, elementType ) != countOccurrences( elt, sn, elementType );
!= countOccurrences( elt, sn, elementType );
if ( unequal ) { if ( unequal ) {
return false; return false;
} }
@ -110,60 +137,67 @@ public class PersistentBag extends AbstractPersistentCollection implements List
return true; return true;
} }
@Override
public boolean isSnapshotEmpty(Serializable snapshot) { public boolean isSnapshotEmpty(Serializable snapshot) {
return ( (Collection) snapshot ).isEmpty(); return ( (Collection) snapshot ).isEmpty();
} }
private int countOccurrences(Object element, List list, Type elementType) private int countOccurrences(Object element, List list, Type elementType)
throws HibernateException { throws HibernateException {
Iterator iter = list.iterator(); final Iterator iter = list.iterator();
int result=0; int result = 0;
while ( iter.hasNext() ) { while ( iter.hasNext() ) {
if ( elementType.isSame( element, iter.next() ) ) result++; if ( elementType.isSame( element, iter.next() ) ) {
result++;
}
} }
return result; return result;
} }
@Override
@SuppressWarnings("unchecked")
public Serializable getSnapshot(CollectionPersister persister) public Serializable getSnapshot(CollectionPersister persister)
throws HibernateException { throws HibernateException {
ArrayList clonedList = new ArrayList( bag.size() ); final ArrayList clonedList = new ArrayList( bag.size() );
Iterator iter = bag.iterator(); for ( Object item : bag ) {
while ( iter.hasNext() ) { clonedList.add( persister.getElementType().deepCopy( item, persister.getFactory() ) );
clonedList.add( persister.getElementType().deepCopy( iter.next(), persister.getFactory() ) );
} }
return clonedList; return clonedList;
} }
@Override
public Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException { public Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException {
List sn = (List) snapshot; final List sn = (List) snapshot;
return getOrphans( sn, bag, entityName, getSession() ); return getOrphans( sn, bag, entityName, getSession() );
} }
@Override
public Serializable disassemble(CollectionPersister persister) public Serializable disassemble(CollectionPersister persister)
throws HibernateException { throws HibernateException {
final int length = bag.size();
int length = bag.size(); final Serializable[] result = new Serializable[length];
Serializable[] result = new Serializable[length];
for ( int i=0; i<length; i++ ) { for ( int i=0; i<length; i++ ) {
result[i] = persister.getElementType().disassemble( bag.get(i), getSession(), null ); result[i] = persister.getElementType().disassemble( bag.get( i ), getSession(), null );
} }
return result; return result;
} }
@Override
@SuppressWarnings("unchecked")
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner) public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner)
throws HibernateException { throws HibernateException {
Serializable[] array = (Serializable[]) disassembled; final Serializable[] array = (Serializable[]) disassembled;
int size = array.length; final int size = array.length;
beforeInitialize( persister, size ); beforeInitialize( persister, size );
for ( int i = 0; i < size; i++ ) { for ( Serializable item : array ) {
Object element = persister.getElementType().assemble( array[i], getSession(), owner ); final Object element = persister.getElementType().assemble( item, getSession(), owner );
if ( element!=null ) { if ( element != null ) {
bag.add( element ); bag.add( element );
} }
} }
} }
@Override
public boolean needsRecreate(CollectionPersister persister) { public boolean needsRecreate(CollectionPersister persister) {
return !persister.isOneToMany(); return !persister.isOneToMany();
} }
@ -177,18 +211,19 @@ public class PersistentBag extends AbstractPersistentCollection implements List
// Anyway, here we implement <set> semantics for a // Anyway, here we implement <set> semantics for a
// <one-to-many> <bag>! // <one-to-many> <bag>!
@Override
@SuppressWarnings("unchecked")
public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) throws HibernateException { public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) throws HibernateException {
//if ( !persister.isOneToMany() ) throw new AssertionFailure("Not implemented for Bags"); final Type elementType = persister.getElementType();
Type elementType = persister.getElementType(); final ArrayList deletes = new ArrayList();
ArrayList deletes = new ArrayList(); final List sn = (List) getSnapshot();
List sn = (List) getSnapshot(); final Iterator olditer = sn.iterator();
Iterator olditer = sn.iterator();
int i=0; int i=0;
while ( olditer.hasNext() ) { while ( olditer.hasNext() ) {
Object old = olditer.next(); final Object old = olditer.next();
Iterator newiter = bag.iterator(); final Iterator newiter = bag.iterator();
boolean found = false; boolean found = false;
if ( bag.size()>i && elementType.isSame( old, bag.get(i++) ) ) { if ( bag.size()>i && elementType.isSame( old, bag.get( i++ ) ) ) {
//a shortcut if its location didn't change! //a shortcut if its location didn't change!
found = true; found = true;
} }
@ -202,104 +237,91 @@ public class PersistentBag extends AbstractPersistentCollection implements List
} }
} }
} }
if (!found) deletes.add(old); if ( !found ) {
deletes.add( old );
}
} }
return deletes.iterator(); return deletes.iterator();
} }
@Override
public boolean needsInserting(Object entry, int i, Type elemType) throws HibernateException { public boolean needsInserting(Object entry, int i, Type elemType) throws HibernateException {
//if ( !persister.isOneToMany() ) throw new AssertionFailure("Not implemented for Bags"); final List sn = (List) getSnapshot();
List sn = (List) getSnapshot(); if ( sn.size() > i && elemType.isSame( sn.get( i ), entry ) ) {
if ( sn.size()>i && elemType.isSame( sn.get(i), entry ) ) { //a shortcut if its location didn't change!
//a shortcut if its location didn't change!
return false; return false;
} }
else { else {
//search for it //search for it
//note that this code is incorrect for other than one-to-many //note that this code is incorrect for other than one-to-many
Iterator olditer = sn.iterator(); for ( Object old : sn ) {
while ( olditer.hasNext() ) { if ( elemType.isSame( old, entry ) ) {
Object old = olditer.next(); return false;
if ( elemType.isSame( old, entry ) ) return false; }
} }
return true; return true;
} }
} }
@Override
public boolean isRowUpdatePossible() { public boolean isRowUpdatePossible() {
return false; return false;
} }
@Override
public boolean needsUpdating(Object entry, int i, Type elemType) { public boolean needsUpdating(Object entry, int i, Type elemType) {
//if ( !persister.isOneToMany() ) throw new AssertionFailure("Not implemented for Bags");
return false; return false;
} }
/** @Override
* @see java.util.Collection#size()
*/
public int size() { public int size() {
return readSize() ? getCachedSize() : bag.size(); return readSize() ? getCachedSize() : bag.size();
} }
/** @Override
* @see java.util.Collection#isEmpty()
*/
public boolean isEmpty() { public boolean isEmpty() {
return readSize() ? getCachedSize()==0 : bag.isEmpty(); return readSize() ? getCachedSize()==0 : bag.isEmpty();
} }
/** @Override
* @see java.util.Collection#contains(Object) @SuppressWarnings("UnnecessaryUnboxing")
*/
public boolean contains(Object object) { public boolean contains(Object object) {
Boolean exists = readElementExistence(object); final Boolean exists = readElementExistence( object );
return exists==null ? return exists == null ? bag.contains( object ) : exists.booleanValue();
bag.contains(object) :
exists.booleanValue();
} }
/** @Override
* @see java.util.Collection#iterator()
*/
public Iterator iterator() { public Iterator iterator() {
read(); read();
return new IteratorProxy( bag.iterator() ); return new IteratorProxy( bag.iterator() );
} }
/** @Override
* @see java.util.Collection#toArray()
*/
public Object[] toArray() { public Object[] toArray() {
read(); read();
return bag.toArray(); return bag.toArray();
} }
/** @Override
* @see java.util.Collection#toArray(Object[])
*/
public Object[] toArray(Object[] a) { public Object[] toArray(Object[] a) {
read(); read();
return bag.toArray(a); return bag.toArray( a );
} }
/** @Override
* @see java.util.Collection#add(Object) @SuppressWarnings("unchecked")
*/
public boolean add(Object object) { public boolean add(Object object) {
if ( !isOperationQueueEnabled() ) { if ( !isOperationQueueEnabled() ) {
write(); write();
return bag.add(object); return bag.add( object );
} }
else { else {
queueOperation( new SimpleAdd(object) ); queueOperation( new SimpleAdd( object ) );
return true; return true;
} }
} }
/** @Override
* @see java.util.Collection#remove(Object)
*/
public boolean remove(Object o) { public boolean remove(Object o) {
initialize( true ); initialize( true );
if ( bag.remove( o ) ) { if ( bag.remove( o ) ) {
@ -311,35 +333,33 @@ public class PersistentBag extends AbstractPersistentCollection implements List
} }
} }
/** @Override
* @see java.util.Collection#containsAll(Collection) @SuppressWarnings("unchecked")
*/
public boolean containsAll(Collection c) { public boolean containsAll(Collection c) {
read(); read();
return bag.containsAll(c); return bag.containsAll( c );
} }
/** @Override
* @see java.util.Collection#addAll(Collection) @SuppressWarnings("unchecked")
*/
public boolean addAll(Collection values) { public boolean addAll(Collection values) {
if ( values.size()==0 ) return false; if ( values.size()==0 ) {
return false;
}
if ( !isOperationQueueEnabled() ) { if ( !isOperationQueueEnabled() ) {
write(); write();
return bag.addAll(values); return bag.addAll( values );
} }
else { else {
Iterator iter = values.iterator(); for ( Object value : values ) {
while ( iter.hasNext() ) { queueOperation( new SimpleAdd( value ) );
queueOperation( new SimpleAdd( iter.next() ) );
} }
return values.size()>0; return values.size()>0;
} }
} }
/** @Override
* @see java.util.Collection#removeAll(Collection) @SuppressWarnings("unchecked")
*/
public boolean removeAll(Collection c) { public boolean removeAll(Collection c) {
if ( c.size()>0 ) { if ( c.size()>0 ) {
initialize( true ); initialize( true );
@ -356,9 +376,8 @@ public class PersistentBag extends AbstractPersistentCollection implements List
} }
} }
/** @Override
* @see java.util.Collection#retainAll(Collection) @SuppressWarnings("unchecked")
*/
public boolean retainAll(Collection c) { public boolean retainAll(Collection c) {
initialize( true ); initialize( true );
if ( bag.retainAll( c ) ) { if ( bag.retainAll( c ) ) {
@ -370,9 +389,8 @@ public class PersistentBag extends AbstractPersistentCollection implements List
} }
} }
/** @Override
* @see java.util.Collection#clear() @SuppressWarnings("unchecked")
*/
public void clear() { public void clear() {
if ( isClearQueueEnabled() ) { if ( isClearQueueEnabled() ) {
queueOperation( new Clear() ); queueOperation( new Clear() );
@ -386,160 +404,161 @@ public class PersistentBag extends AbstractPersistentCollection implements List
} }
} }
@Override
public Object getIndex(Object entry, int i, CollectionPersister persister) { public Object getIndex(Object entry, int i, CollectionPersister persister) {
throw new UnsupportedOperationException("Bags don't have indexes"); throw new UnsupportedOperationException("Bags don't have indexes");
} }
@Override
public Object getElement(Object entry) { public Object getElement(Object entry) {
return entry; return entry;
} }
@Override
public Object getSnapshotElement(Object entry, int i) { public Object getSnapshotElement(Object entry, int i) {
List sn = (List) getSnapshot(); final List sn = (List) getSnapshot();
return sn.get(i); return sn.get( i );
} }
/**
* Count how many times the given object occurs in the elements
*
* @param o The object to check
*
* @return The number of occurences.
*/
@SuppressWarnings("UnusedDeclaration")
public int occurrences(Object o) { public int occurrences(Object o) {
read(); read();
Iterator iter = bag.iterator(); final Iterator itr = bag.iterator();
int result=0; int result = 0;
while ( iter.hasNext() ) { while ( itr.hasNext() ) {
if ( o.equals( iter.next() ) ) result++; if ( o.equals( itr.next() ) ) {
result++;
}
} }
return result; return result;
} }
// List OPERATIONS: // List OPERATIONS:
/** @Override
* @see java.util.List#add(int, Object) @SuppressWarnings("unchecked")
*/
public void add(int i, Object o) { public void add(int i, Object o) {
write(); write();
bag.add(i, o); bag.add( i, o );
} }
/** @Override
* @see java.util.List#addAll(int, Collection) @SuppressWarnings("unchecked")
*/
public boolean addAll(int i, Collection c) { public boolean addAll(int i, Collection c) {
if ( c.size()>0 ) { if ( c.size() > 0 ) {
write(); write();
return bag.addAll(i, c); return bag.addAll( i, c );
} }
else { else {
return false; return false;
} }
} }
/** @Override
* @see java.util.List#get(int) @SuppressWarnings("unchecked")
*/
public Object get(int i) { public Object get(int i) {
read(); read();
return bag.get(i); return bag.get( i );
} }
/** @Override
* @see java.util.List#indexOf(Object) @SuppressWarnings("unchecked")
*/
public int indexOf(Object o) { public int indexOf(Object o) {
read(); read();
return bag.indexOf(o); return bag.indexOf( o );
} }
/** @Override
* @see java.util.List#lastIndexOf(Object) @SuppressWarnings("unchecked")
*/
public int lastIndexOf(Object o) { public int lastIndexOf(Object o) {
read(); read();
return bag.lastIndexOf(o); return bag.lastIndexOf( o );
} }
/** @Override
* @see java.util.List#listIterator() @SuppressWarnings("unchecked")
*/
public ListIterator listIterator() { public ListIterator listIterator() {
read(); read();
return new ListIteratorProxy( bag.listIterator() ); return new ListIteratorProxy( bag.listIterator() );
} }
/** @Override
* @see java.util.List#listIterator(int) @SuppressWarnings("unchecked")
*/
public ListIterator listIterator(int i) { public ListIterator listIterator(int i) {
read(); read();
return new ListIteratorProxy( bag.listIterator(i) ); return new ListIteratorProxy( bag.listIterator( i ) );
} }
/** @Override
* @see java.util.List#remove(int) @SuppressWarnings("unchecked")
*/
public Object remove(int i) { public Object remove(int i) {
write(); write();
return bag.remove(i); return bag.remove( i );
} }
/** @Override
* @see java.util.List#set(int, Object) @SuppressWarnings("unchecked")
*/
public Object set(int i, Object o) { public Object set(int i, Object o) {
write(); write();
return bag.set(i, o); return bag.set( i, o );
} }
/** @Override
* @see java.util.List#subList(int, int) @SuppressWarnings("unchecked")
*/
public List subList(int start, int end) { public List subList(int start, int end) {
read(); read();
return new ListProxy( bag.subList(start, end) ); return new ListProxy( bag.subList( start, end ) );
} }
@Override
public boolean entryExists(Object entry, int i) {
return entry!=null;
}
@Override
public String toString() { public String toString() {
read(); read();
return bag.toString(); return bag.toString();
} }
/*public boolean equals(Object other) {
read();
return bag.equals(other);
}
public int hashCode(Object other) {
read();
return bag.hashCode();
}*/
public boolean entryExists(Object entry, int i) {
return entry!=null;
}
/** /**
* Bag does not respect the collection API and do an * Bag does not respect the collection API and do an
* JVM instance comparison to do the equals. * JVM instance comparison to do the equals.
* The semantic is broken not to have to initialize a * The semantic is broken not to have to initialize a
* collection for a simple equals() operation. * collection for a simple equals() operation.
* @see java.lang.Object#equals(java.lang.Object) * @see java.lang.Object#equals(java.lang.Object)
*
* {@inheritDoc}
*/ */
@Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
return super.equals(obj); return super.equals( obj );
} }
/** @Override
* @see java.lang.Object#hashCode()
*/
public int hashCode() { public int hashCode() {
return super.hashCode(); return super.hashCode();
} }
final class Clear implements DelayedOperation { final class Clear implements DelayedOperation {
@Override
public void operate() { public void operate() {
bag.clear(); bag.clear();
} }
@Override
public Object getAddedInstance() { public Object getAddedInstance() {
return null; return null;
} }
@Override
public Object getOrphan() { public Object getOrphan() {
throw new UnsupportedOperationException("queued clear cannot be used with orphan delete"); throw new UnsupportedOperationException("queued clear cannot be used with orphan delete");
} }
@ -551,12 +570,19 @@ public class PersistentBag extends AbstractPersistentCollection implements List
public SimpleAdd(Object value) { public SimpleAdd(Object value) {
this.value = value; this.value = value;
} }
@Override
@SuppressWarnings("unchecked")
public void operate() { public void operate() {
bag.add(value); bag.add( value );
} }
@Override
public Object getAddedInstance() { public Object getAddedInstance() {
return value; return value;
} }
@Override
public Object getOrphan() { public Object getOrphan() {
return null; return null;
} }

View File

@ -52,191 +52,227 @@ import org.hibernate.type.Type;
* <a href="https://hibernate.onjira.com/browse/HHH-7783">HHH-7783</a> for more information. * <a href="https://hibernate.onjira.com/browse/HHH-7783">HHH-7783</a> for more information.
*/ */
@Deprecated @Deprecated
@SuppressWarnings("UnusedDeclaration")
public class PersistentElementHolder extends AbstractPersistentCollection { public class PersistentElementHolder extends AbstractPersistentCollection {
protected Element element; protected Element element;
/**
* Constructs a PersistentElementHolder
*
* @param session The session
* @param element The DOM element
*/
@SuppressWarnings("UnusedDeclaration")
public PersistentElementHolder(SessionImplementor session, Element element) { public PersistentElementHolder(SessionImplementor session, Element element) {
super(session); super( session );
this.element = element; this.element = element;
setInitialized(); setInitialized();
} }
public Serializable getSnapshot(CollectionPersister persister) /**
throws HibernateException { * Constructs a PersistentElementHolder
*
* @param session The session
* @param persister The collection persister
* @param key The collection key (the fk value)
*/
@SuppressWarnings("UnusedDeclaration")
public PersistentElementHolder(SessionImplementor session, CollectionPersister persister, Serializable key) {
super( session );
final Element owner = (Element) session.getPersistenceContext().getCollectionOwner( key, persister );
if ( owner == null ) {
throw new AssertionFailure("null owner");
}
final String nodeName = persister.getNodeName();
if ( ".".equals( nodeName ) ) {
element = owner;
}
else {
element = owner.element( nodeName );
if ( element == null ) {
element = owner.addElement( nodeName );
}
}
}
@Override
@SuppressWarnings({"unchecked", "deprecation"})
public Serializable getSnapshot(CollectionPersister persister) throws HibernateException {
final Type elementType = persister.getElementType(); final Type elementType = persister.getElementType();
List elements = element.elements( persister.getElementNodeName() ); final List subElements = element.elements( persister.getElementNodeName() );
ArrayList snapshot = new ArrayList( elements.size() ); final ArrayList snapshot = new ArrayList( subElements.size() );
for ( int i=0; i<elements.size(); i++ ) { for ( Object subElement : subElements ) {
Element elem = (Element) elements.get(i); final Element element = (Element) subElement;
Object value = elementType.fromXMLNode( elem, persister.getFactory() ); final Object value = elementType.fromXMLNode( element, persister.getFactory() );
Object copy = elementType.deepCopy(value , persister.getFactory() ); final Object copy = elementType.deepCopy( value, persister.getFactory() );
snapshot.add(copy); snapshot.add( copy );
} }
return snapshot; return snapshot;
} }
@Override @Override
public Collection getOrphans(Serializable snapshot, String entityName) public Collection getOrphans(Serializable snapshot, String entityName) {
throws HibernateException {
//orphan delete not supported for EntityMode.DOM4J //orphan delete not supported for EntityMode.DOM4J
return Collections.EMPTY_LIST; return Collections.EMPTY_LIST;
} }
public PersistentElementHolder(SessionImplementor session, CollectionPersister persister, Serializable key) @Override
throws HibernateException {
super(session);
Element owner = (Element) session.getPersistenceContext().getCollectionOwner(key, persister);
if (owner==null) throw new AssertionFailure("null owner");
//element = XMLHelper.generateDom4jElement( persister.getNodeName() );
final String nodeName = persister.getNodeName();
if ( ".".equals(nodeName) ) {
element = owner;
}
else {
element = owner.element( nodeName );
if (element==null) element = owner.addElement( nodeName );
}
}
public boolean isWrapper(Object collection) { public boolean isWrapper(Object collection) {
return element==collection; return element == collection;
} }
@Override
@SuppressWarnings("deprecation")
public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException { public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException {
Type elementType = persister.getElementType(); final Type elementType = persister.getElementType();
final ArrayList snapshot = (ArrayList) getSnapshot();
ArrayList snapshot = (ArrayList) getSnapshot(); final List elements = element.elements( persister.getElementNodeName() );
List elements = element.elements( persister.getElementNodeName() ); if ( snapshot.size() != elements.size() ) {
if ( snapshot.size()!= elements.size() ) return false; return false;
}
for ( int i=0; i<snapshot.size(); i++ ) { for ( int i=0; i<snapshot.size(); i++ ) {
Object old = snapshot.get(i); final Object old = snapshot.get( i );
Element elem = (Element) elements.get(i); final Element elem = (Element) elements.get( i );
Object current = elementType.fromXMLNode( elem, persister.getFactory() ); final Object current = elementType.fromXMLNode( elem, persister.getFactory() );
if ( elementType.isDirty( old, current, getSession() ) ) return false; if ( elementType.isDirty( old, current, getSession() ) ) {
return false;
}
} }
return true; return true;
} }
@Override
public boolean isSnapshotEmpty(Serializable snapshot) { public boolean isSnapshotEmpty(Serializable snapshot) {
return ( (Collection) snapshot ).isEmpty(); return ( (Collection) snapshot ).isEmpty();
} }
@Override @Override
public boolean empty() { public boolean empty() {
return !element.elementIterator().hasNext(); return !element.elementIterator().hasNext();
} }
@Override
@SuppressWarnings("deprecation")
public Object readFrom(ResultSet rs, CollectionPersister persister, CollectionAliases descriptor, Object owner) public Object readFrom(ResultSet rs, CollectionPersister persister, CollectionAliases descriptor, Object owner)
throws HibernateException, SQLException { throws HibernateException, SQLException {
Object object = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() ); final Object object = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() );
final Type elementType = persister.getElementType(); final Type elementType = persister.getElementType();
Element subelement = element.addElement( persister.getElementNodeName() ); final Element subElement = element.addElement( persister.getElementNodeName() );
elementType.setToXMLNode( subelement, object, persister.getFactory() ); elementType.setToXMLNode( subElement, object, persister.getFactory() );
return object; return object;
} }
@Override
@SuppressWarnings({"deprecation", "unchecked"})
public Iterator entries(CollectionPersister persister) { public Iterator entries(CollectionPersister persister) {
final Type elementType = persister.getElementType(); final Type elementType = persister.getElementType();
List elements = element.elements( persister.getElementNodeName() ); final List subElements = element.elements( persister.getElementNodeName() );
int length = elements.size(); final int length = subElements.size();
List result = new ArrayList(length); final List result = new ArrayList(length);
for ( int i=0; i<length; i++ ) { for ( Object subElementO : subElements ) {
Element elem = (Element) elements.get(i); final Element subElement = (Element) subElementO;
Object object = elementType.fromXMLNode( elem, persister.getFactory() ); final Object object = elementType.fromXMLNode( subElement, persister.getFactory() );
result.add(object); result.add( object );
} }
return result.iterator(); return result.iterator();
} }
public void beforeInitialize(CollectionPersister persister, int anticipatedSize) {} @Override
public void beforeInitialize(CollectionPersister persister, int anticipatedSize) {
}
@Override @Override
public boolean isDirectlyAccessible() { public boolean isDirectlyAccessible() {
return true; return true;
} }
@Override
@SuppressWarnings("deprecation")
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner) public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner)
throws HibernateException { throws HibernateException {
final Type collectionElementType = persister.getElementType();
Type elementType = persister.getElementType(); final Serializable[] cachedSnapshot = (Serializable[]) disassembled;
Serializable[] cached = (Serializable[]) disassembled; for ( Serializable cachedItem : cachedSnapshot ) {
for ( int i=0; i<cached.length; i++ ) { final Object object = collectionElementType.assemble( cachedItem, getSession(), owner );
Object object = elementType.assemble( cached[i], getSession(), owner ); final Element subElement = element.addElement( persister.getElementNodeName() );
Element subelement = element.addElement( persister.getElementNodeName() ); collectionElementType.setToXMLNode( subElement, object, persister.getFactory() );
elementType.setToXMLNode( subelement, object, persister.getFactory() );
} }
} }
@Override
@SuppressWarnings("deprecation")
public Serializable disassemble(CollectionPersister persister) throws HibernateException { public Serializable disassemble(CollectionPersister persister) throws HibernateException {
final Type collectionElementType = persister.getElementType();
Type elementType = persister.getElementType(); final List elements = element.elements( persister.getElementNodeName() );
List elements = element.elements( persister.getElementNodeName() ); final int length = elements.size();
int length = elements.size(); final Serializable[] result = new Serializable[length];
Serializable[] result = new Serializable[length];
for ( int i=0; i<length; i++ ) { for ( int i=0; i<length; i++ ) {
Element elem = (Element) elements.get(i); final Element elem = (Element) elements.get( i );
Object object = elementType.fromXMLNode( elem, persister.getFactory() ); final Object object = collectionElementType.fromXMLNode( elem, persister.getFactory() );
result[i] = elementType.disassemble( object, getSession(), null ); result[i] = collectionElementType.disassemble( object, getSession(), null );
} }
return result; return result;
} }
@Override @Override
public Object getValue() { public Object getValue() {
return element; return element;
} }
public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) @Override
throws HibernateException { @SuppressWarnings({"unchecked", "deprecation"})
public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) throws HibernateException {
Type elementType = persister.getElementType(); final Type elementType = persister.getElementType();
ArrayList snapshot = (ArrayList) getSnapshot(); final ArrayList snapshot = (ArrayList) getSnapshot();
List elements = element.elements( persister.getElementNodeName() ); final List elements = element.elements( persister.getElementNodeName() );
ArrayList result = new ArrayList(); final ArrayList result = new ArrayList();
for ( int i=0; i<snapshot.size(); i++ ) { for ( int i=0; i<snapshot.size(); i++ ) {
Object old = snapshot.get(i); final Object old = snapshot.get( i );
if ( i >= elements.size() ) { if ( i >= elements.size() ) {
result.add(old); result.add( old );
} }
else { else {
Element elem = (Element) elements.get(i); final Element elem = (Element) elements.get( i );
Object object = elementType.fromXMLNode( elem, persister.getFactory() ); final Object object = elementType.fromXMLNode( elem, persister.getFactory() );
if ( elementType.isDirty( old, object, getSession() ) ) result.add(old); if ( elementType.isDirty( old, object, getSession() ) ) {
result.add( old );
}
} }
} }
return result.iterator(); return result.iterator();
} }
public boolean needsInserting(Object entry, int i, Type elementType) @Override
throws HibernateException { public boolean needsInserting(Object entry, int i, Type elementType) throws HibernateException {
ArrayList snapshot = (ArrayList) getSnapshot(); final ArrayList snapshot = (ArrayList) getSnapshot();
return i>=snapshot.size() || elementType.isDirty( snapshot.get(i), entry, getSession() ); return i >= snapshot.size()
|| elementType.isDirty( snapshot.get( i ), entry, getSession() );
} }
public boolean needsUpdating(Object entry, int i, Type elementType) @Override
throws HibernateException { public boolean needsUpdating(Object entry, int i, Type elementType) throws HibernateException {
return false; return false;
} }
@Override
public Object getIndex(Object entry, int i, CollectionPersister persister) { public Object getIndex(Object entry, int i, CollectionPersister persister) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
public Object getElement(Object entry) { public Object getElement(Object entry) {
return entry; return entry;
} }
@Override
public Object getSnapshotElement(Object entry, int i) { public Object getSnapshotElement(Object entry, int i) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
@Override
public boolean entryExists(Object entry, int i) { public boolean entryExists(Object entry, int i) {
return entry!=null; return entry!=null;
} }
} }

View File

@ -53,37 +53,53 @@ import org.hibernate.type.Type;
* @author Gavin King * @author Gavin King
*/ */
public class PersistentIdentifierBag extends AbstractPersistentCollection implements List { public class PersistentIdentifierBag extends AbstractPersistentCollection implements List {
protected List<Object> values;
protected Map<Integer, Object> identifiers;
protected List values; //element /**
protected Map identifiers; //index -> id * Constructs a PersistentIdentifierBag. This form needed for SOAP libraries, etc
*/
public PersistentIdentifierBag(SessionImplementor session) { @SuppressWarnings("UnusedDeclaration")
super(session); public PersistentIdentifierBag() {
} }
public PersistentIdentifierBag() {} //needed for SOAP libraries, etc /**
* Constructs a PersistentIdentifierBag.
*
* @param session The session
*/
public PersistentIdentifierBag(SessionImplementor session) {
super( session );
}
/**
* Constructs a PersistentIdentifierBag.
*
* @param session The session
* @param coll The base elements
*/
@SuppressWarnings("unchecked")
public PersistentIdentifierBag(SessionImplementor session, Collection coll) { public PersistentIdentifierBag(SessionImplementor session, Collection coll) {
super(session); super( session );
if (coll instanceof List) { if (coll instanceof List) {
values = (List) coll; values = (List<Object>) coll;
} }
else { else {
values = new ArrayList(); values = new ArrayList<Object>();
Iterator iter = coll.iterator(); for ( Object element : coll ) {
while ( iter.hasNext() ) { values.add( element );
values.add( iter.next() );
} }
} }
setInitialized(); setInitialized();
setDirectlyAccessible(true); setDirectlyAccessible( true );
identifiers = new HashMap(); identifiers = new HashMap<Integer, Object>();
} }
@Override
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner) public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner)
throws HibernateException { throws HibernateException {
Serializable[] array = (Serializable[]) disassembled; final Serializable[] array = (Serializable[]) disassembled;
int size = array.length; final int size = array.length;
beforeInitialize( persister, size ); beforeInitialize( persister, size );
for ( int i = 0; i < size; i+=2 ) { for ( int i = 0; i < size; i+=2 ) {
identifiers.put( identifiers.put(
@ -94,20 +110,24 @@ public class PersistentIdentifierBag extends AbstractPersistentCollection implem
} }
} }
@Override
public Object getIdentifier(Object entry, int i) { public Object getIdentifier(Object entry, int i) {
return identifiers.get( i ); return identifiers.get( i );
} }
@Override
public boolean isWrapper(Object collection) { public boolean isWrapper(Object collection) {
return values==collection; return values==collection;
} }
@Override
public boolean add(Object o) { public boolean add(Object o) {
write(); write();
values.add(o); values.add( o );
return true; return true;
} }
@Override
public void clear() { public void clear() {
initialize( true ); initialize( true );
if ( ! values.isEmpty() || ! identifiers.isEmpty() ) { if ( ! values.isEmpty() || ! identifiers.isEmpty() ) {
@ -117,31 +137,36 @@ public class PersistentIdentifierBag extends AbstractPersistentCollection implem
} }
} }
@Override
public boolean contains(Object o) { public boolean contains(Object o) {
read(); read();
return values.contains(o); return values.contains( o );
} }
@Override
public boolean containsAll(Collection c) { public boolean containsAll(Collection c) {
read(); read();
return values.containsAll(c); return values.containsAll( c );
} }
@Override
public boolean isEmpty() { public boolean isEmpty() {
return readSize() ? getCachedSize()==0 : values.isEmpty(); return readSize() ? getCachedSize()==0 : values.isEmpty();
} }
@Override
public Iterator iterator() { public Iterator iterator() {
read(); read();
return new IteratorProxy( values.iterator() ); return new IteratorProxy( values.iterator() );
} }
@Override
public boolean remove(Object o) { public boolean remove(Object o) {
initialize( true ); initialize( true );
int index = values.indexOf(o); final int index = values.indexOf( o );
if (index>=0) { if ( index >= 0 ) {
beforeRemove(index); beforeRemove( index );
values.remove(index); values.remove( index );
dirty(); dirty();
return true; return true;
} }
@ -150,12 +175,14 @@ public class PersistentIdentifierBag extends AbstractPersistentCollection implem
} }
} }
@Override
public boolean removeAll(Collection c) { public boolean removeAll(Collection c) {
if ( c.size() > 0 ) { if ( c.size() > 0 ) {
boolean result = false; boolean result = false;
Iterator iter = c.iterator(); for ( Object element : c ) {
while ( iter.hasNext() ) { if ( remove( element ) ) {
if ( remove( iter.next() ) ) result=true; result = true;
}
} }
return result; return result;
} }
@ -164,6 +191,7 @@ public class PersistentIdentifierBag extends AbstractPersistentCollection implem
} }
} }
@Override
public boolean retainAll(Collection c) { public boolean retainAll(Collection c) {
initialize( true ); initialize( true );
if ( values.retainAll( c ) ) { if ( values.retainAll( c ) ) {
@ -175,168 +203,210 @@ public class PersistentIdentifierBag extends AbstractPersistentCollection implem
} }
} }
@Override
public int size() { public int size() {
return readSize() ? getCachedSize() : values.size(); return readSize() ? getCachedSize() : values.size();
} }
@Override
public Object[] toArray() { public Object[] toArray() {
read(); read();
return values.toArray(); return values.toArray();
} }
@Override
public Object[] toArray(Object[] a) { public Object[] toArray(Object[] a) {
read(); read();
return values.toArray(a); return values.toArray( a );
} }
@Override
public void beforeInitialize(CollectionPersister persister, int anticipatedSize) { public void beforeInitialize(CollectionPersister persister, int anticipatedSize) {
identifiers = anticipatedSize <= 0 ? new HashMap() : new HashMap( anticipatedSize + 1 + (int)( anticipatedSize * .75f ), .75f ); identifiers = anticipatedSize <= 0
values = anticipatedSize <= 0 ? new ArrayList() : new ArrayList( anticipatedSize ); ? new HashMap<Integer, Object>()
: new HashMap<Integer, Object>( anticipatedSize + 1 + (int)( anticipatedSize * .75f ), .75f );
values = anticipatedSize <= 0
? new ArrayList<Object>()
: new ArrayList<Object>( anticipatedSize );
} }
@Override
public Serializable disassemble(CollectionPersister persister) public Serializable disassemble(CollectionPersister persister)
throws HibernateException { throws HibernateException {
Serializable[] result = new Serializable[ values.size() * 2 ]; final Serializable[] result = new Serializable[ values.size() * 2 ];
int i=0; int i = 0;
for (int j=0; j< values.size(); j++) { for ( int j=0; j< values.size(); j++ ) {
Object value = values.get(j); final Object value = values.get( j );
result[i++] = persister.getIdentifierType().disassemble( identifiers.get( j ), getSession(), null ); result[i++] = persister.getIdentifierType().disassemble( identifiers.get( j ), getSession(), null );
result[i++] = persister.getElementType().disassemble( value, getSession(), null ); result[i++] = persister.getElementType().disassemble( value, getSession(), null );
} }
return result; return result;
} }
@Override
public boolean empty() { public boolean empty() {
return values.isEmpty(); return values.isEmpty();
} }
@Override
public Iterator entries(CollectionPersister persister) { public Iterator entries(CollectionPersister persister) {
return values.iterator(); return values.iterator();
} }
@Override
public boolean entryExists(Object entry, int i) { public boolean entryExists(Object entry, int i) {
return entry!=null; return entry!=null;
} }
@Override
public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException { public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException {
Type elementType = persister.getElementType(); final Type elementType = persister.getElementType();
Map snap = (Map) getSnapshot(); final Map snap = (Map) getSnapshot();
if ( snap.size()!= values.size() ) return false; if ( snap.size()!= values.size() ) {
return false;
}
for ( int i=0; i<values.size(); i++ ) { for ( int i=0; i<values.size(); i++ ) {
Object value = values.get(i); final Object value = values.get( i );
Object id = identifiers.get( i ); final Object id = identifiers.get( i );
if (id==null) return false; if ( id == null ) {
Object old = snap.get(id); return false;
if ( elementType.isDirty( old, value, getSession() ) ) return false; }
final Object old = snap.get( id );
if ( elementType.isDirty( old, value, getSession() ) ) {
return false;
}
} }
return true; return true;
} }
@Override
public boolean isSnapshotEmpty(Serializable snapshot) { public boolean isSnapshotEmpty(Serializable snapshot) {
return ( (Map) snapshot ).isEmpty(); return ( (Map) snapshot ).isEmpty();
} }
@Override
@SuppressWarnings("unchecked")
public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) throws HibernateException { public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) throws HibernateException {
Map snap = (Map) getSnapshot(); final Map snap = (Map) getSnapshot();
List deletes = new ArrayList( snap.keySet() ); final List deletes = new ArrayList( snap.keySet() );
for ( int i=0; i<values.size(); i++ ) { for ( int i=0; i<values.size(); i++ ) {
if ( values.get(i)!=null ) deletes.remove( identifiers.get( i ) ); if ( values.get( i ) != null ) {
deletes.remove( identifiers.get( i ) );
}
} }
return deletes.iterator(); return deletes.iterator();
} }
@Override
public Object getIndex(Object entry, int i, CollectionPersister persister) { public Object getIndex(Object entry, int i, CollectionPersister persister) {
throw new UnsupportedOperationException("Bags don't have indexes"); throw new UnsupportedOperationException("Bags don't have indexes");
} }
@Override
public Object getElement(Object entry) { public Object getElement(Object entry) {
return entry; return entry;
} }
@Override
public Object getSnapshotElement(Object entry, int i) { public Object getSnapshotElement(Object entry, int i) {
Map snap = (Map) getSnapshot(); final Map snap = (Map) getSnapshot();
Object id = identifiers.get( i ); final Object id = identifiers.get( i );
return snap.get(id); return snap.get( id );
} }
@Override
public boolean needsInserting(Object entry, int i, Type elemType) public boolean needsInserting(Object entry, int i, Type elemType)
throws HibernateException { throws HibernateException {
final Map snap = (Map) getSnapshot();
Map snap = (Map) getSnapshot(); final Object id = identifiers.get( i );
Object id = identifiers.get( i ); return entry != null
return entry!=null && ( id==null || snap.get(id)==null ); && ( id==null || snap.get( id )==null );
} }
@Override
public boolean needsUpdating(Object entry, int i, Type elemType) throws HibernateException { public boolean needsUpdating(Object entry, int i, Type elemType) throws HibernateException {
if ( entry == null ) {
return false;
}
if (entry==null) return false; final Map snap = (Map) getSnapshot();
Map snap = (Map) getSnapshot(); final Object id = identifiers.get( i );
Object id = identifiers.get( i ); if ( id == null ) {
if (id==null) return false; return false;
Object old = snap.get(id); }
return old!=null && elemType.isDirty( old, entry, getSession() );
final Object old = snap.get( id );
return old != null && elemType.isDirty( old, entry, getSession() );
} }
@Override
public Object readFrom( public Object readFrom(
ResultSet rs, ResultSet rs,
CollectionPersister persister, CollectionPersister persister,
CollectionAliases descriptor, CollectionAliases descriptor,
Object owner) Object owner) throws HibernateException, SQLException {
throws HibernateException, SQLException { final Object element = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() );
final Object old = identifiers.put(
Object element = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() );
Object old = identifiers.put(
values.size(), values.size(),
persister.readIdentifier( rs, descriptor.getSuffixedIdentifierAlias(), getSession() ) persister.readIdentifier( rs, descriptor.getSuffixedIdentifierAlias(), getSession() )
); );
if ( old==null ) values.add(element); //maintain correct duplication if loaded in a cartesian product
if ( old == null ) {
//maintain correct duplication if loaded in a cartesian product
values.add( element );
}
return element; return element;
} }
@Override
@SuppressWarnings("unchecked")
public Serializable getSnapshot(CollectionPersister persister) throws HibernateException { public Serializable getSnapshot(CollectionPersister persister) throws HibernateException {
HashMap map = new HashMap( values.size() ); final HashMap map = new HashMap( values.size() );
Iterator iter = values.iterator(); final Iterator iter = values.iterator();
int i=0; int i=0;
while ( iter.hasNext() ) { while ( iter.hasNext() ) {
Object value = iter.next(); final Object value = iter.next();
map.put( map.put(
identifiers.get( i++ ), identifiers.get( i++ ),
persister.getElementType().deepCopy(value, persister.getFactory()) persister.getElementType().deepCopy( value, persister.getFactory() )
); );
} }
return map; return map;
} }
@Override
public Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException { public Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException {
Map sn = (Map) snapshot; final Map sn = (Map) snapshot;
return getOrphans( sn.values(), values, entityName, getSession() ); return getOrphans( sn.values(), values, entityName, getSession() );
} }
@Override
public void preInsert(CollectionPersister persister) throws HibernateException { public void preInsert(CollectionPersister persister) throws HibernateException {
Iterator iter = values.iterator(); final Iterator itr = values.iterator();
int i=0; int i = 0;
while ( iter.hasNext() ) { while ( itr.hasNext() ) {
Object entry = iter.next(); final Object entry = itr.next();
Integer loc = i++; final Integer loc = i++;
if ( !identifiers.containsKey(loc) ) { //TODO: native ids if ( !identifiers.containsKey( loc ) ) {
Serializable id = persister.getIdentifierGenerator().generate( getSession(), entry ); //TODO: native ids
identifiers.put(loc, id); final Serializable id = persister.getIdentifierGenerator().generate( getSession(), entry );
identifiers.put( loc, id );
} }
} }
} }
@Override
public void add(int index, Object element) { public void add(int index, Object element) {
write(); write();
beforeAdd(index); beforeAdd( index );
values.add(index, element); values.add( index, element );
} }
@Override
public boolean addAll(int index, Collection c) { public boolean addAll(int index, Collection c) {
if ( c.size() > 0 ) { if ( c.size() > 0 ) {
Iterator iter = c.iterator(); for ( Object element : c ) {
while ( iter.hasNext() ) { add( index++, element );
add( index++, iter.next() );
} }
return true; return true;
} }
@ -345,42 +415,47 @@ public class PersistentIdentifierBag extends AbstractPersistentCollection implem
} }
} }
@Override
public Object get(int index) { public Object get(int index) {
read(); read();
return values.get(index); return values.get( index );
} }
@Override
public int indexOf(Object o) { public int indexOf(Object o) {
read(); read();
return values.indexOf(o); return values.indexOf( o );
} }
@Override
public int lastIndexOf(Object o) { public int lastIndexOf(Object o) {
read(); read();
return values.lastIndexOf(o); return values.lastIndexOf( o );
} }
@Override
public ListIterator listIterator() { public ListIterator listIterator() {
read(); read();
return new ListIteratorProxy( values.listIterator() ); return new ListIteratorProxy( values.listIterator() );
} }
@Override
public ListIterator listIterator(int index) { public ListIterator listIterator(int index) {
read(); read();
return new ListIteratorProxy( values.listIterator(index) ); return new ListIteratorProxy( values.listIterator( index ) );
} }
private void beforeRemove(int index) { private void beforeRemove(int index) {
Object removedId = identifiers.get( index ); final Object removedId = identifiers.get( index );
int last = values.size()-1; final int last = values.size()-1;
for ( int i=index; i<last; i++ ) { for ( int i=index; i<last; i++ ) {
Object id = identifiers.get( i+1 ); final Object id = identifiers.get( i+1 );
if ( id==null ) { if ( id == null ) {
identifiers.remove( i ); identifiers.remove( i );
} }
else { else {
identifiers.put( i, id ); identifiers.put( i, id );
} }
} }
identifiers.put( last, removedId ); identifiers.put( last, removedId );
} }
@ -392,37 +467,41 @@ public class PersistentIdentifierBag extends AbstractPersistentCollection implem
identifiers.remove( index ); identifiers.remove( index );
} }
@Override
public Object remove(int index) { public Object remove(int index) {
write(); write();
beforeRemove(index); beforeRemove( index );
return values.remove(index); return values.remove( index );
} }
@Override
public Object set(int index, Object element) { public Object set(int index, Object element) {
write(); write();
return values.set(index, element); return values.set( index, element );
} }
@Override
public List subList(int fromIndex, int toIndex) { public List subList(int fromIndex, int toIndex) {
read(); read();
return new ListProxy( values.subList(fromIndex, toIndex) ); return new ListProxy( values.subList( fromIndex, toIndex ) );
} }
@Override
public boolean addAll(Collection c) { public boolean addAll(Collection c) {
if ( c.size()> 0 ) { if ( c.size()> 0 ) {
write(); write();
return values.addAll(c); return values.addAll( c );
} }
else { else {
return false; return false;
} }
} }
@Override
public void afterRowInsert( public void afterRowInsert(
CollectionPersister persister, CollectionPersister persister,
Object entry, Object entry,
int i) int i) throws HibernateException {
throws HibernateException {
//TODO: if we are using identity columns, fetch the identifier //TODO: if we are using identity columns, fetch the identifier
} }

View File

@ -57,16 +57,52 @@ import org.hibernate.type.XmlRepresentableType;
@Deprecated @Deprecated
public abstract class PersistentIndexedElementHolder extends AbstractPersistentCollection { public abstract class PersistentIndexedElementHolder extends AbstractPersistentCollection {
protected Element element; protected Element element;
/**
* Constructs a PersistentIndexedElementHolder.
*
* @param session The session
* @param element The DOM element being wrapped
*/
public PersistentIndexedElementHolder(SessionImplementor session, Element element) { public PersistentIndexedElementHolder(SessionImplementor session, Element element) {
super(session); super( session );
this.element = element; this.element = element;
setInitialized(); setInitialized();
} }
/**
* Constructs a PersistentIndexedElementHolder.
*
* @param session The session
* @param persister The collection persister
* @param key The collection key (fk value)@throws HibernateException
*/
public PersistentIndexedElementHolder(SessionImplementor session, CollectionPersister persister, Serializable key) {
super( session );
final Element owner = (Element) session.getPersistenceContext().getCollectionOwner( key, persister );
if ( owner == null ) {
throw new AssertionFailure( "null owner" );
}
final String nodeName = persister.getNodeName();
if ( ".".equals( nodeName ) ) {
element = owner;
}
else {
element = owner.element( nodeName );
if ( element == null ) {
element = owner.addElement( nodeName );
}
}
}
/**
* A struct representing the index/value pair.
*/
public static final class IndexedValue { public static final class IndexedValue {
String index; final String index;
Object value; final Object value;
IndexedValue(String index, Object value) { IndexedValue(String index, Object value) {
this.index = index; this.index = index;
this.value = value; this.value = value;
@ -74,182 +110,189 @@ public abstract class PersistentIndexedElementHolder extends AbstractPersistentC
} }
protected static String getIndex(Element element, String indexNodeName, int i) { protected static String getIndex(Element element, String indexNodeName, int i) {
if (indexNodeName!=null) { if ( indexNodeName != null ) {
return element.attributeValue(indexNodeName); return element.attributeValue( indexNodeName );
} }
else { else {
return Integer.toString(i); return Integer.toString( i );
} }
} }
protected static void setIndex(Element element, String indexNodeName, String index) { protected static void setIndex(Element element, String indexNodeName, String index) {
if (indexNodeName!=null) element.addAttribute(indexNodeName, index); if ( indexNodeName != null ) {
element.addAttribute( indexNodeName, index );
}
} }
protected static String getIndexAttributeName(CollectionPersister persister) { protected static String getIndexAttributeName(CollectionPersister persister) {
String node = persister.getIndexNodeName(); final String node = persister.getIndexNodeName();
return node==null ? null : node.substring(1); return node == null ? null : node.substring( 1 );
} }
public Serializable getSnapshot(CollectionPersister persister) @Override
throws HibernateException { @SuppressWarnings({"unchecked", "deprecation"})
public Serializable getSnapshot(CollectionPersister persister) throws HibernateException {
final Type elementType = persister.getElementType(); final Type elementType = persister.getElementType();
String indexNode = getIndexAttributeName(persister); final String indexNode = getIndexAttributeName( persister );
List elements = element.elements( persister.getElementNodeName() ); final List elements = element.elements( persister.getElementNodeName() );
HashMap snapshot = new HashMap( elements.size() ); final HashMap snapshot = new HashMap( elements.size() );
for ( int i=0; i<elements.size(); i++ ) { for ( int i=0; i<elements.size(); i++ ) {
Element elem = (Element) elements.get(i); final Element elem = (Element) elements.get( i );
Object value = elementType.fromXMLNode( elem, persister.getFactory() ); final Object value = elementType.fromXMLNode( elem, persister.getFactory() );
Object copy = elementType.deepCopy( value, persister.getFactory() ); final Object copy = elementType.deepCopy( value, persister.getFactory() );
snapshot.put( getIndex(elem, indexNode, i), copy ); snapshot.put( getIndex( elem, indexNode, i ), copy );
} }
return snapshot; return snapshot;
} }
public Collection getOrphans(Serializable snapshot, String entityName) @Override
throws HibernateException { public Collection getOrphans(Serializable snapshot, String entityName) {
//orphan delete not supported for EntityMode.DOM4J //orphan delete not supported for EntityMode.DOM4J
return Collections.EMPTY_LIST; return Collections.EMPTY_LIST;
} }
public PersistentIndexedElementHolder(SessionImplementor session, CollectionPersister persister, Serializable key) @Override
throws HibernateException {
super(session);
Element owner = (Element) session.getPersistenceContext().getCollectionOwner(key, persister);
if (owner==null) throw new AssertionFailure("null owner");
//element = XMLHelper.generateDom4jElement( persister.getNodeName() );
final String nodeName = persister.getNodeName();
if ( ".".equals(nodeName) ) {
element = owner;
}
else {
element = owner.element( nodeName );
if (element==null) element = owner.addElement( nodeName );
}
}
public boolean isWrapper(Object collection) { public boolean isWrapper(Object collection) {
return element==collection; return element==collection;
} }
@Override
@SuppressWarnings("deprecation")
public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException { public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException {
Type elementType = persister.getElementType(); final Type elementType = persister.getElementType();
String indexNode = getIndexAttributeName(persister); final String indexNode = getIndexAttributeName( persister );
HashMap snapshot = (HashMap) getSnapshot(); final HashMap snapshot = (HashMap) getSnapshot();
List elements = element.elements( persister.getElementNodeName() ); final List elements = element.elements( persister.getElementNodeName() );
if ( snapshot.size()!= elements.size() ) return false;
if ( snapshot.size() != elements.size() ) {
return false;
}
for ( int i=0; i<snapshot.size(); i++ ) { for ( int i=0; i<snapshot.size(); i++ ) {
Element elem = (Element) elements.get(i); final Element elem = (Element) elements.get( i );
Object old = snapshot.get( getIndex(elem, indexNode, i) ); final Object old = snapshot.get( getIndex( elem, indexNode, i ) );
Object current = elementType.fromXMLNode( elem, persister.getFactory() ); final Object current = elementType.fromXMLNode( elem, persister.getFactory() );
if ( elementType.isDirty( old, current, getSession() ) ) return false; if ( elementType.isDirty( old, current, getSession() ) ) {
return false;
}
} }
return true; return true;
} }
@Override
public boolean isSnapshotEmpty(Serializable snapshot) { public boolean isSnapshotEmpty(Serializable snapshot) {
return ( (HashMap) snapshot ).isEmpty(); return ( (HashMap) snapshot ).isEmpty();
} }
@Override
public boolean empty() { public boolean empty() {
return !element.elementIterator().hasNext(); return !element.elementIterator().hasNext();
} }
@Override
@SuppressWarnings({"deprecation", "unchecked"})
public Object readFrom(ResultSet rs, CollectionPersister persister, CollectionAliases descriptor, Object owner) public Object readFrom(ResultSet rs, CollectionPersister persister, CollectionAliases descriptor, Object owner)
throws HibernateException, SQLException { throws HibernateException, SQLException {
Object object = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() ); final Object object = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() );
final Type elementType = persister.getElementType(); final Type elementType = persister.getElementType();
final SessionFactoryImplementor factory = persister.getFactory(); final SessionFactoryImplementor factory = persister.getFactory();
String indexNode = getIndexAttributeName(persister); final String indexNode = getIndexAttributeName( persister );
Element elem = element.addElement( persister.getElementNodeName() ); final Element elem = element.addElement( persister.getElementNodeName() );
elementType.setToXMLNode( elem, object, factory ); elementType.setToXMLNode( elem, object, factory );
final Type indexType = persister.getIndexType(); final Type indexType = persister.getIndexType();
final Object indexValue = persister.readIndex( rs, descriptor.getSuffixedIndexAliases(), getSession() ); final Object indexValue = persister.readIndex( rs, descriptor.getSuffixedIndexAliases(), getSession() );
final String index = ( (XmlRepresentableType) indexType ).toXMLString( indexValue, factory ); final String index = ( (XmlRepresentableType) indexType ).toXMLString( indexValue, factory );
setIndex(elem, indexNode, index); setIndex( elem, indexNode, index );
return object; return object;
} }
@Override
@SuppressWarnings({"deprecation", "unchecked"})
public Iterator entries(CollectionPersister persister) { public Iterator entries(CollectionPersister persister) {
final Type elementType = persister.getElementType(); final Type elementType = persister.getElementType();
String indexNode = getIndexAttributeName(persister); final String indexNode = getIndexAttributeName( persister );
List elements = element.elements( persister.getElementNodeName() ); final List elements = element.elements( persister.getElementNodeName() );
int length = elements.size(); final int length = elements.size();
List result = new ArrayList(length); final List result = new ArrayList( length );
for ( int i=0; i<length; i++ ) { for ( int i=0; i<length; i++ ) {
Element elem = (Element) elements.get(i); final Element elem = (Element) elements.get( i );
Object object = elementType.fromXMLNode( elem, persister.getFactory() ); final Object object = elementType.fromXMLNode( elem, persister.getFactory() );
result.add( new IndexedValue( getIndex(elem, indexNode, i), object ) ); result.add( new IndexedValue( getIndex( elem, indexNode, i ), object ) );
} }
return result.iterator(); return result.iterator();
} }
public void beforeInitialize(CollectionPersister persister, int anticipatedSize) {} @Override
public void beforeInitialize(CollectionPersister persister, int anticipatedSize) {
}
@Override
public boolean isDirectlyAccessible() { public boolean isDirectlyAccessible() {
return true; return true;
} }
@Override
public Object getValue() { public Object getValue() {
return element; return element;
} }
public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) @Override
throws HibernateException { @SuppressWarnings({"deprecation", "unchecked"})
public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) throws HibernateException {
final Type indexType = persister.getIndexType(); final Type indexType = persister.getIndexType();
HashMap snapshot = (HashMap) getSnapshot(); final HashMap snapshot = (HashMap) getSnapshot();
HashMap deletes = (HashMap) snapshot.clone(); final HashMap deletes = (HashMap) snapshot.clone();
deletes.keySet().removeAll( ( (HashMap) getSnapshot(persister) ).keySet() ); deletes.keySet().removeAll( ( (HashMap) getSnapshot( persister ) ).keySet() );
ArrayList deleteList = new ArrayList( deletes.size() ); final ArrayList deleteList = new ArrayList( deletes.size() );
for ( Object o : deletes.entrySet() ) { for ( Object o : deletes.entrySet() ) {
Map.Entry me = (Map.Entry) o; final Map.Entry me = (Map.Entry) o;
final Object object = indexIsFormula ? final Object object = indexIsFormula
me.getValue() : ? me.getValue()
( (XmlRepresentableType) indexType ).fromXMLString( (String) me.getKey(), persister.getFactory() ); : ( (XmlRepresentableType) indexType ).fromXMLString( (String) me.getKey(), persister.getFactory() );
if ( object != null ) { if ( object != null ) {
deleteList.add( object ); deleteList.add( object );
} }
} }
return deleteList.iterator(); return deleteList.iterator();
} }
public boolean needsInserting(Object entry, int i, Type elementType) @Override
throws HibernateException { public boolean needsInserting(Object entry, int i, Type elementType) throws HibernateException {
HashMap snapshot = (HashMap) getSnapshot(); final HashMap snapshot = (HashMap) getSnapshot();
IndexedValue iv = (IndexedValue) entry; final IndexedValue iv = (IndexedValue) entry;
return iv.value!=null && snapshot.get( iv.index )==null; return iv.value!=null && snapshot.get( iv.index )==null;
} }
public boolean needsUpdating(Object entry, int i, Type elementType) @Override
throws HibernateException { public boolean needsUpdating(Object entry, int i, Type elementType) throws HibernateException {
HashMap snapshot = (HashMap) getSnapshot(); final HashMap snapshot = (HashMap) getSnapshot();
IndexedValue iv = (IndexedValue) entry; final IndexedValue iv = (IndexedValue) entry;
Object old = snapshot.get( iv.index ); final Object old = snapshot.get( iv.index );
return old!=null && elementType.isDirty( old, iv.value, getSession() ); return old!=null && elementType.isDirty( old, iv.value, getSession() );
} }
@Override
@SuppressWarnings("deprecation")
public Object getIndex(Object entry, int i, CollectionPersister persister) { public Object getIndex(Object entry, int i, CollectionPersister persister) {
String index = ( (IndexedValue) entry ).index; final String index = ( (IndexedValue) entry ).index;
final Type indexType = persister.getIndexType(); final Type indexType = persister.getIndexType();
return ( (XmlRepresentableType) indexType ).fromXMLString( index, persister.getFactory() ); return ( (XmlRepresentableType) indexType ).fromXMLString( index, persister.getFactory() );
} }
@Override
public Object getElement(Object entry) { public Object getElement(Object entry) {
return ( (IndexedValue) entry ).value; return ( (IndexedValue) entry ).value;
} }
@Override
public Object getSnapshotElement(Object entry, int i) { public Object getSnapshotElement(Object entry, int i) {
return ( (HashMap) getSnapshot() ).get( ( (IndexedValue) entry ).index ); return ( (HashMap) getSnapshot() ).get( ( (IndexedValue) entry ).index );
} }
@Override
public boolean entryExists(Object entry, int i) { public boolean entryExists(Object entry, int i) {
return entry!=null; return entry!=null;
} }

View File

@ -32,7 +32,6 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.ListIterator; import java.util.ListIterator;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.loader.CollectionAliases; import org.hibernate.loader.CollectionAliases;
@ -49,12 +48,40 @@ import org.hibernate.type.Type;
public class PersistentList extends AbstractPersistentCollection implements List { public class PersistentList extends AbstractPersistentCollection implements List {
protected List list; protected List list;
/**
* Constructs a PersistentList. This form needed for SOAP libraries, etc
*/
public PersistentList() {
}
/**
* Constructs a PersistentList.
*
* @param session The session
*/
public PersistentList(SessionImplementor session) {
super( session );
}
/**
* Constructs a PersistentList.
*
* @param session The session
* @param list The raw list
*/
public PersistentList(SessionImplementor session, List list) {
super( session );
this.list = list;
setInitialized();
setDirectlyAccessible( true );
}
@Override @Override
@SuppressWarnings( {"unchecked"}) @SuppressWarnings( {"unchecked"})
public Serializable getSnapshot(CollectionPersister persister) throws HibernateException { public Serializable getSnapshot(CollectionPersister persister) throws HibernateException {
ArrayList clonedList = new ArrayList( list.size() ); final ArrayList clonedList = new ArrayList( list.size() );
for ( Object element : list ) { for ( Object element : list ) {
Object deepCopy = persister.getElementType().deepCopy( element, persister.getFactory() ); final Object deepCopy = persister.getElementType().deepCopy( element, persister.getFactory() );
clonedList.add( deepCopy ); clonedList.add( deepCopy );
} }
return clonedList; return clonedList;
@ -62,19 +89,23 @@ public class PersistentList extends AbstractPersistentCollection implements List
@Override @Override
public Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException { public Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException {
List sn = (List) snapshot; final List sn = (List) snapshot;
return getOrphans( sn, list, entityName, getSession() ); return getOrphans( sn, list, entityName, getSession() );
} }
@Override @Override
public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException { public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException {
Type elementType = persister.getElementType(); final Type elementType = persister.getElementType();
List sn = (List) getSnapshot(); final List sn = (List) getSnapshot();
if ( sn.size()!=this.list.size() ) return false; if ( sn.size()!=this.list.size() ) {
Iterator iter = list.iterator(); return false;
Iterator sniter = sn.iterator(); }
while ( iter.hasNext() ) { final Iterator itr = list.iterator();
if ( elementType.isDirty( iter.next(), sniter.next(), getSession() ) ) return false; final Iterator snapshotItr = sn.iterator();
while ( itr.hasNext() ) {
if ( elementType.isDirty( itr.next(), snapshotItr.next(), getSession() ) ) {
return false;
}
} }
return true; return true;
} }
@ -84,94 +115,70 @@ public class PersistentList extends AbstractPersistentCollection implements List
return ( (Collection) snapshot ).isEmpty(); return ( (Collection) snapshot ).isEmpty();
} }
public PersistentList(SessionImplementor session) { @Override
super(session);
}
public PersistentList(SessionImplementor session, List list) {
super(session);
this.list = list;
setInitialized();
setDirectlyAccessible(true);
}
public void beforeInitialize(CollectionPersister persister, int anticipatedSize) { public void beforeInitialize(CollectionPersister persister, int anticipatedSize) {
this.list = ( List ) persister.getCollectionType().instantiate( anticipatedSize ); this.list = (List) persister.getCollectionType().instantiate( anticipatedSize );
} }
@Override
public boolean isWrapper(Object collection) { public boolean isWrapper(Object collection) {
return list==collection; return list==collection;
} }
public PersistentList() {} //needed for SOAP libraries, etc @Override
/**
* @see java.util.List#size()
*/
public int size() { public int size() {
return readSize() ? getCachedSize() : list.size(); return readSize() ? getCachedSize() : list.size();
} }
/** @Override
* @see java.util.List#isEmpty()
*/
public boolean isEmpty() { public boolean isEmpty() {
return readSize() ? getCachedSize()==0 : list.isEmpty(); return readSize() ? getCachedSize()==0 : list.isEmpty();
} }
/** @Override
* @see java.util.List#contains(Object) @SuppressWarnings("UnnecessaryUnboxing")
*/
public boolean contains(Object object) { public boolean contains(Object object) {
Boolean exists = readElementExistence(object); final Boolean exists = readElementExistence( object );
return exists==null ? return exists == null
list.contains(object) : ? list.contains( object )
exists.booleanValue(); : exists.booleanValue();
} }
/** @Override
* @see java.util.List#iterator()
*/
public Iterator iterator() { public Iterator iterator() {
read(); read();
return new IteratorProxy( list.iterator() ); return new IteratorProxy( list.iterator() );
} }
/** @Override
* @see java.util.List#toArray()
*/
public Object[] toArray() { public Object[] toArray() {
read(); read();
return list.toArray(); return list.toArray();
} }
/** @Override
* @see java.util.List#toArray(Object[])
*/
public Object[] toArray(Object[] array) { public Object[] toArray(Object[] array) {
read(); read();
return list.toArray(array); return list.toArray( array );
} }
/** @Override
* @see java.util.List#add(Object) @SuppressWarnings("unchecked")
*/
public boolean add(Object object) { public boolean add(Object object) {
if ( !isOperationQueueEnabled() ) { if ( !isOperationQueueEnabled() ) {
write(); write();
return list.add(object); return list.add( object );
} }
else { else {
queueOperation( new SimpleAdd(object) ); queueOperation( new SimpleAdd( object ) );
return true; return true;
} }
} }
/** @Override
* @see java.util.List#remove(Object) @SuppressWarnings("UnnecessaryUnboxing")
*/
public boolean remove(Object value) { public boolean remove(Object value) {
Boolean exists = isPutQueueEnabled() ? readElementExistence(value) : null; final Boolean exists = isPutQueueEnabled() ? readElementExistence( value ) : null;
if ( exists == null ) { if ( exists == null ) {
initialize( true ); initialize( true );
if ( list.remove( value ) ) { if ( list.remove( value ) ) {
@ -183,7 +190,7 @@ public class PersistentList extends AbstractPersistentCollection implements List
} }
} }
else if ( exists.booleanValue() ) { else if ( exists.booleanValue() ) {
queueOperation( new SimpleRemove(value) ); queueOperation( new SimpleRemove( value ) );
return true; return true;
} }
else { else {
@ -191,50 +198,45 @@ public class PersistentList extends AbstractPersistentCollection implements List
} }
} }
/** @Override
* @see java.util.List#containsAll(Collection) @SuppressWarnings("unchecked")
*/
public boolean containsAll(Collection coll) { public boolean containsAll(Collection coll) {
read(); read();
return list.containsAll(coll); return list.containsAll( coll );
} }
/** @Override
* @see java.util.List#addAll(Collection) @SuppressWarnings("unchecked")
*/
public boolean addAll(Collection values) { public boolean addAll(Collection values) {
if ( values.size()==0 ) { if ( values.size()==0 ) {
return false; return false;
} }
if ( !isOperationQueueEnabled() ) { if ( !isOperationQueueEnabled() ) {
write(); write();
return list.addAll(values); return list.addAll( values );
} }
else { else {
Iterator iter = values.iterator(); for ( Object value : values ) {
while ( iter.hasNext() ) { queueOperation( new SimpleAdd( value ) );
queueOperation( new SimpleAdd( iter.next() ) );
} }
return values.size()>0; return values.size()>0;
} }
} }
/** @Override
* @see java.util.List#addAll(int, Collection) @SuppressWarnings("unchecked")
*/
public boolean addAll(int index, Collection coll) { public boolean addAll(int index, Collection coll) {
if ( coll.size()>0 ) { if ( coll.size()>0 ) {
write(); write();
return list.addAll(index, coll); return list.addAll( index, coll );
} }
else { else {
return false; return false;
} }
} }
/** @Override
* @see java.util.List#removeAll(Collection) @SuppressWarnings("unchecked")
*/
public boolean removeAll(Collection coll) { public boolean removeAll(Collection coll) {
if ( coll.size()>0 ) { if ( coll.size()>0 ) {
initialize( true ); initialize( true );
@ -251,9 +253,8 @@ public class PersistentList extends AbstractPersistentCollection implements List
} }
} }
/** @Override
* @see java.util.List#retainAll(Collection) @SuppressWarnings("unchecked")
*/
public boolean retainAll(Collection coll) { public boolean retainAll(Collection coll) {
initialize( true ); initialize( true );
if ( list.retainAll( coll ) ) { if ( list.retainAll( coll ) ) {
@ -265,9 +266,8 @@ public class PersistentList extends AbstractPersistentCollection implements List
} }
} }
/** @Override
* @see java.util.List#clear() @SuppressWarnings("unchecked")
*/
public void clear() { public void clear() {
if ( isClearQueueEnabled() ) { if ( isClearQueueEnabled() ) {
queueOperation( new Clear() ); queueOperation( new Clear() );
@ -281,166 +281,167 @@ public class PersistentList extends AbstractPersistentCollection implements List
} }
} }
/** @Override
* @see java.util.List#get(int) @SuppressWarnings("unchecked")
*/
public Object get(int index) { public Object get(int index) {
if (index<0) { if ( index < 0 ) {
throw new ArrayIndexOutOfBoundsException("negative index"); throw new ArrayIndexOutOfBoundsException( "negative index" );
} }
Object result = readElementByIndex( index ); final Object result = readElementByIndex( index );
return result==UNKNOWN ? list.get(index) : result; return result == UNKNOWN ? list.get( index ) : result;
} }
/** @Override
* @see java.util.List#set(int, Object) @SuppressWarnings("unchecked")
*/
public Object set(int index, Object value) { public Object set(int index, Object value) {
if (index<0) { if (index<0) {
throw new ArrayIndexOutOfBoundsException("negative index"); throw new ArrayIndexOutOfBoundsException("negative index");
} }
Object old = isPutQueueEnabled() ? readElementByIndex( index ) : UNKNOWN;
final Object old = isPutQueueEnabled() ? readElementByIndex( index ) : UNKNOWN;
if ( old==UNKNOWN ) { if ( old==UNKNOWN ) {
write(); write();
return list.set(index, value); return list.set( index, value );
} }
else { else {
queueOperation( new Set(index, value, old) ); queueOperation( new Set( index, value, old ) );
return old; return old;
} }
} }
/** @Override
* @see java.util.List#add(int, Object) @SuppressWarnings("unchecked")
*/ public Object remove(int index) {
if ( index < 0 ) {
throw new ArrayIndexOutOfBoundsException( "negative index" );
}
final Object old = isPutQueueEnabled() ? readElementByIndex( index ) : UNKNOWN;
if ( old == UNKNOWN ) {
write();
return list.remove( index );
}
else {
queueOperation( new Remove( index, old ) );
return old;
}
}
@Override
@SuppressWarnings("unchecked")
public void add(int index, Object value) { public void add(int index, Object value) {
if (index<0) { if ( index < 0 ) {
throw new ArrayIndexOutOfBoundsException("negative index"); throw new ArrayIndexOutOfBoundsException( "negative index" );
} }
if ( !isOperationQueueEnabled() ) { if ( !isOperationQueueEnabled() ) {
write(); write();
list.add(index, value); list.add( index, value );
} }
else { else {
queueOperation( new Add(index, value) ); queueOperation( new Add( index, value ) );
} }
} }
/** @Override
* @see java.util.List#remove(int) @SuppressWarnings("unchecked")
*/
public Object remove(int index) {
if (index<0) {
throw new ArrayIndexOutOfBoundsException("negative index");
}
Object old = isPutQueueEnabled() ?
readElementByIndex( index ) : UNKNOWN;
if ( old==UNKNOWN ) {
write();
return list.remove(index);
}
else {
queueOperation( new Remove(index, old) );
return old;
}
}
/**
* @see java.util.List#indexOf(Object)
*/
public int indexOf(Object value) { public int indexOf(Object value) {
read(); read();
return list.indexOf(value); return list.indexOf( value );
} }
/** @Override
* @see java.util.List#lastIndexOf(Object) @SuppressWarnings("unchecked")
*/
public int lastIndexOf(Object value) { public int lastIndexOf(Object value) {
read(); read();
return list.lastIndexOf(value); return list.lastIndexOf( value );
} }
/** @Override
* @see java.util.List#listIterator() @SuppressWarnings("unchecked")
*/
public ListIterator listIterator() { public ListIterator listIterator() {
read(); read();
return new ListIteratorProxy( list.listIterator() ); return new ListIteratorProxy( list.listIterator() );
} }
/** @Override
* @see java.util.List#listIterator(int) @SuppressWarnings("unchecked")
*/
public ListIterator listIterator(int index) { public ListIterator listIterator(int index) {
read(); read();
return new ListIteratorProxy( list.listIterator(index) ); return new ListIteratorProxy( list.listIterator( index ) );
} }
/** @Override
* @see java.util.List#subList(int, int) @SuppressWarnings("unchecked")
*/
public java.util.List subList(int from, int to) { public java.util.List subList(int from, int to) {
read(); read();
return new ListProxy( list.subList(from, to) ); return new ListProxy( list.subList( from, to ) );
} }
@Override
public boolean empty() { public boolean empty() {
return list.isEmpty(); return list.isEmpty();
} }
@Override
public String toString() { public String toString() {
read(); read();
return list.toString(); return list.toString();
} }
@Override
@SuppressWarnings("unchecked")
public Object readFrom(ResultSet rs, CollectionPersister persister, CollectionAliases descriptor, Object owner) public Object readFrom(ResultSet rs, CollectionPersister persister, CollectionAliases descriptor, Object owner)
throws HibernateException, SQLException { throws HibernateException, SQLException {
Object element = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() ) ; final Object element = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() ) ;
int index = (Integer) persister.readIndex( rs, descriptor.getSuffixedIndexAliases(), getSession() ); final int index = (Integer) persister.readIndex( rs, descriptor.getSuffixedIndexAliases(), getSession() );
//pad with nulls from the current last element up to the new index //pad with nulls from the current last element up to the new index
for ( int i = list.size(); i<=index; i++) { for ( int i = list.size(); i<=index; i++) {
list.add(i, null); list.add( i, null );
} }
list.set(index, element); list.set( index, element );
return element; return element;
} }
@Override
@SuppressWarnings("unchecked")
public Iterator entries(CollectionPersister persister) { public Iterator entries(CollectionPersister persister) {
return list.iterator(); return list.iterator();
} }
@Override
@SuppressWarnings("unchecked")
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner) public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner)
throws HibernateException { throws HibernateException {
Serializable[] array = ( Serializable[] ) disassembled; final Serializable[] array = (Serializable[]) disassembled;
int size = array.length; final int size = array.length;
beforeInitialize( persister, size ); beforeInitialize( persister, size );
for ( int i = 0; i < size; i++ ) { for ( Serializable arrayElement : array ) {
list.add( persister.getElementType().assemble( array[i], getSession(), owner ) ); list.add( persister.getElementType().assemble( arrayElement, getSession(), owner ) );
} }
} }
public Serializable disassemble(CollectionPersister persister) @Override
throws HibernateException { @SuppressWarnings("unchecked")
public Serializable disassemble(CollectionPersister persister) throws HibernateException {
int length = list.size(); final int length = list.size();
Serializable[] result = new Serializable[length]; final Serializable[] result = new Serializable[length];
for ( int i=0; i<length; i++ ) { for ( int i=0; i<length; i++ ) {
result[i] = persister.getElementType().disassemble( list.get(i), getSession(), null ); result[i] = persister.getElementType().disassemble( list.get( i ), getSession(), null );
} }
return result; return result;
} }
@Override
@SuppressWarnings("unchecked")
public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) throws HibernateException { public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) throws HibernateException {
List deletes = new ArrayList(); final List deletes = new ArrayList();
List sn = (List) getSnapshot(); final List sn = (List) getSnapshot();
int end; int end;
if ( sn.size() > list.size() ) { if ( sn.size() > list.size() ) {
for ( int i=list.size(); i<sn.size(); i++ ) { for ( int i=list.size(); i<sn.size(); i++ ) {
deletes.add( indexIsFormula ? sn.get(i) : i ); deletes.add( indexIsFormula ? sn.get( i ) : i );
} }
end = list.size(); end = list.size();
} }
@ -448,60 +449,78 @@ public class PersistentList extends AbstractPersistentCollection implements List
end = sn.size(); end = sn.size();
} }
for ( int i=0; i<end; i++ ) { for ( int i=0; i<end; i++ ) {
if ( list.get(i)==null && sn.get(i)!=null ) { final Object item = list.get( i );
deletes.add( indexIsFormula ? sn.get(i) : i ); final Object snapshotItem = sn.get( i );
if ( item == null && snapshotItem != null ) {
deletes.add( indexIsFormula ? snapshotItem : i );
} }
} }
return deletes.iterator(); return deletes.iterator();
} }
@Override
public boolean needsInserting(Object entry, int i, Type elemType) throws HibernateException { public boolean needsInserting(Object entry, int i, Type elemType) throws HibernateException {
final List sn = (List) getSnapshot(); final List sn = (List) getSnapshot();
return list.get(i)!=null && ( i >= sn.size() || sn.get(i)==null ); return list.get( i ) != null && ( i >= sn.size() || sn.get( i ) == null );
} }
@Override
public boolean needsUpdating(Object entry, int i, Type elemType) throws HibernateException { public boolean needsUpdating(Object entry, int i, Type elemType) throws HibernateException {
final List sn = (List) getSnapshot(); final List sn = (List) getSnapshot();
return i<sn.size() && sn.get(i)!=null && list.get(i)!=null && return i < sn.size()
elemType.isDirty( list.get(i), sn.get(i), getSession() ); && sn.get( i ) != null
&& list.get( i ) != null
&& elemType.isDirty( list.get( i ), sn.get( i ), getSession() );
} }
@Override
public Object getIndex(Object entry, int i, CollectionPersister persister) { public Object getIndex(Object entry, int i, CollectionPersister persister) {
return i; return i;
} }
@Override
public Object getElement(Object entry) { public Object getElement(Object entry) {
return entry; return entry;
} }
@Override
public Object getSnapshotElement(Object entry, int i) { public Object getSnapshotElement(Object entry, int i) {
final List sn = (List) getSnapshot(); final List sn = (List) getSnapshot();
return sn.get(i); return sn.get( i );
} }
@Override
@SuppressWarnings("EqualsWhichDoesntCheckParameterClass")
public boolean equals(Object other) { public boolean equals(Object other) {
read(); read();
return list.equals(other); return list.equals( other );
} }
@Override
public int hashCode() { public int hashCode() {
read(); read();
return list.hashCode(); return list.hashCode();
} }
@Override
public boolean entryExists(Object entry, int i) { public boolean entryExists(Object entry, int i) {
return entry!=null; return entry!=null;
} }
final class Clear implements DelayedOperation { final class Clear implements DelayedOperation {
@Override
public void operate() { public void operate() {
list.clear(); list.clear();
} }
@Override
public Object getAddedInstance() { public Object getAddedInstance() {
return null; return null;
} }
@Override
public Object getOrphan() { public Object getOrphan() {
throw new UnsupportedOperationException("queued clear cannot be used with orphan delete"); throw new UnsupportedOperationException( "queued clear cannot be used with orphan delete" );
} }
} }
@ -511,12 +530,19 @@ public class PersistentList extends AbstractPersistentCollection implements List
public SimpleAdd(Object value) { public SimpleAdd(Object value) {
this.value = value; this.value = value;
} }
@Override
@SuppressWarnings("unchecked")
public void operate() { public void operate() {
list.add(value); list.add( value );
} }
@Override
public Object getAddedInstance() { public Object getAddedInstance() {
return value; return value;
} }
@Override
public Object getOrphan() { public Object getOrphan() {
return null; return null;
} }
@ -530,12 +556,19 @@ public class PersistentList extends AbstractPersistentCollection implements List
this.index = index; this.index = index;
this.value = value; this.value = value;
} }
@Override
@SuppressWarnings("unchecked")
public void operate() { public void operate() {
list.add(index, value); list.add( index, value );
} }
@Override
public Object getAddedInstance() { public Object getAddedInstance() {
return value; return value;
} }
@Override
public Object getOrphan() { public Object getOrphan() {
return null; return null;
} }
@ -551,12 +584,19 @@ public class PersistentList extends AbstractPersistentCollection implements List
this.value = value; this.value = value;
this.old = old; this.old = old;
} }
@Override
@SuppressWarnings("unchecked")
public void operate() { public void operate() {
list.set(index, value); list.set( index, value );
} }
@Override
public Object getAddedInstance() { public Object getAddedInstance() {
return value; return value;
} }
@Override
public Object getOrphan() { public Object getOrphan() {
return old; return old;
} }
@ -570,12 +610,19 @@ public class PersistentList extends AbstractPersistentCollection implements List
this.index = index; this.index = index;
this.old = old; this.old = old;
} }
@Override
@SuppressWarnings("unchecked")
public void operate() { public void operate() {
list.remove(index); list.remove( index );
} }
@Override
public Object getAddedInstance() { public Object getAddedInstance() {
return null; return null;
} }
@Override
public Object getOrphan() { public Object getOrphan() {
return old; return old;
} }
@ -587,12 +634,19 @@ public class PersistentList extends AbstractPersistentCollection implements List
public SimpleRemove(Object value) { public SimpleRemove(Object value) {
this.value = value; this.value = value;
} }
@Override
@SuppressWarnings("unchecked")
public void operate() { public void operate() {
list.remove(value); list.remove( value );
} }
@Override
public Object getAddedInstance() { public Object getAddedInstance() {
return null; return null;
} }
@Override
public Object getOrphan() { public Object getOrphan() {
return value; return value;
} }

View File

@ -35,6 +35,8 @@ import org.hibernate.type.IntegerType;
import org.hibernate.type.Type; import org.hibernate.type.Type;
/** /**
* Wraps a collection of DOM sub-elements as a List
*
* @author Gavin King * @author Gavin King
* *
* @deprecated To be removed in 5. Removed as part of removing the notion of DOM entity-mode. See Jira issues * @deprecated To be removed in 5. Removed as part of removing the notion of DOM entity-mode. See Jira issues
@ -42,43 +44,59 @@ import org.hibernate.type.Type;
* <a href="https://hibernate.onjira.com/browse/HHH-7783">HHH-7783</a> for more information. * <a href="https://hibernate.onjira.com/browse/HHH-7783">HHH-7783</a> for more information.
*/ */
@Deprecated @Deprecated
@SuppressWarnings({"UnusedDeclaration", "deprecation"})
public class PersistentListElementHolder extends PersistentIndexedElementHolder { public class PersistentListElementHolder extends PersistentIndexedElementHolder {
/**
* Constructs a PersistentListElementHolder.
*
* @param session The session
* @param element The owning DOM element
*/
@SuppressWarnings("UnusedDeclaration")
public PersistentListElementHolder(SessionImplementor session, Element element) { public PersistentListElementHolder(SessionImplementor session, Element element) {
super( session, element ); super( session, element );
} }
public PersistentListElementHolder(SessionImplementor session, CollectionPersister persister, /**
Serializable key) throws HibernateException { * Constructs a PersistentListElementHolder.
*
* @param session The session
* @param persister The collection persister
* @param key The collection key (fk value)
*/
@SuppressWarnings("UnusedDeclaration")
public PersistentListElementHolder(SessionImplementor session, CollectionPersister persister, Serializable key) {
super( session, persister, key ); super( session, persister, key );
} }
@Override
@SuppressWarnings("deprecation")
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner) public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner)
throws HibernateException { throws HibernateException {
final Type elementType = persister.getElementType();
Type elementType = persister.getElementType(); final String indexNodeName = getIndexAttributeName( persister );
final String indexNodeName = getIndexAttributeName(persister); final Serializable[] cached = (Serializable[]) disassembled;
Serializable[] cached = (Serializable[]) disassembled;
for ( int i=0; i<cached.length; i++ ) { for ( int i=0; i<cached.length; i++ ) {
Object object = elementType.assemble( cached[i], getSession(), owner ); final Object object = elementType.assemble( cached[i], getSession(), owner );
Element subelement = element.addElement( persister.getElementNodeName() ); final Element subelement = element.addElement( persister.getElementNodeName() );
elementType.setToXMLNode( subelement, object, persister.getFactory() ); elementType.setToXMLNode( subelement, object, persister.getFactory() );
setIndex( subelement, indexNodeName, Integer.toString(i) ); setIndex( subelement, indexNodeName, Integer.toString( i ) );
} }
} }
@Override
@SuppressWarnings("deprecation")
public Serializable disassemble(CollectionPersister persister) throws HibernateException { public Serializable disassemble(CollectionPersister persister) throws HibernateException {
final Type elementType = persister.getElementType();
Type elementType = persister.getElementType(); final String indexNodeName = getIndexAttributeName( persister );
final String indexNodeName = getIndexAttributeName(persister); final List elements = element.elements( persister.getElementNodeName() );
List elements = element.elements( persister.getElementNodeName() ); final int length = elements.size();
int length = elements.size(); final Serializable[] result = new Serializable[length];
Serializable[] result = new Serializable[length];
for ( int i=0; i<length; i++ ) { for ( int i=0; i<length; i++ ) {
Element elem = (Element) elements.get(i); final Element elem = (Element) elements.get( i );
Object object = elementType.fromXMLNode( elem, persister.getFactory() ); final Object object = elementType.fromXMLNode( elem, persister.getFactory() );
Integer index = IntegerType.INSTANCE.fromString( getIndex(elem, indexNodeName, i) ); final Integer index = IntegerType.INSTANCE.fromString( getIndex( elem, indexNodeName, i ) );
result[index] = elementType.disassemble( object, getSession(), null ); result[index] = elementType.disassemble( object, getSession(), null );
} }
return result; return result;

View File

@ -68,7 +68,7 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
* @param session The session to which this map will belong. * @param session The session to which this map will belong.
*/ */
public PersistentMap(SessionImplementor session) { public PersistentMap(SessionImplementor session) {
super(session); super( session );
} }
/** /**
@ -79,106 +79,108 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
* @param map The underlying map data. * @param map The underlying map data.
*/ */
public PersistentMap(SessionImplementor session, Map map) { public PersistentMap(SessionImplementor session, Map map) {
super(session); super( session );
this.map = map; this.map = map;
setInitialized(); setInitialized();
setDirectlyAccessible(true); setDirectlyAccessible( true );
} }
@Override
@SuppressWarnings( {"unchecked"}) @SuppressWarnings( {"unchecked"})
public Serializable getSnapshot(CollectionPersister persister) throws HibernateException { public Serializable getSnapshot(CollectionPersister persister) throws HibernateException {
HashMap clonedMap = new HashMap( map.size() ); final HashMap clonedMap = new HashMap( map.size() );
for ( Object o : map.entrySet() ) { for ( Object o : map.entrySet() ) {
Entry e = (Entry) o; final Entry e = (Entry) o;
final Object copy = persister.getElementType().deepCopy( e.getValue(), persister.getFactory() ); final Object copy = persister.getElementType().deepCopy( e.getValue(), persister.getFactory() );
clonedMap.put( e.getKey(), copy ); clonedMap.put( e.getKey(), copy );
} }
return clonedMap; return clonedMap;
} }
@Override
public Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException { public Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException {
Map sn = (Map) snapshot; final Map sn = (Map) snapshot;
return getOrphans( sn.values(), map.values(), entityName, getSession() ); return getOrphans( sn.values(), map.values(), entityName, getSession() );
} }
@Override
public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException { public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException {
Type elementType = persister.getElementType(); final Type elementType = persister.getElementType();
Map xmap = (Map) getSnapshot(); final Map snapshotMap = (Map) getSnapshot();
if ( xmap.size()!=this.map.size() ) return false; if ( snapshotMap.size() != this.map.size() ) {
Iterator iter = map.entrySet().iterator(); return false;
while ( iter.hasNext() ) { }
Map.Entry entry = (Map.Entry) iter.next();
if ( elementType.isDirty( entry.getValue(), xmap.get( entry.getKey() ), getSession() ) ) return false; for ( Object o : map.entrySet() ) {
final Entry entry = (Entry) o;
if ( elementType.isDirty( entry.getValue(), snapshotMap.get( entry.getKey() ), getSession() ) ) {
return false;
}
} }
return true; return true;
} }
@Override
public boolean isSnapshotEmpty(Serializable snapshot) { public boolean isSnapshotEmpty(Serializable snapshot) {
return ( (Map) snapshot ).isEmpty(); return ( (Map) snapshot ).isEmpty();
} }
@Override
public boolean isWrapper(Object collection) { public boolean isWrapper(Object collection) {
return map==collection; return map==collection;
} }
@Override
public void beforeInitialize(CollectionPersister persister, int anticipatedSize) { public void beforeInitialize(CollectionPersister persister, int anticipatedSize) {
this.map = ( Map ) persister.getCollectionType().instantiate( anticipatedSize ); this.map = (Map) persister.getCollectionType().instantiate( anticipatedSize );
} }
@Override
/**
* @see java.util.Map#size()
*/
public int size() { public int size() {
return readSize() ? getCachedSize() : map.size(); return readSize() ? getCachedSize() : map.size();
} }
/** @Override
* @see java.util.Map#isEmpty()
*/
public boolean isEmpty() { public boolean isEmpty() {
return readSize() ? getCachedSize()==0 : map.isEmpty(); return readSize() ? getCachedSize()==0 : map.isEmpty();
} }
/** @Override
* @see java.util.Map#containsKey(Object) @SuppressWarnings("UnnecessaryUnboxing")
*/
public boolean containsKey(Object key) { public boolean containsKey(Object key) {
Boolean exists = readIndexExistence(key); final Boolean exists = readIndexExistence( key );
return exists==null ? map.containsKey(key) : exists.booleanValue(); return exists == null ? map.containsKey( key ) : exists.booleanValue();
} }
/** @Override
* @see java.util.Map#containsValue(Object) @SuppressWarnings("UnnecessaryUnboxing")
*/
public boolean containsValue(Object value) { public boolean containsValue(Object value) {
Boolean exists = readElementExistence(value); final Boolean exists = readElementExistence( value );
return exists==null ? return exists == null
map.containsValue(value) : ? map.containsValue( value )
exists.booleanValue(); : exists.booleanValue();
} }
/** @Override
* @see java.util.Map#get(Object)
*/
public Object get(Object key) { public Object get(Object key) {
Object result = readElementByIndex(key); final Object result = readElementByIndex( key );
return result==UNKNOWN ? map.get(key) : result; return result == UNKNOWN
? map.get( key )
: result;
} }
/** @Override
* @see java.util.Map#put(Object, Object) @SuppressWarnings("unchecked")
*/
public Object put(Object key, Object value) { public Object put(Object key, Object value) {
if ( isPutQueueEnabled() ) { if ( isPutQueueEnabled() ) {
Object old = readElementByIndex( key ); final Object old = readElementByIndex( key );
if ( old != UNKNOWN ) { if ( old != UNKNOWN ) {
queueOperation( new Put( key, value, old ) ); queueOperation( new Put( key, value, old ) );
return old; return old;
} }
} }
initialize( true ); initialize( true );
Object old = map.put( key, value ); final Object old = map.put( key, value );
// would be better to use the element-type to determine // would be better to use the element-type to determine
// whether the old and the new are equal here; the problem being // whether the old and the new are equal here; the problem being
// we do not necessarily have access to the element type in all // we do not necessarily have access to the element type in all
@ -189,12 +191,11 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
return old; return old;
} }
/** @Override
* @see java.util.Map#remove(Object) @SuppressWarnings("unchecked")
*/
public Object remove(Object key) { public Object remove(Object key) {
if ( isPutQueueEnabled() ) { if ( isPutQueueEnabled() ) {
Object old = readElementByIndex( key ); final Object old = readElementByIndex( key );
if ( old != UNKNOWN ) { if ( old != UNKNOWN ) {
queueOperation( new Remove( key, old ) ); queueOperation( new Remove( key, old ) );
return old; return old;
@ -208,23 +209,20 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
return map.remove( key ); return map.remove( key );
} }
/** @Override
* @see java.util.Map#putAll(java.util.Map puts) @SuppressWarnings("unchecked")
*/
public void putAll(Map puts) { public void putAll(Map puts) {
if ( puts.size()>0 ) { if ( puts.size() > 0 ) {
initialize( true ); initialize( true );
Iterator itr = puts.entrySet().iterator(); for ( Object o : puts.entrySet() ) {
while ( itr.hasNext() ) { final Entry entry = (Entry) o;
Map.Entry entry = ( Entry ) itr.next();
put( entry.getKey(), entry.getValue() ); put( entry.getKey(), entry.getValue() );
} }
} }
} }
/** @Override
* @see java.util.Map#clear() @SuppressWarnings("unchecked")
*/
public void clear() { public void clear() {
if ( isClearQueueEnabled() ) { if ( isClearQueueEnabled() ) {
queueOperation( new Clear() ); queueOperation( new Clear() );
@ -238,34 +236,35 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
} }
} }
/** @Override
* @see java.util.Map#keySet() @SuppressWarnings("unchecked")
*/
public Set keySet() { public Set keySet() {
read(); read();
return new SetProxy( map.keySet() ); return new SetProxy( map.keySet() );
} }
/** @Override
* @see java.util.Map#values() @SuppressWarnings("unchecked")
*/
public Collection values() { public Collection values() {
read(); read();
return new SetProxy( map.values() ); return new SetProxy( map.values() );
} }
/** @Override
* @see java.util.Map#entrySet() @SuppressWarnings("unchecked")
*/
public Set entrySet() { public Set entrySet() {
read(); read();
return new EntrySetProxy( map.entrySet() ); return new EntrySetProxy( map.entrySet() );
} }
@Override
@SuppressWarnings("unchecked")
public boolean empty() { public boolean empty() {
return map.isEmpty(); return map.isEmpty();
} }
@Override
@SuppressWarnings("unchecked")
public String toString() { public String toString() {
read(); read();
return map.toString(); return map.toString();
@ -273,6 +272,8 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
private transient List<Object[]> loadingEntries; private transient List<Object[]> loadingEntries;
@Override
@SuppressWarnings("unchecked")
public Object readFrom( public Object readFrom(
ResultSet rs, ResultSet rs,
CollectionPersister persister, CollectionPersister persister,
@ -296,80 +297,134 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
for ( Object[] entry : loadingEntries ) { for ( Object[] entry : loadingEntries ) {
map.put( entry[0], entry[1] ); map.put( entry[0], entry[1] );
} }
loadingEntries = null; loadingEntries = null;
} }
return super.endRead(); return super.endRead();
} }
@Override
@SuppressWarnings("unchecked")
public Iterator entries(CollectionPersister persister) { public Iterator entries(CollectionPersister persister) {
return map.entrySet().iterator(); return map.entrySet().iterator();
} }
/** a wrapper for Map.Entry sets */ /**
* a wrapper for Map.Entry sets
*/
class EntrySetProxy implements Set { class EntrySetProxy implements Set {
private final Set set; private final Set set;
EntrySetProxy(Set set) { EntrySetProxy(Set set) {
this.set=set; this.set=set;
} }
@Override
@SuppressWarnings("unchecked")
public boolean add(Object entry) { public boolean add(Object entry) {
//write(); -- doesn't //write(); -- doesn't
return set.add(entry); return set.add( entry );
} }
@Override
@SuppressWarnings("unchecked")
public boolean addAll(Collection entries) { public boolean addAll(Collection entries) {
//write(); -- doesn't //write(); -- doesn't
return set.addAll(entries); return set.addAll( entries );
} }
@Override
@SuppressWarnings("unchecked")
public void clear() { public void clear() {
write(); write();
set.clear(); set.clear();
} }
@Override
@SuppressWarnings("unchecked")
public boolean contains(Object entry) { public boolean contains(Object entry) {
return set.contains(entry); return set.contains( entry );
} }
@Override
@SuppressWarnings("unchecked")
public boolean containsAll(Collection entries) { public boolean containsAll(Collection entries) {
return set.containsAll(entries); return set.containsAll( entries );
} }
@Override
@SuppressWarnings("unchecked")
public boolean isEmpty() { public boolean isEmpty() {
return set.isEmpty(); return set.isEmpty();
} }
@Override
@SuppressWarnings("unchecked")
public Iterator iterator() { public Iterator iterator() {
return new EntryIteratorProxy( set.iterator() ); return new EntryIteratorProxy( set.iterator() );
} }
@Override
@SuppressWarnings("unchecked")
public boolean remove(Object entry) { public boolean remove(Object entry) {
write(); write();
return set.remove(entry); return set.remove( entry );
} }
@Override
@SuppressWarnings("unchecked")
public boolean removeAll(Collection entries) { public boolean removeAll(Collection entries) {
write(); write();
return set.removeAll(entries); return set.removeAll( entries );
} }
@Override
@SuppressWarnings("unchecked")
public boolean retainAll(Collection entries) { public boolean retainAll(Collection entries) {
write(); write();
return set.retainAll(entries); return set.retainAll( entries );
} }
@Override
@SuppressWarnings("unchecked")
public int size() { public int size() {
return set.size(); return set.size();
} }
// amazingly, these two will work because AbstractCollection // amazingly, these two will work because AbstractCollection
// uses iterator() to fill the array // uses iterator() to fill the array
@Override
@SuppressWarnings("unchecked")
public Object[] toArray() { public Object[] toArray() {
return set.toArray(); return set.toArray();
} }
@Override
@SuppressWarnings("unchecked")
public Object[] toArray(Object[] array) { public Object[] toArray(Object[] array) {
return set.toArray(array); return set.toArray( array );
} }
} }
final class EntryIteratorProxy implements Iterator { final class EntryIteratorProxy implements Iterator {
private final Iterator iter; private final Iterator iter;
EntryIteratorProxy(Iterator iter) { EntryIteratorProxy(Iterator iter) {
this.iter=iter; this.iter=iter;
} }
@Override
@SuppressWarnings("unchecked")
public boolean hasNext() { public boolean hasNext() {
return iter.hasNext(); return iter.hasNext();
} }
@Override
@SuppressWarnings("unchecked")
public Object next() { public Object next() {
return new MapEntryProxy( (Map.Entry) iter.next() ); return new MapEntryProxy( (Map.Entry) iter.next() );
} }
@Override
@SuppressWarnings("unchecked")
public void remove() { public void remove() {
write(); write();
iter.remove(); iter.remove();
@ -381,37 +436,63 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
MapEntryProxy( Map.Entry me ) { MapEntryProxy( Map.Entry me ) {
this.me = me; this.me = me;
} }
public Object getKey() { return me.getKey(); }
public Object getValue() { return me.getValue(); } @Override
public boolean equals(Object o) { return me.equals(o); } @SuppressWarnings("unchecked")
public int hashCode() { return me.hashCode(); } public Object getKey() {
return me.getKey();
}
@Override
@SuppressWarnings("unchecked")
public Object getValue() {
return me.getValue();
}
@Override
@SuppressWarnings({"unchecked", "EqualsWhichDoesntCheckParameterClass"})
public boolean equals(Object o) {
return me.equals( o );
}
@Override
@SuppressWarnings("unchecked")
public int hashCode() {
return me.hashCode();
}
// finally, what it's all about... // finally, what it's all about...
@Override
@SuppressWarnings("unchecked")
public Object setValue(Object value) { public Object setValue(Object value) {
write(); write();
return me.setValue(value); return me.setValue( value );
} }
} }
@Override
@SuppressWarnings("unchecked")
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner) public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner)
throws HibernateException { throws HibernateException {
Serializable[] array = ( Serializable[] ) disassembled; final Serializable[] array = (Serializable[]) disassembled;
int size = array.length; final int size = array.length;
beforeInitialize( persister, size ); beforeInitialize( persister, size );
for ( int i = 0; i < size; i+=2 ) { for ( int i = 0; i < size; i+=2 ) {
map.put( map.put(
persister.getIndexType().assemble( array[i], getSession(), owner ), persister.getIndexType().assemble( array[i], getSession(), owner ),
persister.getElementType().assemble( array[i+1], getSession(), owner ) persister.getElementType().assemble( array[i+1], getSession(), owner )
); );
} }
} }
@Override
@SuppressWarnings("unchecked")
public Serializable disassemble(CollectionPersister persister) throws HibernateException { public Serializable disassemble(CollectionPersister persister) throws HibernateException {
final Serializable[] result = new Serializable[ map.size() * 2 ];
Serializable[] result = new Serializable[ map.size() * 2 ]; final Iterator itr = map.entrySet().iterator();
Iterator iter = map.entrySet().iterator();
int i=0; int i=0;
while ( iter.hasNext() ) { while ( itr.hasNext() ) {
Map.Entry e = (Map.Entry) iter.next(); final Map.Entry e = (Map.Entry) itr.next();
result[i++] = persister.getIndexType().disassemble( e.getKey(), getSession(), null ); result[i++] = persister.getIndexType().disassemble( e.getKey(), getSession(), null );
result[i++] = persister.getElementType().disassemble( e.getValue(), getSession(), null ); result[i++] = persister.getElementType().disassemble( e.getValue(), getSession(), null );
} }
@ -419,74 +500,92 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
} }
public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) @Override
throws HibernateException { @SuppressWarnings("unchecked")
List deletes = new ArrayList(); public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) throws HibernateException {
Iterator iter = ( (Map) getSnapshot() ).entrySet().iterator(); final List deletes = new ArrayList();
while ( iter.hasNext() ) { for ( Object o : ((Map) getSnapshot()).entrySet() ) {
Map.Entry e = (Map.Entry) iter.next(); final Entry e = (Entry) o;
Object key = e.getKey(); final Object key = e.getKey();
if ( e.getValue()!=null && map.get(key)==null ) { if ( e.getValue() != null && map.get( key ) == null ) {
deletes.add( indexIsFormula ? e.getValue() : key ); deletes.add( indexIsFormula ? e.getValue() : key );
} }
} }
return deletes.iterator(); return deletes.iterator();
} }
public boolean needsInserting(Object entry, int i, Type elemType) @Override
throws HibernateException { @SuppressWarnings("unchecked")
public boolean needsInserting(Object entry, int i, Type elemType) throws HibernateException {
final Map sn = (Map) getSnapshot(); final Map sn = (Map) getSnapshot();
Map.Entry e = (Map.Entry) entry; final Map.Entry e = (Map.Entry) entry;
return e.getValue()!=null && sn.get( e.getKey() )==null; return e.getValue() != null && sn.get( e.getKey() ) == null;
} }
public boolean needsUpdating(Object entry, int i, Type elemType) @Override
throws HibernateException { @SuppressWarnings("unchecked")
public boolean needsUpdating(Object entry, int i, Type elemType) throws HibernateException {
final Map sn = (Map) getSnapshot(); final Map sn = (Map) getSnapshot();
Map.Entry e = (Map.Entry) entry; final Map.Entry e = (Map.Entry) entry;
Object snValue = sn.get( e.getKey() ); final Object snValue = sn.get( e.getKey() );
return e.getValue()!=null && return e.getValue() != null
snValue!=null && && snValue != null
elemType.isDirty( snValue, e.getValue(), getSession() ); && elemType.isDirty( snValue, e.getValue(), getSession() );
} }
@Override
@SuppressWarnings("unchecked")
public Object getIndex(Object entry, int i, CollectionPersister persister) { public Object getIndex(Object entry, int i, CollectionPersister persister) {
return ( (Map.Entry) entry ).getKey(); return ( (Map.Entry) entry ).getKey();
} }
@Override
@SuppressWarnings("unchecked")
public Object getElement(Object entry) { public Object getElement(Object entry) {
return ( (Map.Entry) entry ).getValue(); return ( (Map.Entry) entry ).getValue();
} }
@Override
@SuppressWarnings("unchecked")
public Object getSnapshotElement(Object entry, int i) { public Object getSnapshotElement(Object entry, int i) {
final Map sn = (Map) getSnapshot(); final Map sn = (Map) getSnapshot();
return sn.get( ( (Map.Entry) entry ).getKey() ); return sn.get( ( (Map.Entry) entry ).getKey() );
} }
@Override
@SuppressWarnings({"unchecked", "EqualsWhichDoesntCheckParameterClass"})
public boolean equals(Object other) { public boolean equals(Object other) {
read(); read();
return map.equals(other); return map.equals( other );
} }
@Override
@SuppressWarnings("unchecked")
public int hashCode() { public int hashCode() {
read(); read();
return map.hashCode(); return map.hashCode();
} }
@Override
@SuppressWarnings("unchecked")
public boolean entryExists(Object entry, int i) { public boolean entryExists(Object entry, int i) {
return ( (Map.Entry) entry ).getValue()!=null; return ( (Map.Entry) entry ).getValue() != null;
} }
final class Clear implements DelayedOperation { final class Clear implements DelayedOperation {
@Override
public void operate() { public void operate() {
map.clear(); map.clear();
} }
@Override
public Object getAddedInstance() { public Object getAddedInstance() {
return null; return null;
} }
@Override
public Object getOrphan() { public Object getOrphan() {
throw new UnsupportedOperationException("queued clear cannot be used with orphan delete"); throw new UnsupportedOperationException( "queued clear cannot be used with orphan delete" );
} }
} }
@ -500,12 +599,21 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
this.value = value; this.value = value;
this.old = old; this.old = old;
} }
@Override
@SuppressWarnings("unchecked")
public void operate() { public void operate() {
map.put(index, value); map.put( index, value );
} }
@Override
@SuppressWarnings("unchecked")
public Object getAddedInstance() { public Object getAddedInstance() {
return value; return value;
} }
@Override
@SuppressWarnings("unchecked")
public Object getOrphan() { public Object getOrphan() {
return old; return old;
} }
@ -519,12 +627,19 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
this.index = index; this.index = index;
this.old = old; this.old = old;
} }
@Override
@SuppressWarnings("unchecked")
public void operate() { public void operate() {
map.remove(index); map.remove( index );
} }
@Override
public Object getAddedInstance() { public Object getAddedInstance() {
return null; return null;
} }
@Override
public Object getOrphan() { public Object getOrphan() {
return old; return old;
} }

View File

@ -35,60 +35,76 @@ import org.hibernate.type.Type;
import org.hibernate.type.XmlRepresentableType; import org.hibernate.type.XmlRepresentableType;
/** /**
* Wraps a collection of DOM sub-elements as a Map
*
* @author Gavin King * @author Gavin King
* *
* @deprecated To be removed in 5. Removed as part of removing the notion of DOM entity-mode. See Jira issues * @deprecated To be removed in 5. Removed as part of removing the notion of DOM entity-mode. See Jira issues
* <a href="https://hibernate.onjira.com/browse/HHH-7782">HHH-7782</a> and * <a href="https://hibernate.onjira.com/browse/HHH-7782">HHH-7782</a> and
* <a href="https://hibernate.onjira.com/browse/HHH-7783">HHH-7783</a> for more information. * <a href="https://hibernate.onjira.com/browse/HHH-7783">HHH-7783</a> for more information.
*/ */
@SuppressWarnings({"UnusedDeclaration", "deprecation"})
@Deprecated @Deprecated
public class PersistentMapElementHolder extends PersistentIndexedElementHolder { public class PersistentMapElementHolder extends PersistentIndexedElementHolder {
/**
* Constructs a PersistentMapElementHolder.
*
* @param session The session
* @param element The owning DOM element
*/
public PersistentMapElementHolder(SessionImplementor session, Element element) { public PersistentMapElementHolder(SessionImplementor session, Element element) {
super( session, element ); super( session, element );
} }
public PersistentMapElementHolder(SessionImplementor session, CollectionPersister persister, /**
Serializable key) throws HibernateException { * Constructs a PersistentMapElementHolder.
*
* @param session The session
* @param persister The collection persister
* @param key The collection key (fk value)
*/
public PersistentMapElementHolder(SessionImplementor session, CollectionPersister persister, Serializable key) {
super( session, persister, key ); super( session, persister, key );
} }
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner) @Override
throws HibernateException { @SuppressWarnings("unchecked")
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner) {
Type elementType = persister.getElementType(); final Type elementType = persister.getElementType();
Type indexType = persister.getIndexType(); final Type indexType = persister.getIndexType();
final String indexNodeName = getIndexAttributeName(persister); final String indexNodeName = getIndexAttributeName( persister );
Serializable[] cached = (Serializable[]) disassembled; final Serializable[] cached = (Serializable[]) disassembled;
int i = 0;
while ( i < cached.length ) {
final Object index = indexType.assemble( cached[i++], getSession(), owner );
final Object object = elementType.assemble( cached[i++], getSession(), owner );
for ( int i=0; i<cached.length; ) { final Element subElement = element.addElement( persister.getElementNodeName() );
Object index = indexType.assemble( cached[i++], getSession(), owner ); elementType.setToXMLNode( subElement, object, persister.getFactory() );
Object object = elementType.assemble( cached[i++], getSession(), owner );
final String indexString = ( (XmlRepresentableType) indexType ).toXMLString( index, persister.getFactory() );
Element subelement = element.addElement( persister.getElementNodeName() ); setIndex( subElement, indexNodeName, indexString );
elementType.setToXMLNode( subelement, object, persister.getFactory() );
String indexString = ( (XmlRepresentableType) indexType ).toXMLString( index, persister.getFactory() );
setIndex( subelement, indexNodeName, indexString );
} }
} }
@Override
@SuppressWarnings("unchecked")
public Serializable disassemble(CollectionPersister persister) throws HibernateException { public Serializable disassemble(CollectionPersister persister) throws HibernateException {
final Type elementType = persister.getElementType();
Type elementType = persister.getElementType(); final Type indexType = persister.getIndexType();
Type indexType = persister.getIndexType(); final String indexNodeName = getIndexAttributeName( persister );
final String indexNodeName = getIndexAttributeName(persister);
List elements = element.elements( persister.getElementNodeName() ); final List elements = element.elements( persister.getElementNodeName() );
int length = elements.size(); final int length = elements.size();
Serializable[] result = new Serializable[length*2]; final Serializable[] result = new Serializable[length*2];
for ( int i=0; i<length*2; ) { int i = 0;
Element elem = (Element) elements.get(i/2); while ( i < length*2 ) {
Object object = elementType.fromXMLNode( elem, persister.getFactory() ); final Element elem = (Element) elements.get(i/2);
final String indexString = getIndex(elem, indexNodeName, i); final Object object = elementType.fromXMLNode( elem, persister.getFactory() );
Object index = ( (XmlRepresentableType) indexType ).fromXMLString( indexString, persister.getFactory() ); final String indexString = getIndex( elem, indexNodeName, i );
final Object index = ( (XmlRepresentableType) indexType ).fromXMLString( indexString, persister.getFactory() );
result[i++] = indexType.disassemble( index, getSession(), null ); result[i++] = indexType.disassemble( index, getSession(), null );
result[i++] = elementType.disassemble( object, getSession(), null ); result[i++] = elementType.disassemble( object, getSession(), null );
} }

View File

@ -48,7 +48,6 @@ import org.hibernate.type.Type;
* @author Gavin King * @author Gavin King
*/ */
public class PersistentSet extends AbstractPersistentCollection implements java.util.Set { public class PersistentSet extends AbstractPersistentCollection implements java.util.Set {
protected Set set; protected Set set;
protected transient List tempList; protected transient List tempList;
@ -80,128 +79,127 @@ public class PersistentSet extends AbstractPersistentCollection implements java.
* @param set The underlying set data. * @param set The underlying set data.
*/ */
public PersistentSet(SessionImplementor session, java.util.Set set) { public PersistentSet(SessionImplementor session, java.util.Set set) {
super(session); super( session );
// Sets can be just a view of a part of another collection. // Sets can be just a view of a part of another collection.
// do we need to copy it to be sure it won't be changing // do we need to copy it to be sure it won't be changing
// underneath us? // underneath us?
// ie. this.set.addAll(set); // ie. this.set.addAll(set);
this.set = set; this.set = set;
setInitialized(); setInitialized();
setDirectlyAccessible(true); setDirectlyAccessible( true );
} }
@Override
@SuppressWarnings( {"unchecked"}) @SuppressWarnings( {"unchecked"})
public Serializable getSnapshot(CollectionPersister persister) throws HibernateException { public Serializable getSnapshot(CollectionPersister persister) throws HibernateException {
HashMap clonedSet = new HashMap( set.size() ); final HashMap clonedSet = new HashMap( set.size() );
for ( Object aSet : set ) { for ( Object aSet : set ) {
Object copied = persister.getElementType() final Object copied = persister.getElementType().deepCopy( aSet, persister.getFactory() );
.deepCopy( aSet, persister.getFactory() );
clonedSet.put( copied, copied ); clonedSet.put( copied, copied );
} }
return clonedSet; return clonedSet;
} }
@Override
public Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException { public Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException {
java.util.Map sn = (java.util.Map) snapshot; final java.util.Map sn = (java.util.Map) snapshot;
return getOrphans( sn.keySet(), set, entityName, getSession() ); return getOrphans( sn.keySet(), set, entityName, getSession() );
} }
@Override
public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException { public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException {
Type elementType = persister.getElementType(); final Type elementType = persister.getElementType();
java.util.Map sn = (java.util.Map) getSnapshot(); final java.util.Map sn = (java.util.Map) getSnapshot();
if ( sn.size()!=set.size() ) { if ( sn.size()!=set.size() ) {
return false; return false;
} }
else { else {
Iterator iter = set.iterator(); for ( Object test : set ) {
while ( iter.hasNext() ) { final Object oldValue = sn.get( test );
Object test = iter.next(); if ( oldValue == null || elementType.isDirty( oldValue, test, getSession() ) ) {
Object oldValue = sn.get(test); return false;
if ( oldValue==null || elementType.isDirty( oldValue, test, getSession() ) ) return false; }
} }
return true; return true;
} }
} }
@Override
public boolean isSnapshotEmpty(Serializable snapshot) { public boolean isSnapshotEmpty(Serializable snapshot) {
return ( (java.util.Map) snapshot ).isEmpty(); return ( (java.util.Map) snapshot ).isEmpty();
} }
@Override
public void beforeInitialize(CollectionPersister persister, int anticipatedSize) { public void beforeInitialize(CollectionPersister persister, int anticipatedSize) {
this.set = ( Set ) persister.getCollectionType().instantiate( anticipatedSize ); this.set = (Set) persister.getCollectionType().instantiate( anticipatedSize );
} }
@Override
@SuppressWarnings("unchecked")
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner) public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner)
throws HibernateException { throws HibernateException {
Serializable[] array = ( Serializable[] ) disassembled; final Serializable[] array = (Serializable[]) disassembled;
int size = array.length; final int size = array.length;
beforeInitialize( persister, size ); beforeInitialize( persister, size );
for (int i = 0; i < size; i++ ) { for ( Serializable arrayElement : array ) {
Object element = persister.getElementType().assemble( array[i], getSession(), owner ); final Object assembledArrayElement = persister.getElementType().assemble( arrayElement, getSession(), owner );
if ( element != null ) { if ( assembledArrayElement != null ) {
set.add( element ); set.add( assembledArrayElement );
} }
} }
} }
@Override
public boolean empty() { public boolean empty() {
return set.isEmpty(); return set.isEmpty();
} }
/** @Override
* @see java.util.Set#size() @SuppressWarnings("unchecked")
*/
public int size() { public int size() {
return readSize() ? getCachedSize() : set.size(); return readSize() ? getCachedSize() : set.size();
} }
/** @Override
* @see java.util.Set#isEmpty() @SuppressWarnings("unchecked")
*/
public boolean isEmpty() { public boolean isEmpty() {
return readSize() ? getCachedSize()==0 : set.isEmpty(); return readSize() ? getCachedSize()==0 : set.isEmpty();
} }
/** @Override
* @see java.util.Set#contains(Object) @SuppressWarnings({"unchecked", "UnnecessaryUnboxing"})
*/
public boolean contains(Object object) { public boolean contains(Object object) {
Boolean exists = readElementExistence(object); final Boolean exists = readElementExistence( object );
return exists==null ? return exists == null
set.contains(object) : ? set.contains( object )
exists.booleanValue(); : exists.booleanValue();
} }
/** @Override
* @see java.util.Set#iterator() @SuppressWarnings("unchecked")
*/
public Iterator iterator() { public Iterator iterator() {
read(); read();
return new IteratorProxy( set.iterator() ); return new IteratorProxy( set.iterator() );
} }
/** @Override
* @see java.util.Set#toArray() @SuppressWarnings("unchecked")
*/
public Object[] toArray() { public Object[] toArray() {
read(); read();
return set.toArray(); return set.toArray();
} }
/** @Override
* @see java.util.Set#toArray(Object[]) @SuppressWarnings("unchecked")
*/
public Object[] toArray(Object[] array) { public Object[] toArray(Object[] array) {
read(); read();
return set.toArray(array); return set.toArray( array );
} }
/** @Override
* @see java.util.Set#add(Object) @SuppressWarnings({"unchecked", "UnnecessaryUnboxing"})
*/
public boolean add(Object value) { public boolean add(Object value) {
Boolean exists = isOperationQueueEnabled() ? readElementExistence( value ) : null; final Boolean exists = isOperationQueueEnabled() ? readElementExistence( value ) : null;
if ( exists == null ) { if ( exists == null ) {
initialize( true ); initialize( true );
if ( set.add( value ) ) { if ( set.add( value ) ) {
@ -216,17 +214,16 @@ public class PersistentSet extends AbstractPersistentCollection implements java.
return false; return false;
} }
else { else {
queueOperation( new SimpleAdd(value) ); queueOperation( new SimpleAdd( value ) );
return true; return true;
} }
} }
/** @Override
* @see java.util.Set#remove(Object) @SuppressWarnings({"unchecked", "UnnecessaryUnboxing"})
*/
public boolean remove(Object value) { public boolean remove(Object value) {
Boolean exists = isPutQueueEnabled() ? readElementExistence( value ) : null; final Boolean exists = isPutQueueEnabled() ? readElementExistence( value ) : null;
if ( exists==null ) { if ( exists == null ) {
initialize( true ); initialize( true );
if ( set.remove( value ) ) { if ( set.remove( value ) ) {
dirty(); dirty();
@ -237,7 +234,7 @@ public class PersistentSet extends AbstractPersistentCollection implements java.
} }
} }
else if ( exists.booleanValue() ) { else if ( exists.booleanValue() ) {
queueOperation( new SimpleRemove(value) ); queueOperation( new SimpleRemove( value ) );
return true; return true;
} }
else { else {
@ -245,17 +242,15 @@ public class PersistentSet extends AbstractPersistentCollection implements java.
} }
} }
/** @Override
* @see java.util.Set#containsAll(Collection) @SuppressWarnings("unchecked")
*/
public boolean containsAll(Collection coll) { public boolean containsAll(Collection coll) {
read(); read();
return set.containsAll(coll); return set.containsAll( coll );
} }
/** @Override
* @see java.util.Set#addAll(Collection) @SuppressWarnings("unchecked")
*/
public boolean addAll(Collection coll) { public boolean addAll(Collection coll) {
if ( coll.size() > 0 ) { if ( coll.size() > 0 ) {
initialize( true ); initialize( true );
@ -272,9 +267,8 @@ public class PersistentSet extends AbstractPersistentCollection implements java.
} }
} }
/** @Override
* @see java.util.Set#retainAll(Collection) @SuppressWarnings("unchecked")
*/
public boolean retainAll(Collection coll) { public boolean retainAll(Collection coll) {
initialize( true ); initialize( true );
if ( set.retainAll( coll ) ) { if ( set.retainAll( coll ) ) {
@ -286,9 +280,8 @@ public class PersistentSet extends AbstractPersistentCollection implements java.
} }
} }
/** @Override
* @see java.util.Set#removeAll(Collection) @SuppressWarnings("unchecked")
*/
public boolean removeAll(Collection coll) { public boolean removeAll(Collection coll) {
if ( coll.size() > 0 ) { if ( coll.size() > 0 ) {
initialize( true ); initialize( true );
@ -305,9 +298,8 @@ public class PersistentSet extends AbstractPersistentCollection implements java.
} }
} }
/** @Override
* @see java.util.Set#clear() @SuppressWarnings("unchecked")
*/
public void clear() { public void clear() {
if ( isClearQueueEnabled() ) { if ( isClearQueueEnabled() ) {
queueOperation( new Clear() ); queueOperation( new Clear() );
@ -321,129 +313,168 @@ public class PersistentSet extends AbstractPersistentCollection implements java.
} }
} }
@Override
@SuppressWarnings("unchecked")
public String toString() { public String toString() {
//if (needLoading) return "asleep";
read(); read();
return set.toString(); return set.toString();
} }
@Override
@SuppressWarnings("unchecked")
public Object readFrom( public Object readFrom(
ResultSet rs, ResultSet rs,
CollectionPersister persister, CollectionPersister persister,
CollectionAliases descriptor, CollectionAliases descriptor,
Object owner) throws HibernateException, SQLException { Object owner) throws HibernateException, SQLException {
Object element = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() ); final Object element = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() );
if (element!=null) tempList.add(element); if ( element != null ) {
tempList.add( element );
}
return element; return element;
} }
@Override
@SuppressWarnings("unchecked")
public void beginRead() { public void beginRead() {
super.beginRead(); super.beginRead();
tempList = new ArrayList(); tempList = new ArrayList();
} }
@Override
@SuppressWarnings("unchecked")
public boolean endRead() { public boolean endRead() {
set.addAll(tempList); set.addAll( tempList );
tempList = null; tempList = null;
setInitialized(); setInitialized();
return true; return true;
} }
@Override
@SuppressWarnings("unchecked")
public Iterator entries(CollectionPersister persister) { public Iterator entries(CollectionPersister persister) {
return set.iterator(); return set.iterator();
} }
public Serializable disassemble(CollectionPersister persister) @Override
throws HibernateException { @SuppressWarnings("unchecked")
public Serializable disassemble(CollectionPersister persister) throws HibernateException {
Serializable[] result = new Serializable[ set.size() ]; final Serializable[] result = new Serializable[ set.size() ];
Iterator iter = set.iterator(); final Iterator itr = set.iterator();
int i=0; int i=0;
while ( iter.hasNext() ) { while ( itr.hasNext() ) {
result[i++] = persister.getElementType().disassemble( iter.next(), getSession(), null ); result[i++] = persister.getElementType().disassemble( itr.next(), getSession(), null );
} }
return result; return result;
} }
@Override
@SuppressWarnings("unchecked")
public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) throws HibernateException { public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) throws HibernateException {
Type elementType = persister.getElementType(); final Type elementType = persister.getElementType();
final java.util.Map sn = (java.util.Map) getSnapshot(); final java.util.Map sn = (java.util.Map) getSnapshot();
ArrayList deletes = new ArrayList( sn.size() ); final ArrayList deletes = new ArrayList( sn.size() );
Iterator iter = sn.keySet().iterator();
while ( iter.hasNext() ) { Iterator itr = sn.keySet().iterator();
Object test = iter.next(); while ( itr.hasNext() ) {
if ( !set.contains(test) ) { final Object test = itr.next();
if ( !set.contains( test ) ) {
// the element has been removed from the set // the element has been removed from the set
deletes.add(test); deletes.add( test );
} }
} }
iter = set.iterator();
while ( iter.hasNext() ) { itr = set.iterator();
Object test = iter.next(); while ( itr.hasNext() ) {
Object oldValue = sn.get(test); final Object test = itr.next();
final Object oldValue = sn.get( test );
if ( oldValue!=null && elementType.isDirty( test, oldValue, getSession() ) ) { if ( oldValue!=null && elementType.isDirty( test, oldValue, getSession() ) ) {
// the element has changed // the element has changed
deletes.add(oldValue); deletes.add( oldValue );
} }
} }
return deletes.iterator(); return deletes.iterator();
} }
@Override
@SuppressWarnings("unchecked")
public boolean needsInserting(Object entry, int i, Type elemType) throws HibernateException { public boolean needsInserting(Object entry, int i, Type elemType) throws HibernateException {
final java.util.Map sn = (java.util.Map) getSnapshot(); final Object oldValue = ( (java.util.Map) getSnapshot() ).get( entry );
Object oldValue = sn.get(entry);
// note that it might be better to iterate the snapshot but this is safe, // note that it might be better to iterate the snapshot but this is safe,
// assuming the user implements equals() properly, as required by the Set // assuming the user implements equals() properly, as required by the Set
// contract! // contract!
return oldValue==null || elemType.isDirty( oldValue, entry, getSession() ); return oldValue == null || elemType.isDirty( oldValue, entry, getSession() );
} }
@Override
@SuppressWarnings("unchecked")
public boolean needsUpdating(Object entry, int i, Type elemType) { public boolean needsUpdating(Object entry, int i, Type elemType) {
return false; return false;
} }
@Override
@SuppressWarnings("unchecked")
public boolean isRowUpdatePossible() { public boolean isRowUpdatePossible() {
return false; return false;
} }
@Override
@SuppressWarnings("unchecked")
public Object getIndex(Object entry, int i, CollectionPersister persister) { public Object getIndex(Object entry, int i, CollectionPersister persister) {
throw new UnsupportedOperationException("Sets don't have indexes"); throw new UnsupportedOperationException("Sets don't have indexes");
} }
@Override
@SuppressWarnings("unchecked")
public Object getElement(Object entry) { public Object getElement(Object entry) {
return entry; return entry;
} }
@Override
@SuppressWarnings("unchecked")
public Object getSnapshotElement(Object entry, int i) { public Object getSnapshotElement(Object entry, int i) {
throw new UnsupportedOperationException("Sets don't support updating by element"); throw new UnsupportedOperationException("Sets don't support updating by element");
} }
@Override
@SuppressWarnings({"unchecked", "EqualsWhichDoesntCheckParameterClass"})
public boolean equals(Object other) { public boolean equals(Object other) {
read(); read();
return set.equals(other); return set.equals( other );
} }
@Override
@SuppressWarnings("unchecked")
public int hashCode() { public int hashCode() {
read(); read();
return set.hashCode(); return set.hashCode();
} }
@Override
@SuppressWarnings("unchecked")
public boolean entryExists(Object key, int i) { public boolean entryExists(Object key, int i) {
return true; return true;
} }
@Override
@SuppressWarnings("unchecked")
public boolean isWrapper(Object collection) { public boolean isWrapper(Object collection) {
return set==collection; return set==collection;
} }
final class Clear implements DelayedOperation { final class Clear implements DelayedOperation {
@Override
public void operate() { public void operate() {
set.clear(); set.clear();
} }
@Override
public Object getAddedInstance() { public Object getAddedInstance() {
return null; return null;
} }
@Override
public Object getOrphan() { public Object getOrphan() {
throw new UnsupportedOperationException("queued clear cannot be used with orphan delete"); throw new UnsupportedOperationException("queued clear cannot be used with orphan delete");
} }
@ -455,12 +486,19 @@ public class PersistentSet extends AbstractPersistentCollection implements java.
public SimpleAdd(Object value) { public SimpleAdd(Object value) {
this.value = value; this.value = value;
} }
@Override
@SuppressWarnings("unchecked")
public void operate() { public void operate() {
set.add(value); set.add( value );
} }
@Override
public Object getAddedInstance() { public Object getAddedInstance() {
return value; return value;
} }
@Override
public Object getOrphan() { public Object getOrphan() {
return null; return null;
} }
@ -472,12 +510,19 @@ public class PersistentSet extends AbstractPersistentCollection implements java.
public SimpleRemove(Object value) { public SimpleRemove(Object value) {
this.value = value; this.value = value;
} }
@Override
@SuppressWarnings("unchecked")
public void operate() { public void operate() {
set.remove(value); set.remove( value );
} }
@Override
public Object getAddedInstance() { public Object getAddedInstance() {
return null; return null;
} }
@Override
public Object getOrphan() { public Object getOrphan() {
return value; return value;
} }

View File

@ -26,7 +26,6 @@ package org.hibernate.collection.internal;
import java.io.Serializable; import java.io.Serializable;
import java.util.Collection; import java.util.Collection;
import java.util.Comparator; import java.util.Comparator;
import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.SortedMap; import java.util.SortedMap;
@ -45,167 +44,212 @@ import org.hibernate.persister.collection.BasicCollectionPersister;
* @author <a href="mailto:doug.currie@alum.mit.edu">e</a> * @author <a href="mailto:doug.currie@alum.mit.edu">e</a>
*/ */
public class PersistentSortedMap extends PersistentMap implements SortedMap { public class PersistentSortedMap extends PersistentMap implements SortedMap {
protected Comparator comparator; protected Comparator comparator;
/**
* Constructs a PersistentSortedMap. This form needed for SOAP libraries, etc
*/
@SuppressWarnings("UnusedDeclaration")
public PersistentSortedMap() {
}
/**
* Constructs a PersistentSortedMap.
*
* @param session The session
*/
public PersistentSortedMap(SessionImplementor session) {
super( session );
}
/**
* Constructs a PersistentSortedMap.
*
* @param session The session
* @param map The underlying map data
*/
public PersistentSortedMap(SessionImplementor session, SortedMap map) {
super( session, map );
comparator = map.comparator();
}
@SuppressWarnings({"unchecked", "UnusedParameters"})
protected Serializable snapshot(BasicCollectionPersister persister, EntityMode entityMode) throws HibernateException { protected Serializable snapshot(BasicCollectionPersister persister, EntityMode entityMode) throws HibernateException {
TreeMap clonedMap = new TreeMap(comparator); final TreeMap clonedMap = new TreeMap( comparator );
Iterator iter = map.entrySet().iterator(); for ( Object o : map.entrySet() ) {
while ( iter.hasNext() ) { final Entry e = (Entry) o;
Map.Entry e = (Map.Entry) iter.next();
clonedMap.put( e.getKey(), persister.getElementType().deepCopy( e.getValue(), persister.getFactory() ) ); clonedMap.put( e.getKey(), persister.getElementType().deepCopy( e.getValue(), persister.getFactory() ) );
} }
return clonedMap; return clonedMap;
} }
public PersistentSortedMap(SessionImplementor session) {
super(session);
}
public void setComparator(Comparator comparator) { public void setComparator(Comparator comparator) {
this.comparator = comparator; this.comparator = comparator;
} }
public PersistentSortedMap(SessionImplementor session, SortedMap map) { @Override
super(session, map);
comparator = map.comparator();
}
public PersistentSortedMap() {} //needed for SOAP libraries, etc
/**
* @see PersistentSortedMap#comparator()
*/
public Comparator comparator() { public Comparator comparator() {
return comparator; return comparator;
} }
/** @Override
* @see PersistentSortedMap#subMap(Object, Object) @SuppressWarnings("unchecked")
*/
public SortedMap subMap(Object fromKey, Object toKey) { public SortedMap subMap(Object fromKey, Object toKey) {
read(); read();
SortedMap m = ( (SortedMap) map ).subMap(fromKey, toKey); final SortedMap subMap = ( (SortedMap) map ).subMap( fromKey, toKey );
return new SortedSubMap(m); return new SortedSubMap( subMap );
} }
/** @Override
* @see PersistentSortedMap#headMap(Object) @SuppressWarnings("unchecked")
*/
public SortedMap headMap(Object toKey) { public SortedMap headMap(Object toKey) {
read(); read();
SortedMap m; final SortedMap headMap = ( (SortedMap) map ).headMap( toKey );
m = ( (SortedMap) map ).headMap(toKey); return new SortedSubMap( headMap );
return new SortedSubMap(m);
} }
/** @Override
* @see PersistentSortedMap#tailMap(Object) @SuppressWarnings("unchecked")
*/
public SortedMap tailMap(Object fromKey) { public SortedMap tailMap(Object fromKey) {
read(); read();
SortedMap m; final SortedMap tailMap = ( (SortedMap) map ).tailMap( fromKey );
m = ( (SortedMap) map ).tailMap(fromKey); return new SortedSubMap( tailMap );
return new SortedSubMap(m);
} }
/** @Override
* @see PersistentSortedMap#firstKey() @SuppressWarnings("unchecked")
*/
public Object firstKey() { public Object firstKey() {
read(); read();
return ( (SortedMap) map ).firstKey(); return ( (SortedMap) map ).firstKey();
} }
/** @Override
* @see PersistentSortedMap#lastKey() @SuppressWarnings("unchecked")
*/
public Object lastKey() { public Object lastKey() {
read(); read();
return ( (SortedMap) map ).lastKey(); return ( (SortedMap) map ).lastKey();
} }
class SortedSubMap implements SortedMap { class SortedSubMap implements SortedMap {
SortedMap subMap;
SortedMap submap; SortedSubMap(SortedMap subMap) {
this.subMap = subMap;
SortedSubMap(SortedMap m) {
this.submap = m;
} }
// from Map
@Override
@SuppressWarnings("unchecked")
public int size() { public int size() {
return submap.size(); return subMap.size();
} }
@Override
@SuppressWarnings("unchecked")
public boolean isEmpty() { public boolean isEmpty() {
return submap.isEmpty(); return subMap.isEmpty();
} }
@Override
@SuppressWarnings("unchecked")
public boolean containsKey(Object key) { public boolean containsKey(Object key) {
return submap.containsKey(key); return subMap.containsKey( key );
} }
@Override
@SuppressWarnings("unchecked")
public boolean containsValue(Object key) { public boolean containsValue(Object key) {
return submap.containsValue(key) ; return subMap.containsValue( key ) ;
} }
@Override
@SuppressWarnings("unchecked")
public Object get(Object key) { public Object get(Object key) {
return submap.get(key); return subMap.get( key );
} }
@Override
@SuppressWarnings("unchecked")
public Object put(Object key, Object value) { public Object put(Object key, Object value) {
write(); write();
return submap.put(key, value); return subMap.put( key, value );
} }
@Override
@SuppressWarnings("unchecked")
public Object remove(Object key) { public Object remove(Object key) {
write(); write();
return submap.remove(key); return subMap.remove( key );
} }
@Override
@SuppressWarnings("unchecked")
public void putAll(Map other) { public void putAll(Map other) {
write(); write();
submap.putAll(other); subMap.putAll( other );
} }
@Override
@SuppressWarnings("unchecked")
public void clear() { public void clear() {
write(); write();
submap.clear(); subMap.clear();
} }
@Override
@SuppressWarnings("unchecked")
public Set keySet() { public Set keySet() {
return new SetProxy( submap.keySet() ); return new SetProxy( subMap.keySet() );
} }
@Override
@SuppressWarnings("unchecked")
public Collection values() { public Collection values() {
return new SetProxy( submap.values() ); return new SetProxy( subMap.values() );
} }
@Override
@SuppressWarnings("unchecked")
public Set entrySet() { public Set entrySet() {
return new EntrySetProxy( submap.entrySet() ); return new EntrySetProxy( subMap.entrySet() );
} }
// from SortedMap
@Override
@SuppressWarnings("unchecked")
public Comparator comparator() { public Comparator comparator() {
return submap.comparator(); return subMap.comparator();
} }
@Override
@SuppressWarnings("unchecked")
public SortedMap subMap(Object fromKey, Object toKey) { public SortedMap subMap(Object fromKey, Object toKey) {
SortedMap m; final SortedMap subMap = this.subMap.subMap( fromKey, toKey );
m = submap.subMap(fromKey, toKey); return new SortedSubMap( subMap );
return new SortedSubMap( m );
} }
@Override
@SuppressWarnings("unchecked")
public SortedMap headMap(Object toKey) { public SortedMap headMap(Object toKey) {
SortedMap m; final SortedMap headMap = subMap.headMap( toKey );
m = submap.headMap(toKey); return new SortedSubMap( headMap );
return new SortedSubMap(m);
} }
@Override
@SuppressWarnings("unchecked")
public SortedMap tailMap(Object fromKey) { public SortedMap tailMap(Object fromKey) {
SortedMap m; final SortedMap tailMap = subMap.tailMap( fromKey );
m = submap.tailMap(fromKey); return new SortedSubMap( tailMap );
return new SortedSubMap(m);
} }
@Override
@SuppressWarnings("unchecked")
public Object firstKey() { public Object firstKey() {
return submap.firstKey(); return subMap.firstKey();
} }
@Override
@SuppressWarnings("unchecked")
public Object lastKey() { public Object lastKey() {
return submap.lastKey(); return subMap.lastKey();
} }
} }
} }

View File

@ -25,7 +25,6 @@ package org.hibernate.collection.internal;
import java.io.Serializable; import java.io.Serializable;
import java.util.Comparator; import java.util.Comparator;
import java.util.Iterator;
import java.util.SortedSet; import java.util.SortedSet;
import java.util.TreeMap; import java.util.TreeMap;
@ -42,17 +41,42 @@ import org.hibernate.persister.collection.BasicCollectionPersister;
* @author <a href="mailto:doug.currie@alum.mit.edu">e</a> * @author <a href="mailto:doug.currie@alum.mit.edu">e</a>
*/ */
public class PersistentSortedSet extends PersistentSet implements SortedSet { public class PersistentSortedSet extends PersistentSet implements SortedSet {
protected Comparator comparator; protected Comparator comparator;
protected Serializable snapshot(BasicCollectionPersister persister, EntityMode entityMode) /**
throws HibernateException { * Constructs a PersistentSortedSet. This form needed for SOAP libraries, etc
//if (set==null) return new Set(session); */
TreeMap clonedSet = new TreeMap(comparator); @SuppressWarnings("UnusedDeclaration")
Iterator iter = set.iterator(); public PersistentSortedSet() {
while ( iter.hasNext() ) { }
Object copy = persister.getElementType().deepCopy( iter.next(), persister.getFactory() );
clonedSet.put(copy, copy); /**
* Constructs a PersistentSortedSet
*
* @param session The session
*/
public PersistentSortedSet(SessionImplementor session) {
super( session );
}
/**
* Constructs a PersistentSortedSet
*
* @param session The session
* @param set The underlying set data
*/
public PersistentSortedSet(SessionImplementor session, SortedSet set) {
super( session, set );
comparator = set.comparator();
}
@SuppressWarnings({"unchecked", "UnusedParameters"})
protected Serializable snapshot(BasicCollectionPersister persister, EntityMode entityMode)
throws HibernateException {
final TreeMap clonedSet = new TreeMap( comparator );
for ( Object setElement : set ) {
final Object copy = persister.getElementType().deepCopy( setElement, persister.getFactory() );
clonedSet.put( copy, copy );
} }
return clonedSet; return clonedSet;
} }
@ -61,106 +85,91 @@ public class PersistentSortedSet extends PersistentSet implements SortedSet {
this.comparator = comparator; this.comparator = comparator;
} }
public PersistentSortedSet(SessionImplementor session) { @Override
super(session);
}
public PersistentSortedSet(SessionImplementor session, SortedSet set) {
super(session, set);
comparator = set.comparator();
}
public PersistentSortedSet() {} //needed for SOAP libraries, etc
/**
* @see PersistentSortedSet#comparator()
*/
public Comparator comparator() { public Comparator comparator() {
return comparator; return comparator;
} }
/** @Override
* @see PersistentSortedSet#subSet(Object,Object) @SuppressWarnings("unchecked")
*/
public SortedSet subSet(Object fromElement, Object toElement) { public SortedSet subSet(Object fromElement, Object toElement) {
read(); read();
SortedSet s; final SortedSet subSet = ( (SortedSet) set ).subSet( fromElement, toElement );
s = ( (SortedSet) set ).subSet(fromElement, toElement); return new SubSetProxy( subSet );
return new SubSetProxy(s);
} }
/** @Override
* @see PersistentSortedSet#headSet(Object) @SuppressWarnings("unchecked")
*/
public SortedSet headSet(Object toElement) { public SortedSet headSet(Object toElement) {
read(); read();
SortedSet s = ( (SortedSet) set ).headSet(toElement); final SortedSet headSet = ( (SortedSet) set ).headSet(toElement);
return new SubSetProxy(s); return new SubSetProxy( headSet );
} }
/** @Override
* @see PersistentSortedSet#tailSet(Object) @SuppressWarnings("unchecked")
*/
public SortedSet tailSet(Object fromElement) { public SortedSet tailSet(Object fromElement) {
read(); read();
SortedSet s = ( (SortedSet) set ).tailSet(fromElement); final SortedSet tailSet = ( (SortedSet) set ).tailSet( fromElement );
return new SubSetProxy(s); return new SubSetProxy( tailSet );
} }
/** @Override
* @see PersistentSortedSet#first() @SuppressWarnings("unchecked")
*/
public Object first() { public Object first() {
read(); read();
return ( (SortedSet) set ).first(); return ( (SortedSet) set ).first();
} }
/** @Override
* @see PersistentSortedSet#last() @SuppressWarnings("unchecked")
*/
public Object last() { public Object last() {
read(); read();
return ( (SortedSet) set ).last(); return ( (SortedSet) set ).last();
} }
/** wrapper for subSets to propagate write to its backing set */ /**
* wrapper for subSets to propagate write to its backing set
*/
class SubSetProxy extends SetProxy implements SortedSet { class SubSetProxy extends SetProxy implements SortedSet {
SubSetProxy(SortedSet s) { SubSetProxy(SortedSet s) {
super(s); super( s );
} }
@Override
@SuppressWarnings("unchecked")
public Comparator comparator() { public Comparator comparator() {
return ( (SortedSet) this.set ).comparator(); return ( (SortedSet) this.set ).comparator();
} }
@Override
@SuppressWarnings("unchecked")
public Object first() { public Object first() {
return ( (SortedSet) this.set ).first(); return ( (SortedSet) this.set ).first();
} }
@Override
@SuppressWarnings("unchecked")
public SortedSet headSet(Object toValue) { public SortedSet headSet(Object toValue) {
return new SubSetProxy( ( (SortedSet) this.set ).headSet(toValue) ); return new SubSetProxy( ( (SortedSet) this.set ).headSet( toValue ) );
} }
@Override
@SuppressWarnings("unchecked")
public Object last() { public Object last() {
return ( (SortedSet) this.set ).last(); return ( (SortedSet) this.set ).last();
} }
@Override
@SuppressWarnings("unchecked")
public SortedSet subSet(Object fromValue, Object toValue) { public SortedSet subSet(Object fromValue, Object toValue) {
return new SubSetProxy( ( (SortedSet) this.set ).subSet(fromValue, toValue) ); return new SubSetProxy( ( (SortedSet) this.set ).subSet( fromValue, toValue ) );
} }
@Override
@SuppressWarnings("unchecked")
public SortedSet tailSet(Object fromValue) { public SortedSet tailSet(Object fromValue) {
return new SubSetProxy( ( (SortedSet) this.set ).tailSet(fromValue) ); return new SubSetProxy( ( (SortedSet) this.set ).tailSet( fromValue ) );
} }
} }
} }

View File

@ -0,0 +1,28 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
/**
* Internal implementations and support for persistent collections
*/
package org.hibernate.collection.internal;

View File

@ -63,28 +63,38 @@ import org.hibernate.type.Type;
* @author Gavin King * @author Gavin King
*/ */
public interface PersistentCollection { public interface PersistentCollection {
/** /**
* Get the owning entity. Note that the owner is only * Get the owning entity. Note that the owner is only
* set during the flush cycle, and when a new collection * set during the flush cycle, and when a new collection
* wrapper is created while loading an entity. * wrapper is created while loading an entity.
*
* @return The owner
*/ */
public Object getOwner(); public Object getOwner();
/** /**
* Set the reference to the owning entity * Set the reference to the owning entity
*
* @param entity The owner
*/ */
public void setOwner(Object entity); public void setOwner(Object entity);
/** /**
* Is the collection empty? (don't try to initialize the collection) * Is the collection empty? (don't try to initialize the collection)
*
* @return {@code false} if the collection is non-empty; {@code true} otherwise.
*/ */
public boolean empty(); public boolean empty();
/** /**
* After flushing, re-init snapshot state. * After flushing, re-init snapshot state.
*
* @param key The collection instance key (fk value).
* @param role The collection role
* @param snapshot The snapshot state
*/ */
public void setSnapshot(Serializable key, String role, Serializable snapshot); public void setSnapshot(Serializable key, String role, Serializable snapshot);
/** /**
* After flushing, clear any "queued" additions, since the * After flushing, clear any "queued" additions, since the
* database state is now synchronized with the memory state. * database state is now synchronized with the memory state.
@ -92,7 +102,9 @@ public interface PersistentCollection {
public void postAction(); public void postAction();
/** /**
* return the user-visible collection (or array) instance * Return the user-visible collection (or array) instance
*
* @return The underlying collection/array
*/ */
public Object getValue(); public Object getValue();
@ -103,70 +115,121 @@ public interface PersistentCollection {
/** /**
* Called after reading all rows from the JDBC result set * Called after reading all rows from the JDBC result set
*
* @return Whether to end the read.
*/ */
public boolean endRead(); public boolean endRead();
/** /**
* Called after initializing from cache * Called after initializing from cache
*
* @return ??
*/ */
public boolean afterInitialize(); public boolean afterInitialize();
/** /**
* Could the application possibly have a direct reference to * Could the application possibly have a direct reference to
* the underlying collection implementation? * the underlying collection implementation?
*
* @return {@code true} indicates that the application might have access to the underlying collection/array.
*/ */
public boolean isDirectlyAccessible(); public boolean isDirectlyAccessible();
/** /**
* Disassociate this collection from the given session. * Disassociate this collection from the given session.
*
* @param currentSession The session we are disassociating from. Used for validations.
*
* @return true if this was currently associated with the given session * @return true if this was currently associated with the given session
*/ */
public boolean unsetSession(SessionImplementor currentSession); public boolean unsetSession(SessionImplementor currentSession);
/** /**
* Associate the collection with the given session. * Associate the collection with the given session.
*
* @param session The session to associate with
*
* @return false if the collection was already associated with the session * @return false if the collection was already associated with the session
*
* @throws HibernateException if the collection was already associated * @throws HibernateException if the collection was already associated
* with another open session * with another open session
*/ */
public boolean setCurrentSession(SessionImplementor session) public boolean setCurrentSession(SessionImplementor session) throws HibernateException;
throws HibernateException;
/** /**
* Read the state of the collection from a disassembled cached value * Read the state of the collection from a disassembled cached value
*
* @param persister The collection persister
* @param disassembled The disassembled cached state
* @param owner The collection owner
*/ */
public void initializeFromCache(CollectionPersister persister, public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner);
Serializable disassembled, Object owner) throws HibernateException;
/** /**
* Iterate all collection entries, during update of the database * Iterate all collection entries, during update of the database
*
* @param persister The collection persister.
*
* @return The iterator
*/ */
public Iterator entries(CollectionPersister persister); public Iterator entries(CollectionPersister persister);
/** /**
* Read a row from the JDBC result set * Read a row from the JDBC result set
*
* @param rs The JDBC ResultSet
* @param role The collection role
* @param descriptor The aliases used for the columns making up the collection
* @param owner The collection owner
*
* @return The read object
*
* @throws HibernateException Generally indicates a problem resolving data read from the ResultSet
* @throws SQLException Indicates a problem accessing the ResultSet
*/ */
public Object readFrom(ResultSet rs, CollectionPersister role, CollectionAliases descriptor, Object owner) public Object readFrom(ResultSet rs, CollectionPersister role, CollectionAliases descriptor, Object owner)
throws HibernateException, SQLException; throws HibernateException, SQLException;
/** /**
* Get the index of the given collection entry * Get the identifier of the given collection entry. This refers to the collection identifier, not the
* identifier of the (possibly) entity elements. This is only valid for invocation on the
* {@code idbag} collection.
*
* @param entry The collection entry/element
* @param i The assumed identifier (?)
*
* @return The identifier value
*/ */
public Object getIdentifier(Object entry, int i); public Object getIdentifier(Object entry, int i);
/** /**
* Get the index of the given collection entry * Get the index of the given collection entry
*
* @param entry The collection entry/element
* @param i The assumed index
* @param persister it was more elegant before we added this... * @param persister it was more elegant before we added this...
*
* @return The index value
*/ */
public Object getIndex(Object entry, int i, CollectionPersister persister); public Object getIndex(Object entry, int i, CollectionPersister persister);
/** /**
* Get the value of the given collection entry * Get the value of the given collection entry. Generally the given entry parameter value will just be returned.
* Might get a different value for a duplicate entries in a Set.
*
* @param entry The object instance for which to get the collection element instance.
*
* @return The corresponding object that is part of the collection elements.
*/ */
public Object getElement(Object entry); public Object getElement(Object entry);
/** /**
* Get the snapshot value of the given collection entry * Get the snapshot value of the given collection entry
*
* @param entry The entry
* @param i The index
*
* @return The snapshot state for that element
*/ */
public Object getSnapshotElement(Object entry, int i); public Object getSnapshotElement(Object entry, int i);
@ -175,106 +238,168 @@ public interface PersistentCollection {
* allowing appropriate initializations to occur. * allowing appropriate initializations to occur.
* *
* @param persister The underlying collection persister. * @param persister The underlying collection persister.
* @param anticipatedSize The anticipated size of the collection after initilization is complete. * @param anticipatedSize The anticipated size of the collection after initialization is complete.
*/ */
public void beforeInitialize(CollectionPersister persister, int anticipatedSize); public void beforeInitialize(CollectionPersister persister, int anticipatedSize);
/** /**
* Does the current state exactly match the snapshot? * Does the current state exactly match the snapshot?
*
* @param persister The collection persister
*
* @return {@code true} if the current state and the snapshot state match.
*
*/ */
public boolean equalsSnapshot(CollectionPersister persister) public boolean equalsSnapshot(CollectionPersister persister);
throws HibernateException;
/** /**
* Is the snapshot empty? * Is the snapshot empty?
*
* @param snapshot The snapshot to check
*
* @return {@code true} if the given snapshot is empty
*/ */
public boolean isSnapshotEmpty(Serializable snapshot); public boolean isSnapshotEmpty(Serializable snapshot);
/** /**
* Disassemble the collection, ready for the cache * Disassemble the collection to get it ready for the cache
*
* @param persister The collection persister
*
* @return The disassembled state
*/ */
public Serializable disassemble(CollectionPersister persister) public Serializable disassemble(CollectionPersister persister) ;
throws HibernateException;
/** /**
* Do we need to completely recreate this collection when it changes? * Do we need to completely recreate this collection when it changes?
*
* @param persister The collection persister
*
* @return {@code true} if a change requires a recreate.
*/ */
public boolean needsRecreate(CollectionPersister persister); public boolean needsRecreate(CollectionPersister persister);
/** /**
* Return a new snapshot of the current state of the collection * Return a new snapshot of the current state of the collection
*
* @param persister The collection persister
*
* @return The snapshot
*/ */
public Serializable getSnapshot(CollectionPersister persister) public Serializable getSnapshot(CollectionPersister persister);
throws HibernateException;
/** /**
* To be called internally by the session, forcing * To be called internally by the session, forcing immediate initialization.
* immediate initialization.
*/ */
public void forceInitialization() throws HibernateException; public void forceInitialization();
/** /**
* Does an element exist at this entry in the collection? * Does the given element/entry exist in the collection?
*
* @param entry The object to check if it exists as a collection element
* @param i Unused
*
* @return {@code true} if the given entry is a collection element
*/ */
public boolean entryExists(Object entry, int i); //note that i parameter is now unused (delete it?) public boolean entryExists(Object entry, int i);
/** /**
* Do we need to insert this element? * Do we need to insert this element?
*
* @param entry The collection element to check
* @param i The index (for indexed collections)
* @param elemType The type for the element
*
* @return {@code true} if the element needs inserting
*/ */
public boolean needsInserting(Object entry, int i, Type elemType) public boolean needsInserting(Object entry, int i, Type elemType);
throws HibernateException;
/** /**
* Do we need to update this element? * Do we need to update this element?
*
* @param entry The collection element to check
* @param i The index (for indexed collections)
* @param elemType The type for the element
*
* @return {@code true} if the element needs updating
*/
public boolean needsUpdating(Object entry, int i, Type elemType);
/**
* Can each element in the collection be mapped unequivocally to a single row in the database? Generally
* bags and sets are the only collections that cannot be.
*
* @return {@code true} if the row for each element is known
*/ */
public boolean needsUpdating(Object entry, int i, Type elemType)
throws HibernateException;
public boolean isRowUpdatePossible(); public boolean isRowUpdatePossible();
/** /**
* Get all the elements that need deleting * Get all the elements that need deleting
*
* @param persister The collection persister
* @param indexIsFormula For indexed collections, tells whether the index is a formula (calculated value) mapping
*
* @return An iterator over the elements to delete
*/ */
public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula);
throws HibernateException;
/** /**
* Is this the wrapper for the given underlying collection instance? * Is this the wrapper for the given collection instance?
*
* @param collection The collection to check whether this is wrapping it
*
* @return {@code true} if this is a wrapper around that given collection instance.
*/ */
public boolean isWrapper(Object collection); public boolean isWrapper(Object collection);
/** /**
* Is this instance initialized? * Is this instance initialized?
*
* @return Was this collection initialized? Or is its data still not (fully) loaded?
*/ */
public boolean wasInitialized(); public boolean wasInitialized();
/** /**
* Does this instance have any "queued" additions? * Does this instance have any "queued" operations?
*
* @return {@code true} indicates there are pending, queued, delayed operations
*/ */
public boolean hasQueuedOperations(); public boolean hasQueuedOperations();
/** /**
* Iterate the "queued" additions * Iterator over the "queued" additions
*
* @return The iterator
*/ */
public Iterator queuedAdditionIterator(); public Iterator queuedAdditionIterator();
/** /**
* Get the "queued" orphans * Get the "queued" orphans
*
* @param entityName The name of the entity that makes up the elements
*
* @return The orphaned elements
*/ */
public Collection getQueuedOrphans(String entityName); public Collection getQueuedOrphans(String entityName);
/** /**
* Get the current collection key value * Get the current collection key value
*
* @return the current collection key value
*/ */
public Serializable getKey(); public Serializable getKey();
/** /**
* Get the current role name * Get the current role name
*
* @return the collection role name
*/ */
public String getRole(); public String getRole();
/** /**
* Is the collection unreferenced? * Is the collection unreferenced?
*
* @return {@code true} if the collection is no longer referenced by an owner
*/ */
public boolean isUnreferenced(); public boolean isUnreferenced();
@ -283,6 +408,8 @@ public interface PersistentCollection {
* reliable during the flush cycle, after the * reliable during the flush cycle, after the
* collection elements are dirty checked against * collection elements are dirty checked against
* the snapshot. * the snapshot.
*
* @return {@code true} if the collection is dirty
*/ */
public boolean isDirty(); public boolean isDirty();
@ -293,8 +420,9 @@ public interface PersistentCollection {
public void clearDirty(); public void clearDirty();
/** /**
* Get the snapshot cached by the collection * Get the snapshot cached by the collection instance
* instance *
* @return The internally stored snapshot state
*/ */
public Serializable getStoredSnapshot(); public Serializable getStoredSnapshot();
@ -306,20 +434,28 @@ public interface PersistentCollection {
/** /**
* Called before inserting rows, to ensure that any surrogate keys * Called before inserting rows, to ensure that any surrogate keys
* are fully generated * are fully generated
*
* @param persister The collection persister
*/ */
public void preInsert(CollectionPersister persister) public void preInsert(CollectionPersister persister);
throws HibernateException;
/** /**
* Called after inserting a row, to fetch the natively generated id * Called after inserting a row, to fetch the natively generated id
*
* @param persister The collection persister
* @param entry The collection element just inserted
* @param i The element position/index
*/ */
public void afterRowInsert(CollectionPersister persister, Object entry, int i) public void afterRowInsert(CollectionPersister persister, Object entry, int i);
throws HibernateException;
/** /**
* get all "orphaned" elements * get all "orphaned" elements
*
* @param snapshot The snapshot state
* @param entityName The name of the entity that are the elements of the collection
*
* @return The orphans
*/ */
public Collection getOrphans(Serializable snapshot, String entityName) public Collection getOrphans(Serializable snapshot, String entityName);
throws HibernateException;
} }

View File

@ -0,0 +1,28 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2013, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
/**
* SPI definitions for persistent collections
*/
package org.hibernate.collection.spi;