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
*/
public final class EntityInsertAction extends AbstractEntityInsertAction {
private Object version;
private Object cacheEntry;
@ -130,7 +129,7 @@ public final class EntityInsertAction extends AbstractEntityInsertAction {
version,
session
);
cacheEntry = persister.getCacheEntryStructure().structure(ce);
cacheEntry = persister.getCacheEntryStructure().structure( ce );
final CacheKey ck = session.generateCacheKey( id, persister.getIdentifierType(), persister.getRootEntityName() );
final boolean put = persister.getCacheAccessStrategy().insert( ck, cacheEntry, version );

View File

@ -63,7 +63,7 @@ public class TransformingClassLoader extends ClassLoader {
try {
final CtClass cc = classPool.get( name );
// 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 );
}
catch (NotFoundException e) {

View File

@ -30,10 +30,11 @@ import org.hibernate.mapping.Collection;
import org.hibernate.mapping.PersistentClass;
import org.hibernate.metamodel.binding.EntityBinding;
import org.hibernate.metamodel.binding.PluralAttributeBinding;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.VersionType;
/**
* Standard CacheDataDescription implementation.
*
* @author Steve Ebersole
*/
public class CacheDataDescriptionImpl implements CacheDataDescription {
@ -41,48 +42,87 @@ public class CacheDataDescriptionImpl implements CacheDataDescription {
private final boolean versioned;
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) {
this.mutable = mutable;
this.versioned = versioned;
this.versionComparator = versionComparator;
}
@Override
public boolean isMutable() {
return mutable;
}
@Override
public boolean isVersioned() {
return versioned;
}
@Override
public Comparator getVersionComparator() {
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) {
return new CacheDataDescriptionImpl(
model.isMutable(),
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) {
return new CacheDataDescriptionImpl(
model.isMutable(),
model.isVersioned(),
getVersionComparator( model )
);
return new CacheDataDescriptionImpl( 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) {
return new CacheDataDescriptionImpl(
model.isMutable(),
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) {
return new CacheDataDescriptionImpl(
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 ) {
Comparator versionComparator = null;
if ( model.isVersioned() ) {
versionComparator = (
( VersionType ) model.getHierarchyDetails()
final VersionType versionType = (VersionType) model.getHierarchyDetails()
.getVersioningAttributeBinding()
.getHibernateTypeDescriptor()
.getResolvedTypeMapping()
).getComparator();
.getResolvedTypeMapping();
return versionType.getComparator();
}
return versionComparator;
return null;
}
}

View File

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

View File

@ -28,8 +28,6 @@ import java.util.Map;
import org.hibernate.boot.registry.StandardServiceInitiator;
import org.hibernate.boot.registry.selector.spi.StrategySelector;
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;
/**
@ -38,6 +36,9 @@ import org.hibernate.service.spi.ServiceRegistryImplementor;
* @author Hardy Ferentschik
*/
public class RegionFactoryInitiator implements StandardServiceInitiator<RegionFactory> {
/**
* Singleton access
*/
public static final RegionFactoryInitiator INSTANCE = new RegionFactoryInitiator();
/**
@ -59,35 +60,17 @@ public class RegionFactoryInitiator implements StandardServiceInitiator<RegionFa
setting,
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) {
if ( "org.hibernate.cache.EhCacheRegionFactory".equals( name ) ) {
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
* 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.
*
* @author Gavin King
* @author Steve Ebersole
*/
public class StandardQueryCache implements QueryCache {
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
CoreMessageLogger.class,
StandardQueryCache.class.getName()
@ -67,28 +66,54 @@ public class StandardQueryCache implements QueryCache {
private QueryResultsRegion cacheRegion;
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(
final Settings settings,
final Properties props,
final UpdateTimestampsCache updateTimestampsCache,
String regionName) throws HibernateException {
if ( regionName == null ) {
regionName = StandardQueryCache.class.getName();
final String regionName) {
String regionNameToUse = regionName;
if ( regionNameToUse == null ) {
regionNameToUse = StandardQueryCache.class.getName();
}
String prefix = settings.getCacheRegionPrefix();
final String prefix = settings.getCacheRegionPrefix();
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;
}
@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" })
public boolean put(
final QueryKey key,
@ -99,20 +124,21 @@ public class StandardQueryCache implements QueryCache {
if ( isNaturalKeyLookup && result.isEmpty() ) {
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 );
cacheable.add( ts );
final boolean singleResult = returnTypes.length == 1;
final boolean isSingleResult = returnTypes.length == 1;
for ( Object aResult : result ) {
Serializable cacheItem = singleResult ? returnTypes[0].disassemble(
aResult,
session,
null
) : TypeHelper.disassemble( (Object[]) aResult, returnTypes, null, session, null );
final Serializable cacheItem = isSingleResult
? returnTypes[0].disassemble( aResult, session, null )
: TypeHelper.disassemble( (Object[]) aResult, returnTypes, null, session, null );
cacheable.add( cacheItem );
logCachedResultRowDetails( returnTypes, aResult );
}
@ -121,6 +147,7 @@ public class StandardQueryCache implements QueryCache {
return true;
}
@Override
@SuppressWarnings({ "unchecked" })
public List get(
final QueryKey key,
@ -128,23 +155,31 @@ public class StandardQueryCache implements QueryCache {
final boolean isNaturalKeyLookup,
final Set spaces,
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 );
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;
}
Long timestamp = (Long) cacheable.get( 0 );
final Long timestamp = (Long) cacheable.get( 0 );
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;
}
if ( DEBUGGING ) LOG.debug( "Returning cached query results" );
if ( DEBUGGING ) {
LOG.debug( "Returning cached query results" );
}
final boolean singleResult = returnTypes.length == 1;
for ( int i = 1; i < cacheable.size(); i++ ) {
if ( singleResult ) {
@ -154,7 +189,8 @@ public class StandardQueryCache implements QueryCache {
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++ ) {
try {
if ( singleResult ) {
@ -168,17 +204,19 @@ public class StandardQueryCache implements QueryCache {
logCachedResultRowDetails( returnTypes, result.get( i - 1 ) );
}
catch ( RuntimeException ex ) {
if ( isNaturalKeyLookup &&
( UnresolvableObjectException.class.isInstance( ex ) ||
EntityNotFoundException.class.isInstance( ex ) ) ) {
//TODO: not really completely correct, since
// the uoe could occur while resolving
// associations, leaving the PC in an
// inconsistent state
if ( DEBUGGING ) LOG.debug( "Unable to reassemble cached result set" );
if ( isNaturalKeyLookup ) {
// potentially perform special handling for natural-id look ups.
if ( UnresolvableObjectException.class.isInstance( ex )
|| EntityNotFoundException.class.isInstance( ex ) ) {
if ( DEBUGGING ) {
LOG.debug( "Unable to reassemble cached natural-id query result" );
}
cacheRegion.evict( key );
// EARLY EXIT !!!!!
return null;
}
}
throw ex;
}
}
@ -186,23 +224,12 @@ public class StandardQueryCache implements QueryCache {
}
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 );
}
public void destroy() {
try {
cacheRegion.destroy();
}
catch ( Exception e ) {
LOG.unableToDestroyQueryCache( cacheRegion.getName(), e.getMessage() );
}
}
public QueryResultsRegion getRegion() {
return cacheRegion;
}
@Override
public String toString() {
return "StandardQueryCache(" + cacheRegion.getName() + ')';
@ -222,12 +249,13 @@ public class StandardQueryCache implements QueryCache {
);
}
else {
StringBuilder returnTypeInfo = new StringBuilder();
for ( int i = 0; i < returnTypes.length; i++ ) {
final StringBuilder returnTypeInfo = new StringBuilder();
for ( Type returnType : returnTypes ) {
returnTypeInfo.append( "typename=" )
.append( returnTypes[i].getName() )
.append( returnType.getName() )
.append( " class=" )
.append( returnTypes[i].getReturnedClass().getName() ).append( ' ' );
.append( returnType.getReturnedClass().getName() )
.append( ' ' );
}
LOG.trace( "unexpected returnTypes is " + returnTypeInfo.toString() + "! result" );
}
@ -248,7 +276,10 @@ public class StandardQueryCache implements QueryCache {
return;
}
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 ) {
LOG.trace(
"Unexpected result tuple! tuple is null; should be Object["
@ -263,8 +294,12 @@ public class StandardQueryCache implements QueryCache {
+ ( returnTypes == null ? "null" : "empty" )
);
}
LOG.trace( " tuple is Object[" + tuple.length + "]; returnTypes is Type[" + returnTypes.length + "]" );
if ( tuple.length != returnTypes.length ) {
LOG.tracef(
"tuple is Object[%s]; returnTypes is %s",
tuple.length,
returnTypes == null ? "null" : "Type[" + returnTypes.length + "]"
);
if ( returnTypes != null && tuple.length != returnTypes.length ) {
LOG.trace(
"Unexpected tuple length! transformer= expected="
+ returnTypes.length + " got=" + tuple.length
@ -272,7 +307,8 @@ public class StandardQueryCache implements QueryCache {
}
else {
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(
"Unexpected tuple value type! transformer= expected="
+ returnTypes[j].getReturnedClass().getName()

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.hibernate.HibernateException;
import org.hibernate.cache.CacheException;
import org.hibernate.cfg.Settings;
import org.hibernate.engine.spi.SessionFactoryImplementor;

View File

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

View File

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

View File

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

View File

@ -29,6 +29,7 @@ import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import org.jboss.logging.Logger;
@ -48,27 +49,52 @@ import org.hibernate.type.Type;
* @author Gavin King
*/
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)
private transient Class elementClass;
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) {
super(session);
super( session );
this.array = array;
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 {
int length = /*(array==null) ? tempList.size() :*/ Array.getLength(array);
Serializable result = (Serializable) Array.newInstance( persister.getElementClass(), length );
// final int length = (array==null) ? tempList.size() : Array.getLength( array );
final int length = Array.getLength( array );
final Serializable result = (Serializable) Array.newInstance( persister.getElementClass(), length );
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 {
Array.set( result, i, persister.getElementType().deepCopy(elt, persister.getFactory()) );
Array.set( result, i, persister.getElementType().deepCopy( elt, persister.getFactory() ) );
}
catch (IllegalArgumentException iae) {
LOG.invalidArrayElementType( iae.getMessage() );
@ -78,70 +104,84 @@ public class PersistentArrayHolder extends AbstractPersistentCollection {
return result;
}
@Override
public boolean isSnapshotEmpty(Serializable snapshot) {
return Array.getLength( snapshot ) == 0;
}
@Override
public Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException {
Object[] sn = (Object[]) snapshot;
Object[] arr = (Object[]) array;
ArrayList result = new ArrayList();
for (int i=0; i<sn.length; i++) result.add( sn[i] );
for (int i=0; i<sn.length; i++) identityRemove( result, arr[i], entityName, getSession() );
final Object[] sn = (Object[]) snapshot;
final Object[] arr = (Object[]) array;
final ArrayList result = new ArrayList();
Collections.addAll( result, sn );
for ( int i=0; i<sn.length; i++ ) {
identityRemove( result, arr[i], entityName, getSession() );
}
return result;
}
public PersistentArrayHolder(SessionImplementor session, CollectionPersister persister) throws HibernateException {
super(session);
elementClass = persister.getElementClass();
}
@SuppressWarnings("UnusedDeclaration")
public Object getArray() {
return array;
}
@Override
public boolean isWrapper(Object collection) {
return array==collection;
}
@Override
public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException {
Type elementType = persister.getElementType();
Serializable snapshot = getSnapshot();
int xlen = Array.getLength(snapshot);
if ( xlen!= Array.getLength(array) ) return false;
final Type elementType = persister.getElementType();
final Serializable snapshot = getSnapshot();
final int xlen = Array.getLength( snapshot );
if ( xlen!= Array.getLength( array ) ) {
return false;
}
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;
}
/**
* Get an iterator over the array elements
*
* @return The iterator
*/
@SuppressWarnings("unchecked")
public Iterator elements() {
//if (array==null) return tempList.iterator();
int length = Array.getLength(array);
java.util.List list = new ArrayList(length);
for (int i=0; i<length; i++) {
list.add( Array.get(array, i) );
final int length = Array.getLength( array );
final java.util.List list = new ArrayList( length );
for ( int i=0; i<length; i++ ) {
list.add( Array.get( array, i ) );
}
return list.iterator();
}
@Override
public boolean empty() {
return false;
}
@Override
@SuppressWarnings("unchecked")
public Object readFrom(ResultSet rs, CollectionPersister persister, CollectionAliases descriptor, Object owner)
throws HibernateException, SQLException {
Object element = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() );
int index = (Integer) persister.readIndex( rs, descriptor.getSuffixedIndexAliases(), getSession() );
final Object element = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() );
final int index = (Integer) persister.readIndex( rs, descriptor.getSuffixedIndexAliases(), getSession() );
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;
}
@Override
@SuppressWarnings("unchecked")
public Iterator entries(CollectionPersister persister) {
return elements();
}
@ -151,17 +191,19 @@ public class PersistentArrayHolder extends AbstractPersistentCollection {
super.beginRead();
tempList = new ArrayList();
}
@Override
public boolean endRead() {
setInitialized();
array = Array.newInstance( elementClass, tempList.size() );
for ( int i=0; i<tempList.size(); i++) {
Array.set(array, i, tempList.get(i) );
for ( int i=0; i<tempList.size(); i++ ) {
Array.set( array, i, tempList.get( i ) );
}
tempList=null;
tempList = null;
return true;
}
@Override
public void beforeInitialize(CollectionPersister persister, int anticipatedSize) {
//if (tempList==null) throw new UnsupportedOperationException("Can't lazily initialize arrays");
}
@ -171,10 +213,10 @@ public class PersistentArrayHolder extends AbstractPersistentCollection {
return true;
}
@Override
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner)
throws HibernateException {
Serializable[] cached = (Serializable[]) disassembled;
final Serializable[] cached = (Serializable[]) disassembled;
array = Array.newInstance( persister.getElementClass(), cached.length );
for ( int i=0; i<cached.length; i++ ) {
@ -182,21 +224,15 @@ public class PersistentArrayHolder extends AbstractPersistentCollection {
}
}
@Override
public Serializable disassemble(CollectionPersister persister) throws HibernateException {
int length = Array.getLength(array);
Serializable[] result = new Serializable[length];
final int length = Array.getLength( array );
final Serializable[] result = new Serializable[length];
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;
}
@Override
@ -204,52 +240,63 @@ public class PersistentArrayHolder extends AbstractPersistentCollection {
return array;
}
@Override
public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) throws HibernateException {
java.util.List<Integer> deletes = new ArrayList<Integer>();
Serializable sn = getSnapshot();
int snSize = Array.getLength(sn);
int arraySize = Array.getLength(array);
final java.util.List<Integer> deletes = new ArrayList<Integer>();
final Serializable sn = getSnapshot();
final int snSize = Array.getLength( sn );
final int arraySize = Array.getLength( array );
int end;
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;
}
else {
end = snSize;
}
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();
}
@Override
public boolean needsInserting(Object entry, int i, Type elemType) throws HibernateException {
Serializable sn = getSnapshot();
return Array.get(array, i)!=null && ( i >= Array.getLength(sn) || Array.get(sn, i)==null );
final Serializable sn = getSnapshot();
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 {
Serializable sn = getSnapshot();
return i<Array.getLength(sn) &&
Array.get(sn, i)!=null &&
Array.get(array, i)!=null &&
elemType.isDirty( Array.get(array, i), Array.get(sn, i), getSession() );
final Serializable sn = getSnapshot();
return i < Array.getLength( sn )
&& Array.get( sn, i ) != null
&& Array.get( array, i ) != null
&& elemType.isDirty( Array.get( array, i ), Array.get( sn, i ), getSession() );
}
@Override
public Object getIndex(Object entry, int i, CollectionPersister persister) {
return i;
}
@Override
public Object getElement(Object entry) {
return entry;
}
@Override
public Object getSnapshotElement(Object entry, int i) {
Serializable sn = getSnapshot();
return Array.get(sn, i);
final Serializable sn = getSnapshot();
return Array.get( sn, i );
}
@Override
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;
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) {
super(session);
if (coll instanceof List) {
super( session );
if ( coll instanceof List ) {
bag = (List) coll;
}
else {
bag = new ArrayList();
Iterator iter = coll.iterator();
while ( iter.hasNext() ) {
bag.add( iter.next() );
for ( Object element : coll ) {
bag.add( element );
}
}
setInitialized();
setDirectlyAccessible(true);
setDirectlyAccessible( true );
}
public PersistentBag() {} //needed for SOAP libraries, etc
@Override
public boolean isWrapper(Object collection) {
return bag==collection;
}
@Override
public boolean empty() {
return bag.isEmpty();
}
@Override
public Iterator entries(CollectionPersister persister) {
return bag.iterator();
}
@Override
@SuppressWarnings("unchecked")
public Object readFrom(ResultSet rs, CollectionPersister persister, CollectionAliases descriptor, Object owner)
throws HibernateException, SQLException {
// note that if we load this collection from a cartesian product
// the multiplicity would be broken ... so use an idbag instead
Object element = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() ) ;
if (element!=null) bag.add(element);
final Object element = persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() ) ;
if ( element != null ) {
bag.add( element );
}
return element;
}
@Override
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 {
Type elementType = persister.getElementType();
List sn = (List) getSnapshot();
if ( sn.size()!=bag.size() ) return false;
final Type elementType = persister.getElementType();
final List sn = (List) getSnapshot();
if ( sn.size() != bag.size() ) {
return false;
}
for ( Object elt : bag ) {
final boolean unequal = countOccurrences( elt, bag, elementType )
!= countOccurrences( elt, sn, elementType );
final boolean unequal = countOccurrences( elt, bag, elementType ) != countOccurrences( elt, sn, elementType );
if ( unequal ) {
return false;
}
@ -110,60 +137,67 @@ public class PersistentBag extends AbstractPersistentCollection implements List
return true;
}
@Override
public boolean isSnapshotEmpty(Serializable snapshot) {
return ( (Collection) snapshot ).isEmpty();
}
private int countOccurrences(Object element, List list, Type elementType)
throws HibernateException {
Iterator iter = list.iterator();
int result=0;
final Iterator iter = list.iterator();
int result = 0;
while ( iter.hasNext() ) {
if ( elementType.isSame( element, iter.next() ) ) result++;
if ( elementType.isSame( element, iter.next() ) ) {
result++;
}
}
return result;
}
@Override
@SuppressWarnings("unchecked")
public Serializable getSnapshot(CollectionPersister persister)
throws HibernateException {
ArrayList clonedList = new ArrayList( bag.size() );
Iterator iter = bag.iterator();
while ( iter.hasNext() ) {
clonedList.add( persister.getElementType().deepCopy( iter.next(), persister.getFactory() ) );
final ArrayList clonedList = new ArrayList( bag.size() );
for ( Object item : bag ) {
clonedList.add( persister.getElementType().deepCopy( item, persister.getFactory() ) );
}
return clonedList;
}
@Override
public Collection getOrphans(Serializable snapshot, String entityName) throws HibernateException {
List sn = (List) snapshot;
final List sn = (List) snapshot;
return getOrphans( sn, bag, entityName, getSession() );
}
@Override
public Serializable disassemble(CollectionPersister persister)
throws HibernateException {
int length = bag.size();
Serializable[] result = new Serializable[length];
final int length = bag.size();
final Serializable[] result = new Serializable[length];
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;
}
@Override
@SuppressWarnings("unchecked")
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner)
throws HibernateException {
Serializable[] array = (Serializable[]) disassembled;
int size = array.length;
final Serializable[] array = (Serializable[]) disassembled;
final int size = array.length;
beforeInitialize( persister, size );
for ( int i = 0; i < size; i++ ) {
Object element = persister.getElementType().assemble( array[i], getSession(), owner );
if ( element!=null ) {
for ( Serializable item : array ) {
final Object element = persister.getElementType().assemble( item, getSession(), owner );
if ( element != null ) {
bag.add( element );
}
}
}
@Override
public boolean needsRecreate(CollectionPersister persister) {
return !persister.isOneToMany();
}
@ -177,18 +211,19 @@ public class PersistentBag extends AbstractPersistentCollection implements List
// Anyway, here we implement <set> semantics for a
// <one-to-many> <bag>!
@Override
@SuppressWarnings("unchecked")
public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) throws HibernateException {
//if ( !persister.isOneToMany() ) throw new AssertionFailure("Not implemented for Bags");
Type elementType = persister.getElementType();
ArrayList deletes = new ArrayList();
List sn = (List) getSnapshot();
Iterator olditer = sn.iterator();
final Type elementType = persister.getElementType();
final ArrayList deletes = new ArrayList();
final List sn = (List) getSnapshot();
final Iterator olditer = sn.iterator();
int i=0;
while ( olditer.hasNext() ) {
Object old = olditer.next();
Iterator newiter = bag.iterator();
final Object old = olditer.next();
final Iterator newiter = bag.iterator();
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!
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();
}
@Override
public boolean needsInserting(Object entry, int i, Type elemType) throws HibernateException {
//if ( !persister.isOneToMany() ) throw new AssertionFailure("Not implemented for Bags");
List sn = (List) getSnapshot();
if ( sn.size()>i && elemType.isSame( sn.get(i), entry ) ) {
final List sn = (List) getSnapshot();
if ( sn.size() > i && elemType.isSame( sn.get( i ), entry ) ) {
//a shortcut if its location didn't change!
return false;
}
else {
//search for it
//note that this code is incorrect for other than one-to-many
Iterator olditer = sn.iterator();
while ( olditer.hasNext() ) {
Object old = olditer.next();
if ( elemType.isSame( old, entry ) ) return false;
for ( Object old : sn ) {
if ( elemType.isSame( old, entry ) ) {
return false;
}
}
return true;
}
}
@Override
public boolean isRowUpdatePossible() {
return false;
}
@Override
public boolean needsUpdating(Object entry, int i, Type elemType) {
//if ( !persister.isOneToMany() ) throw new AssertionFailure("Not implemented for Bags");
return false;
}
/**
* @see java.util.Collection#size()
*/
@Override
public int size() {
return readSize() ? getCachedSize() : bag.size();
}
/**
* @see java.util.Collection#isEmpty()
*/
@Override
public boolean isEmpty() {
return readSize() ? getCachedSize()==0 : bag.isEmpty();
}
/**
* @see java.util.Collection#contains(Object)
*/
@Override
@SuppressWarnings("UnnecessaryUnboxing")
public boolean contains(Object object) {
Boolean exists = readElementExistence(object);
return exists==null ?
bag.contains(object) :
exists.booleanValue();
final Boolean exists = readElementExistence( object );
return exists == null ? bag.contains( object ) : exists.booleanValue();
}
/**
* @see java.util.Collection#iterator()
*/
@Override
public Iterator iterator() {
read();
return new IteratorProxy( bag.iterator() );
}
/**
* @see java.util.Collection#toArray()
*/
@Override
public Object[] toArray() {
read();
return bag.toArray();
}
/**
* @see java.util.Collection#toArray(Object[])
*/
@Override
public Object[] toArray(Object[] a) {
read();
return bag.toArray(a);
return bag.toArray( a );
}
/**
* @see java.util.Collection#add(Object)
*/
@Override
@SuppressWarnings("unchecked")
public boolean add(Object object) {
if ( !isOperationQueueEnabled() ) {
write();
return bag.add(object);
return bag.add( object );
}
else {
queueOperation( new SimpleAdd(object) );
queueOperation( new SimpleAdd( object ) );
return true;
}
}
/**
* @see java.util.Collection#remove(Object)
*/
@Override
public boolean remove(Object o) {
initialize( true );
if ( bag.remove( o ) ) {
@ -311,35 +333,33 @@ public class PersistentBag extends AbstractPersistentCollection implements List
}
}
/**
* @see java.util.Collection#containsAll(Collection)
*/
@Override
@SuppressWarnings("unchecked")
public boolean containsAll(Collection c) {
read();
return bag.containsAll(c);
return bag.containsAll( c );
}
/**
* @see java.util.Collection#addAll(Collection)
*/
@Override
@SuppressWarnings("unchecked")
public boolean addAll(Collection values) {
if ( values.size()==0 ) return false;
if ( values.size()==0 ) {
return false;
}
if ( !isOperationQueueEnabled() ) {
write();
return bag.addAll(values);
return bag.addAll( values );
}
else {
Iterator iter = values.iterator();
while ( iter.hasNext() ) {
queueOperation( new SimpleAdd( iter.next() ) );
for ( Object value : values ) {
queueOperation( new SimpleAdd( value ) );
}
return values.size()>0;
}
}
/**
* @see java.util.Collection#removeAll(Collection)
*/
@Override
@SuppressWarnings("unchecked")
public boolean removeAll(Collection c) {
if ( c.size()>0 ) {
initialize( true );
@ -356,9 +376,8 @@ public class PersistentBag extends AbstractPersistentCollection implements List
}
}
/**
* @see java.util.Collection#retainAll(Collection)
*/
@Override
@SuppressWarnings("unchecked")
public boolean retainAll(Collection c) {
initialize( true );
if ( bag.retainAll( c ) ) {
@ -370,9 +389,8 @@ public class PersistentBag extends AbstractPersistentCollection implements List
}
}
/**
* @see java.util.Collection#clear()
*/
@Override
@SuppressWarnings("unchecked")
public void clear() {
if ( isClearQueueEnabled() ) {
queueOperation( new Clear() );
@ -386,160 +404,161 @@ public class PersistentBag extends AbstractPersistentCollection implements List
}
}
@Override
public Object getIndex(Object entry, int i, CollectionPersister persister) {
throw new UnsupportedOperationException("Bags don't have indexes");
}
@Override
public Object getElement(Object entry) {
return entry;
}
@Override
public Object getSnapshotElement(Object entry, int i) {
List sn = (List) getSnapshot();
return sn.get(i);
final List sn = (List) getSnapshot();
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) {
read();
Iterator iter = bag.iterator();
int result=0;
while ( iter.hasNext() ) {
if ( o.equals( iter.next() ) ) result++;
final Iterator itr = bag.iterator();
int result = 0;
while ( itr.hasNext() ) {
if ( o.equals( itr.next() ) ) {
result++;
}
}
return result;
}
// List OPERATIONS:
/**
* @see java.util.List#add(int, Object)
*/
@Override
@SuppressWarnings("unchecked")
public void add(int i, Object o) {
write();
bag.add(i, o);
bag.add( i, o );
}
/**
* @see java.util.List#addAll(int, Collection)
*/
@Override
@SuppressWarnings("unchecked")
public boolean addAll(int i, Collection c) {
if ( c.size()>0 ) {
if ( c.size() > 0 ) {
write();
return bag.addAll(i, c);
return bag.addAll( i, c );
}
else {
return false;
}
}
/**
* @see java.util.List#get(int)
*/
@Override
@SuppressWarnings("unchecked")
public Object get(int i) {
read();
return bag.get(i);
return bag.get( i );
}
/**
* @see java.util.List#indexOf(Object)
*/
@Override
@SuppressWarnings("unchecked")
public int indexOf(Object o) {
read();
return bag.indexOf(o);
return bag.indexOf( o );
}
/**
* @see java.util.List#lastIndexOf(Object)
*/
@Override
@SuppressWarnings("unchecked")
public int lastIndexOf(Object o) {
read();
return bag.lastIndexOf(o);
return bag.lastIndexOf( o );
}
/**
* @see java.util.List#listIterator()
*/
@Override
@SuppressWarnings("unchecked")
public ListIterator listIterator() {
read();
return new ListIteratorProxy( bag.listIterator() );
}
/**
* @see java.util.List#listIterator(int)
*/
@Override
@SuppressWarnings("unchecked")
public ListIterator listIterator(int i) {
read();
return new ListIteratorProxy( bag.listIterator(i) );
return new ListIteratorProxy( bag.listIterator( i ) );
}
/**
* @see java.util.List#remove(int)
*/
@Override
@SuppressWarnings("unchecked")
public Object remove(int i) {
write();
return bag.remove(i);
return bag.remove( i );
}
/**
* @see java.util.List#set(int, Object)
*/
@Override
@SuppressWarnings("unchecked")
public Object set(int i, Object o) {
write();
return bag.set(i, o);
return bag.set( i, o );
}
/**
* @see java.util.List#subList(int, int)
*/
@Override
@SuppressWarnings("unchecked")
public List subList(int start, int end) {
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() {
read();
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
* JVM instance comparison to do the equals.
* The semantic is broken not to have to initialize a
* collection for a simple equals() operation.
* @see java.lang.Object#equals(java.lang.Object)
*
* {@inheritDoc}
*/
@Override
public boolean equals(Object obj) {
return super.equals(obj);
return super.equals( obj );
}
/**
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return super.hashCode();
}
final class Clear implements DelayedOperation {
@Override
public void operate() {
bag.clear();
}
@Override
public Object getAddedInstance() {
return null;
}
@Override
public Object getOrphan() {
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) {
this.value = value;
}
@Override
@SuppressWarnings("unchecked")
public void operate() {
bag.add(value);
bag.add( value );
}
@Override
public Object getAddedInstance() {
return value;
}
@Override
public Object getOrphan() {
return null;
}

View File

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

View File

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

View File

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

View File

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

View File

@ -35,6 +35,8 @@ import org.hibernate.type.IntegerType;
import org.hibernate.type.Type;
/**
* Wraps a collection of DOM sub-elements as a List
*
* @author Gavin King
*
* @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.
*/
@Deprecated
@SuppressWarnings({"UnusedDeclaration", "deprecation"})
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) {
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 );
}
@Override
@SuppressWarnings("deprecation")
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner)
throws HibernateException {
Type elementType = persister.getElementType();
final String indexNodeName = getIndexAttributeName(persister);
Serializable[] cached = (Serializable[]) disassembled;
final Type elementType = persister.getElementType();
final String indexNodeName = getIndexAttributeName( persister );
final Serializable[] cached = (Serializable[]) disassembled;
for ( int i=0; i<cached.length; i++ ) {
Object object = elementType.assemble( cached[i], getSession(), owner );
Element subelement = element.addElement( persister.getElementNodeName() );
final Object object = elementType.assemble( cached[i], getSession(), owner );
final Element subelement = element.addElement( persister.getElementNodeName() );
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 {
Type elementType = persister.getElementType();
final String indexNodeName = getIndexAttributeName(persister);
List elements = element.elements( persister.getElementNodeName() );
int length = elements.size();
Serializable[] result = new Serializable[length];
final Type elementType = persister.getElementType();
final String indexNodeName = getIndexAttributeName( persister );
final List elements = element.elements( persister.getElementNodeName() );
final int length = elements.size();
final Serializable[] result = new Serializable[length];
for ( int i=0; i<length; i++ ) {
Element elem = (Element) elements.get(i);
Object object = elementType.fromXMLNode( elem, persister.getFactory() );
Integer index = IntegerType.INSTANCE.fromString( getIndex(elem, indexNodeName, i) );
final Element elem = (Element) elements.get( i );
final Object object = elementType.fromXMLNode( elem, persister.getFactory() );
final Integer index = IntegerType.INSTANCE.fromString( getIndex( elem, indexNodeName, i ) );
result[index] = elementType.disassemble( object, getSession(), null );
}
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.
*/
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.
*/
public PersistentMap(SessionImplementor session, Map map) {
super(session);
super( session );
this.map = map;
setInitialized();
setDirectlyAccessible(true);
setDirectlyAccessible( true );
}
@Override
@SuppressWarnings( {"unchecked"})
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() ) {
Entry e = (Entry) o;
final Entry e = (Entry) o;
final Object copy = persister.getElementType().deepCopy( e.getValue(), persister.getFactory() );
clonedMap.put( e.getKey(), copy );
}
return clonedMap;
}
@Override
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() );
}
@Override
public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException {
Type elementType = persister.getElementType();
Map xmap = (Map) getSnapshot();
if ( xmap.size()!=this.map.size() ) return false;
Iterator iter = map.entrySet().iterator();
while ( iter.hasNext() ) {
Map.Entry entry = (Map.Entry) iter.next();
if ( elementType.isDirty( entry.getValue(), xmap.get( entry.getKey() ), getSession() ) ) return false;
final Type elementType = persister.getElementType();
final Map snapshotMap = (Map) getSnapshot();
if ( snapshotMap.size() != this.map.size() ) {
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;
}
@Override
public boolean isSnapshotEmpty(Serializable snapshot) {
return ( (Map) snapshot ).isEmpty();
}
@Override
public boolean isWrapper(Object collection) {
return map==collection;
}
@Override
public void beforeInitialize(CollectionPersister persister, int anticipatedSize) {
this.map = ( Map ) persister.getCollectionType().instantiate( anticipatedSize );
this.map = (Map) persister.getCollectionType().instantiate( anticipatedSize );
}
/**
* @see java.util.Map#size()
*/
@Override
public int size() {
return readSize() ? getCachedSize() : map.size();
}
/**
* @see java.util.Map#isEmpty()
*/
@Override
public boolean isEmpty() {
return readSize() ? getCachedSize()==0 : map.isEmpty();
}
/**
* @see java.util.Map#containsKey(Object)
*/
@Override
@SuppressWarnings("UnnecessaryUnboxing")
public boolean containsKey(Object key) {
Boolean exists = readIndexExistence(key);
return exists==null ? map.containsKey(key) : exists.booleanValue();
final Boolean exists = readIndexExistence( key );
return exists == null ? map.containsKey( key ) : exists.booleanValue();
}
/**
* @see java.util.Map#containsValue(Object)
*/
@Override
@SuppressWarnings("UnnecessaryUnboxing")
public boolean containsValue(Object value) {
Boolean exists = readElementExistence(value);
return exists==null ?
map.containsValue(value) :
exists.booleanValue();
final Boolean exists = readElementExistence( value );
return exists == null
? map.containsValue( value )
: exists.booleanValue();
}
/**
* @see java.util.Map#get(Object)
*/
@Override
public Object get(Object key) {
Object result = readElementByIndex(key);
return result==UNKNOWN ? map.get(key) : result;
final Object result = readElementByIndex( key );
return result == UNKNOWN
? map.get( key )
: result;
}
/**
* @see java.util.Map#put(Object, Object)
*/
@Override
@SuppressWarnings("unchecked")
public Object put(Object key, Object value) {
if ( isPutQueueEnabled() ) {
Object old = readElementByIndex( key );
final Object old = readElementByIndex( key );
if ( old != UNKNOWN ) {
queueOperation( new Put( key, value, old ) );
return old;
}
}
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
// whether the old and the new are equal here; the problem being
// 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;
}
/**
* @see java.util.Map#remove(Object)
*/
@Override
@SuppressWarnings("unchecked")
public Object remove(Object key) {
if ( isPutQueueEnabled() ) {
Object old = readElementByIndex( key );
final Object old = readElementByIndex( key );
if ( old != UNKNOWN ) {
queueOperation( new Remove( key, old ) );
return old;
@ -208,23 +209,20 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
return map.remove( key );
}
/**
* @see java.util.Map#putAll(java.util.Map puts)
*/
@Override
@SuppressWarnings("unchecked")
public void putAll(Map puts) {
if ( puts.size()>0 ) {
if ( puts.size() > 0 ) {
initialize( true );
Iterator itr = puts.entrySet().iterator();
while ( itr.hasNext() ) {
Map.Entry entry = ( Entry ) itr.next();
for ( Object o : puts.entrySet() ) {
final Entry entry = (Entry) o;
put( entry.getKey(), entry.getValue() );
}
}
}
/**
* @see java.util.Map#clear()
*/
@Override
@SuppressWarnings("unchecked")
public void clear() {
if ( isClearQueueEnabled() ) {
queueOperation( new Clear() );
@ -238,34 +236,35 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
}
}
/**
* @see java.util.Map#keySet()
*/
@Override
@SuppressWarnings("unchecked")
public Set keySet() {
read();
return new SetProxy( map.keySet() );
}
/**
* @see java.util.Map#values()
*/
@Override
@SuppressWarnings("unchecked")
public Collection values() {
read();
return new SetProxy( map.values() );
}
/**
* @see java.util.Map#entrySet()
*/
@Override
@SuppressWarnings("unchecked")
public Set entrySet() {
read();
return new EntrySetProxy( map.entrySet() );
}
@Override
@SuppressWarnings("unchecked")
public boolean empty() {
return map.isEmpty();
}
@Override
@SuppressWarnings("unchecked")
public String toString() {
read();
return map.toString();
@ -273,6 +272,8 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
private transient List<Object[]> loadingEntries;
@Override
@SuppressWarnings("unchecked")
public Object readFrom(
ResultSet rs,
CollectionPersister persister,
@ -301,75 +302,129 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
return super.endRead();
}
@Override
@SuppressWarnings("unchecked")
public Iterator entries(CollectionPersister persister) {
return map.entrySet().iterator();
}
/** a wrapper for Map.Entry sets */
/**
* a wrapper for Map.Entry sets
*/
class EntrySetProxy implements Set {
private final Set set;
EntrySetProxy(Set set) {
this.set=set;
}
@Override
@SuppressWarnings("unchecked")
public boolean add(Object entry) {
//write(); -- doesn't
return set.add(entry);
return set.add( entry );
}
@Override
@SuppressWarnings("unchecked")
public boolean addAll(Collection entries) {
//write(); -- doesn't
return set.addAll(entries);
return set.addAll( entries );
}
@Override
@SuppressWarnings("unchecked")
public void clear() {
write();
set.clear();
}
@Override
@SuppressWarnings("unchecked")
public boolean contains(Object entry) {
return set.contains(entry);
return set.contains( entry );
}
@Override
@SuppressWarnings("unchecked")
public boolean containsAll(Collection entries) {
return set.containsAll(entries);
return set.containsAll( entries );
}
@Override
@SuppressWarnings("unchecked")
public boolean isEmpty() {
return set.isEmpty();
}
@Override
@SuppressWarnings("unchecked")
public Iterator iterator() {
return new EntryIteratorProxy( set.iterator() );
}
@Override
@SuppressWarnings("unchecked")
public boolean remove(Object entry) {
write();
return set.remove(entry);
return set.remove( entry );
}
@Override
@SuppressWarnings("unchecked")
public boolean removeAll(Collection entries) {
write();
return set.removeAll(entries);
return set.removeAll( entries );
}
@Override
@SuppressWarnings("unchecked")
public boolean retainAll(Collection entries) {
write();
return set.retainAll(entries);
return set.retainAll( entries );
}
@Override
@SuppressWarnings("unchecked")
public int size() {
return set.size();
}
// amazingly, these two will work because AbstractCollection
// uses iterator() to fill the array
@Override
@SuppressWarnings("unchecked")
public Object[] toArray() {
return set.toArray();
}
@Override
@SuppressWarnings("unchecked")
public Object[] toArray(Object[] array) {
return set.toArray(array);
return set.toArray( array );
}
}
final class EntryIteratorProxy implements Iterator {
private final Iterator iter;
EntryIteratorProxy(Iterator iter) {
this.iter=iter;
}
@Override
@SuppressWarnings("unchecked")
public boolean hasNext() {
return iter.hasNext();
}
@Override
@SuppressWarnings("unchecked")
public Object next() {
return new MapEntryProxy( (Map.Entry) iter.next() );
}
@Override
@SuppressWarnings("unchecked")
public void remove() {
write();
iter.remove();
@ -381,21 +436,46 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
MapEntryProxy( Map.Entry me ) {
this.me = me;
}
public Object getKey() { return me.getKey(); }
public Object getValue() { return me.getValue(); }
public boolean equals(Object o) { return me.equals(o); }
public int hashCode() { return me.hashCode(); }
@Override
@SuppressWarnings("unchecked")
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...
@Override
@SuppressWarnings("unchecked")
public Object setValue(Object value) {
write();
return me.setValue(value);
return me.setValue( value );
}
}
@Override
@SuppressWarnings("unchecked")
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner)
throws HibernateException {
Serializable[] array = ( Serializable[] ) disassembled;
int size = array.length;
final Serializable[] array = (Serializable[]) disassembled;
final int size = array.length;
beforeInitialize( persister, size );
for ( int i = 0; i < size; i+=2 ) {
map.put(
@ -405,13 +485,14 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
}
}
@Override
@SuppressWarnings("unchecked")
public Serializable disassemble(CollectionPersister persister) throws HibernateException {
Serializable[] result = new Serializable[ map.size() * 2 ];
Iterator iter = map.entrySet().iterator();
final Serializable[] result = new Serializable[ map.size() * 2 ];
final Iterator itr = map.entrySet().iterator();
int i=0;
while ( iter.hasNext() ) {
Map.Entry e = (Map.Entry) iter.next();
while ( itr.hasNext() ) {
final Map.Entry e = (Map.Entry) itr.next();
result[i++] = persister.getIndexType().disassemble( e.getKey(), 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)
throws HibernateException {
List deletes = new ArrayList();
Iterator iter = ( (Map) getSnapshot() ).entrySet().iterator();
while ( iter.hasNext() ) {
Map.Entry e = (Map.Entry) iter.next();
Object key = e.getKey();
if ( e.getValue()!=null && map.get(key)==null ) {
@Override
@SuppressWarnings("unchecked")
public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula) throws HibernateException {
final List deletes = new ArrayList();
for ( Object o : ((Map) getSnapshot()).entrySet() ) {
final Entry e = (Entry) o;
final Object key = e.getKey();
if ( e.getValue() != null && map.get( key ) == null ) {
deletes.add( indexIsFormula ? e.getValue() : key );
}
}
return deletes.iterator();
}
public boolean needsInserting(Object entry, int i, Type elemType)
throws HibernateException {
@Override
@SuppressWarnings("unchecked")
public boolean needsInserting(Object entry, int i, Type elemType) throws HibernateException {
final Map sn = (Map) getSnapshot();
Map.Entry e = (Map.Entry) entry;
return e.getValue()!=null && sn.get( e.getKey() )==null;
final Map.Entry e = (Map.Entry) entry;
return e.getValue() != null && sn.get( e.getKey() ) == null;
}
public boolean needsUpdating(Object entry, int i, Type elemType)
throws HibernateException {
@Override
@SuppressWarnings("unchecked")
public boolean needsUpdating(Object entry, int i, Type elemType) throws HibernateException {
final Map sn = (Map) getSnapshot();
Map.Entry e = (Map.Entry) entry;
Object snValue = sn.get( e.getKey() );
return e.getValue()!=null &&
snValue!=null &&
elemType.isDirty( snValue, e.getValue(), getSession() );
final Map.Entry e = (Map.Entry) entry;
final Object snValue = sn.get( e.getKey() );
return e.getValue() != null
&& snValue != null
&& elemType.isDirty( snValue, e.getValue(), getSession() );
}
@Override
@SuppressWarnings("unchecked")
public Object getIndex(Object entry, int i, CollectionPersister persister) {
return ( (Map.Entry) entry ).getKey();
}
@Override
@SuppressWarnings("unchecked")
public Object getElement(Object entry) {
return ( (Map.Entry) entry ).getValue();
}
@Override
@SuppressWarnings("unchecked")
public Object getSnapshotElement(Object entry, int i) {
final Map sn = (Map) getSnapshot();
return sn.get( ( (Map.Entry) entry ).getKey() );
}
@Override
@SuppressWarnings({"unchecked", "EqualsWhichDoesntCheckParameterClass"})
public boolean equals(Object other) {
read();
return map.equals(other);
return map.equals( other );
}
@Override
@SuppressWarnings("unchecked")
public int hashCode() {
read();
return map.hashCode();
}
@Override
@SuppressWarnings("unchecked")
public boolean entryExists(Object entry, int i) {
return ( (Map.Entry) entry ).getValue()!=null;
return ( (Map.Entry) entry ).getValue() != null;
}
final class Clear implements DelayedOperation {
@Override
public void operate() {
map.clear();
}
@Override
public Object getAddedInstance() {
return null;
}
@Override
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.old = old;
}
@Override
@SuppressWarnings("unchecked")
public void operate() {
map.put(index, value);
map.put( index, value );
}
@Override
@SuppressWarnings("unchecked")
public Object getAddedInstance() {
return value;
}
@Override
@SuppressWarnings("unchecked")
public Object getOrphan() {
return old;
}
@ -519,12 +627,19 @@ public class PersistentMap extends AbstractPersistentCollection implements Map {
this.index = index;
this.old = old;
}
@Override
@SuppressWarnings("unchecked")
public void operate() {
map.remove(index);
map.remove( index );
}
@Override
public Object getAddedInstance() {
return null;
}
@Override
public Object getOrphan() {
return old;
}

View File

@ -35,60 +35,76 @@ import org.hibernate.type.Type;
import org.hibernate.type.XmlRepresentableType;
/**
* Wraps a collection of DOM sub-elements as a Map
*
* @author Gavin King
*
* @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-7783">HHH-7783</a> for more information.
*/
@SuppressWarnings({"UnusedDeclaration", "deprecation"})
@Deprecated
public class PersistentMapElementHolder extends PersistentIndexedElementHolder {
/**
* Constructs a PersistentMapElementHolder.
*
* @param session The session
* @param element The owning DOM element
*/
public PersistentMapElementHolder(SessionImplementor session, Element 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 );
}
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner)
throws HibernateException {
@Override
@SuppressWarnings("unchecked")
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner) {
final Type elementType = persister.getElementType();
final Type indexType = persister.getIndexType();
final String indexNodeName = getIndexAttributeName( persister );
Type elementType = persister.getElementType();
Type indexType = persister.getIndexType();
final String indexNodeName = getIndexAttributeName(persister);
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 );
Serializable[] cached = (Serializable[]) disassembled;
for ( int i=0; i<cached.length; ) {
Object index = indexType.assemble( cached[i++], getSession(), owner );
Object object = elementType.assemble( cached[i++], getSession(), owner );
Element subelement = element.addElement( persister.getElementNodeName() );
elementType.setToXMLNode( subelement, object, persister.getFactory() );
String indexString = ( (XmlRepresentableType) indexType ).toXMLString( index, persister.getFactory() );
setIndex( subelement, indexNodeName, indexString );
}
final Element subElement = element.addElement( persister.getElementNodeName() );
elementType.setToXMLNode( subElement, object, persister.getFactory() );
final String indexString = ( (XmlRepresentableType) indexType ).toXMLString( index, persister.getFactory() );
setIndex( subElement, indexNodeName, indexString );
}
}
@Override
@SuppressWarnings("unchecked")
public Serializable disassemble(CollectionPersister persister) throws HibernateException {
final Type elementType = persister.getElementType();
final Type indexType = persister.getIndexType();
final String indexNodeName = getIndexAttributeName( persister );
Type elementType = persister.getElementType();
Type indexType = persister.getIndexType();
final String indexNodeName = getIndexAttributeName(persister);
List elements = element.elements( persister.getElementNodeName() );
int length = elements.size();
Serializable[] result = new Serializable[length*2];
for ( int i=0; i<length*2; ) {
Element elem = (Element) elements.get(i/2);
Object object = elementType.fromXMLNode( elem, persister.getFactory() );
final String indexString = getIndex(elem, indexNodeName, i);
Object index = ( (XmlRepresentableType) indexType ).fromXMLString( indexString, persister.getFactory() );
final List elements = element.elements( persister.getElementNodeName() );
final int length = elements.size();
final Serializable[] result = new Serializable[length*2];
int i = 0;
while ( i < length*2 ) {
final Element elem = (Element) elements.get(i/2);
final Object object = elementType.fromXMLNode( elem, 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++] = elementType.disassemble( object, getSession(), null );
}

View File

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

View File

@ -26,7 +26,6 @@ package org.hibernate.collection.internal;
import java.io.Serializable;
import java.util.Collection;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
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>
*/
public class PersistentSortedMap extends PersistentMap implements SortedMap {
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 {
TreeMap clonedMap = new TreeMap(comparator);
Iterator iter = map.entrySet().iterator();
while ( iter.hasNext() ) {
Map.Entry e = (Map.Entry) iter.next();
final TreeMap clonedMap = new TreeMap( comparator );
for ( Object o : map.entrySet() ) {
final Entry e = (Entry) o;
clonedMap.put( e.getKey(), persister.getElementType().deepCopy( e.getValue(), persister.getFactory() ) );
}
return clonedMap;
}
public PersistentSortedMap(SessionImplementor session) {
super(session);
}
public void setComparator(Comparator comparator) {
this.comparator = comparator;
}
public PersistentSortedMap(SessionImplementor session, SortedMap map) {
super(session, map);
comparator = map.comparator();
}
public PersistentSortedMap() {} //needed for SOAP libraries, etc
/**
* @see PersistentSortedMap#comparator()
*/
@Override
public Comparator comparator() {
return comparator;
}
/**
* @see PersistentSortedMap#subMap(Object, Object)
*/
@Override
@SuppressWarnings("unchecked")
public SortedMap subMap(Object fromKey, Object toKey) {
read();
SortedMap m = ( (SortedMap) map ).subMap(fromKey, toKey);
return new SortedSubMap(m);
final SortedMap subMap = ( (SortedMap) map ).subMap( fromKey, toKey );
return new SortedSubMap( subMap );
}
/**
* @see PersistentSortedMap#headMap(Object)
*/
@Override
@SuppressWarnings("unchecked")
public SortedMap headMap(Object toKey) {
read();
SortedMap m;
m = ( (SortedMap) map ).headMap(toKey);
return new SortedSubMap(m);
final SortedMap headMap = ( (SortedMap) map ).headMap( toKey );
return new SortedSubMap( headMap );
}
/**
* @see PersistentSortedMap#tailMap(Object)
*/
@Override
@SuppressWarnings("unchecked")
public SortedMap tailMap(Object fromKey) {
read();
SortedMap m;
m = ( (SortedMap) map ).tailMap(fromKey);
return new SortedSubMap(m);
final SortedMap tailMap = ( (SortedMap) map ).tailMap( fromKey );
return new SortedSubMap( tailMap );
}
/**
* @see PersistentSortedMap#firstKey()
*/
@Override
@SuppressWarnings("unchecked")
public Object firstKey() {
read();
return ( (SortedMap) map ).firstKey();
}
/**
* @see PersistentSortedMap#lastKey()
*/
@Override
@SuppressWarnings("unchecked")
public Object lastKey() {
read();
return ( (SortedMap) map ).lastKey();
}
class SortedSubMap implements SortedMap {
SortedMap subMap;
SortedMap submap;
SortedSubMap(SortedMap m) {
this.submap = m;
SortedSubMap(SortedMap subMap) {
this.subMap = subMap;
}
// from Map
@Override
@SuppressWarnings("unchecked")
public int size() {
return submap.size();
return subMap.size();
}
@Override
@SuppressWarnings("unchecked")
public boolean isEmpty() {
return submap.isEmpty();
return subMap.isEmpty();
}
@Override
@SuppressWarnings("unchecked")
public boolean containsKey(Object key) {
return submap.containsKey(key);
return subMap.containsKey( key );
}
@Override
@SuppressWarnings("unchecked")
public boolean containsValue(Object key) {
return submap.containsValue(key) ;
return subMap.containsValue( key ) ;
}
@Override
@SuppressWarnings("unchecked")
public Object get(Object key) {
return submap.get(key);
return subMap.get( key );
}
@Override
@SuppressWarnings("unchecked")
public Object put(Object key, Object value) {
write();
return submap.put(key, value);
return subMap.put( key, value );
}
@Override
@SuppressWarnings("unchecked")
public Object remove(Object key) {
write();
return submap.remove(key);
return subMap.remove( key );
}
@Override
@SuppressWarnings("unchecked")
public void putAll(Map other) {
write();
submap.putAll(other);
subMap.putAll( other );
}
@Override
@SuppressWarnings("unchecked")
public void clear() {
write();
submap.clear();
subMap.clear();
}
@Override
@SuppressWarnings("unchecked")
public Set keySet() {
return new SetProxy( submap.keySet() );
return new SetProxy( subMap.keySet() );
}
@Override
@SuppressWarnings("unchecked")
public Collection values() {
return new SetProxy( submap.values() );
return new SetProxy( subMap.values() );
}
@Override
@SuppressWarnings("unchecked")
public Set entrySet() {
return new EntrySetProxy( submap.entrySet() );
return new EntrySetProxy( subMap.entrySet() );
}
// from SortedMap
@Override
@SuppressWarnings("unchecked")
public Comparator comparator() {
return submap.comparator();
return subMap.comparator();
}
@Override
@SuppressWarnings("unchecked")
public SortedMap subMap(Object fromKey, Object toKey) {
SortedMap m;
m = submap.subMap(fromKey, toKey);
return new SortedSubMap( m );
final SortedMap subMap = this.subMap.subMap( fromKey, toKey );
return new SortedSubMap( subMap );
}
@Override
@SuppressWarnings("unchecked")
public SortedMap headMap(Object toKey) {
SortedMap m;
m = submap.headMap(toKey);
return new SortedSubMap(m);
final SortedMap headMap = subMap.headMap( toKey );
return new SortedSubMap( headMap );
}
@Override
@SuppressWarnings("unchecked")
public SortedMap tailMap(Object fromKey) {
SortedMap m;
m = submap.tailMap(fromKey);
return new SortedSubMap(m);
final SortedMap tailMap = subMap.tailMap( fromKey );
return new SortedSubMap( tailMap );
}
@Override
@SuppressWarnings("unchecked")
public Object firstKey() {
return submap.firstKey();
return subMap.firstKey();
}
@Override
@SuppressWarnings("unchecked")
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.util.Comparator;
import java.util.Iterator;
import java.util.SortedSet;
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>
*/
public class PersistentSortedSet extends PersistentSet implements SortedSet {
protected Comparator comparator;
/**
* Constructs a PersistentSortedSet. This form needed for SOAP libraries, etc
*/
@SuppressWarnings("UnusedDeclaration")
public PersistentSortedSet() {
}
/**
* 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 {
//if (set==null) return new Set(session);
TreeMap clonedSet = new TreeMap(comparator);
Iterator iter = set.iterator();
while ( iter.hasNext() ) {
Object copy = persister.getElementType().deepCopy( iter.next(), persister.getFactory() );
clonedSet.put(copy, copy);
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;
}
@ -61,106 +85,91 @@ public class PersistentSortedSet extends PersistentSet implements SortedSet {
this.comparator = comparator;
}
public PersistentSortedSet(SessionImplementor session) {
super(session);
}
public PersistentSortedSet(SessionImplementor session, SortedSet set) {
super(session, set);
comparator = set.comparator();
}
public PersistentSortedSet() {} //needed for SOAP libraries, etc
/**
* @see PersistentSortedSet#comparator()
*/
@Override
public Comparator comparator() {
return comparator;
}
/**
* @see PersistentSortedSet#subSet(Object,Object)
*/
@Override
@SuppressWarnings("unchecked")
public SortedSet subSet(Object fromElement, Object toElement) {
read();
SortedSet s;
s = ( (SortedSet) set ).subSet(fromElement, toElement);
return new SubSetProxy(s);
final SortedSet subSet = ( (SortedSet) set ).subSet( fromElement, toElement );
return new SubSetProxy( subSet );
}
/**
* @see PersistentSortedSet#headSet(Object)
*/
@Override
@SuppressWarnings("unchecked")
public SortedSet headSet(Object toElement) {
read();
SortedSet s = ( (SortedSet) set ).headSet(toElement);
return new SubSetProxy(s);
final SortedSet headSet = ( (SortedSet) set ).headSet(toElement);
return new SubSetProxy( headSet );
}
/**
* @see PersistentSortedSet#tailSet(Object)
*/
@Override
@SuppressWarnings("unchecked")
public SortedSet tailSet(Object fromElement) {
read();
SortedSet s = ( (SortedSet) set ).tailSet(fromElement);
return new SubSetProxy(s);
final SortedSet tailSet = ( (SortedSet) set ).tailSet( fromElement );
return new SubSetProxy( tailSet );
}
/**
* @see PersistentSortedSet#first()
*/
@Override
@SuppressWarnings("unchecked")
public Object first() {
read();
return ( (SortedSet) set ).first();
}
/**
* @see PersistentSortedSet#last()
*/
@Override
@SuppressWarnings("unchecked")
public Object last() {
read();
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 {
SubSetProxy(SortedSet s) {
super(s);
super( s );
}
@Override
@SuppressWarnings("unchecked")
public Comparator comparator() {
return ( (SortedSet) this.set ).comparator();
}
@Override
@SuppressWarnings("unchecked")
public Object first() {
return ( (SortedSet) this.set ).first();
}
@Override
@SuppressWarnings("unchecked")
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() {
return ( (SortedSet) this.set ).last();
}
@Override
@SuppressWarnings("unchecked")
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) {
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,25 +63,35 @@ import org.hibernate.type.Type;
* @author Gavin King
*/
public interface PersistentCollection {
/**
* Get the owning entity. Note that the owner is only
* set during the flush cycle, and when a new collection
* wrapper is created while loading an entity.
*
* @return The owner
*/
public Object getOwner();
/**
* Set the reference to the owning entity
*
* @param entity The owner
*/
public void setOwner(Object entity);
/**
* 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();
/**
* 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);
@ -92,7 +102,9 @@ public interface PersistentCollection {
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();
@ -103,70 +115,121 @@ public interface PersistentCollection {
/**
* Called after reading all rows from the JDBC result set
*
* @return Whether to end the read.
*/
public boolean endRead();
/**
* Called after initializing from cache
*
* @return ??
*/
public boolean afterInitialize();
/**
* Could the application possibly have a direct reference to
* the underlying collection implementation?
*
* @return {@code true} indicates that the application might have access to the underlying collection/array.
*/
public boolean isDirectlyAccessible();
/**
* 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
*/
public boolean unsetSession(SessionImplementor currentSession);
/**
* 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
*
* @throws HibernateException if the collection was already associated
* with another open session
*/
public boolean setCurrentSession(SessionImplementor session)
throws HibernateException;
public boolean setCurrentSession(SessionImplementor session) throws HibernateException;
/**
* 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,
Serializable disassembled, Object owner) throws HibernateException;
public void initializeFromCache(CollectionPersister persister, Serializable disassembled, Object owner);
/**
* Iterate all collection entries, during update of the database
*
* @param persister The collection persister.
*
* @return The iterator
*/
public Iterator entries(CollectionPersister persister);
/**
* 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)
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);
/**
* 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...
*
* @return The index value
*/
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);
/**
* 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);
@ -175,106 +238,168 @@ public interface PersistentCollection {
* allowing appropriate initializations to occur.
*
* @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);
/**
* 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)
throws HibernateException;
public boolean equalsSnapshot(CollectionPersister persister);
/**
* Is the snapshot empty?
*
* @param snapshot The snapshot to check
*
* @return {@code true} if the given snapshot is empty
*/
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)
throws HibernateException;
public Serializable disassemble(CollectionPersister persister) ;
/**
* 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);
/**
* Return a new snapshot of the current state of the collection
*
* @param persister The collection persister
*
* @return The snapshot
*/
public Serializable getSnapshot(CollectionPersister persister)
throws HibernateException;
public Serializable getSnapshot(CollectionPersister persister);
/**
* To be called internally by the session, forcing
* immediate initialization.
* To be called internally by the session, forcing 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?
*
* @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)
throws HibernateException;
public boolean needsInserting(Object entry, int i, Type elemType);
/**
* 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)
throws HibernateException;
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 isRowUpdatePossible();
/**
* 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)
throws HibernateException;
public Iterator getDeletes(CollectionPersister persister, boolean indexIsFormula);
/**
* 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);
/**
* Is this instance initialized?
*
* @return Was this collection initialized? Or is its data still not (fully) loaded?
*/
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();
/**
* Iterate the "queued" additions
* Iterator over the "queued" additions
*
* @return The iterator
*/
public Iterator queuedAdditionIterator();
/**
* 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);
/**
* Get the current collection key value
*
* @return the current collection key value
*/
public Serializable getKey();
/**
* Get the current role name
*
* @return the collection role name
*/
public String getRole();
/**
* Is the collection unreferenced?
*
* @return {@code true} if the collection is no longer referenced by an owner
*/
public boolean isUnreferenced();
@ -283,6 +408,8 @@ public interface PersistentCollection {
* reliable during the flush cycle, after the
* collection elements are dirty checked against
* the snapshot.
*
* @return {@code true} if the collection is dirty
*/
public boolean isDirty();
@ -293,8 +420,9 @@ public interface PersistentCollection {
public void clearDirty();
/**
* Get the snapshot cached by the collection
* instance
* Get the snapshot cached by the collection instance
*
* @return The internally stored snapshot state
*/
public Serializable getStoredSnapshot();
@ -306,20 +434,28 @@ public interface PersistentCollection {
/**
* Called before inserting rows, to ensure that any surrogate keys
* are fully generated
*
* @param persister The collection persister
*/
public void preInsert(CollectionPersister persister)
throws HibernateException;
public void preInsert(CollectionPersister persister);
/**
* 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)
throws HibernateException;
public void afterRowInsert(CollectionPersister persister, Object entry, int i);
/**
* 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)
throws HibernateException;
public Collection getOrphans(Serializable snapshot, String entityName);
}

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;