HHH-8159 - Apply fixups indicated by analysis tools
This commit is contained in:
parent
11464ea097
commit
63093dbfd9
|
@ -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 );
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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;
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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 ) );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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;
|
Loading…
Reference in New Issue