org.babyfish.hibernate.collection.spi.persistence.MapBasePersistence Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of babyfish-hibernate Show documentation
Show all versions of babyfish-hibernate Show documentation
The hibernate enhancement project of BabyFish.
The newest version!
/*
* BabyFish, Object Model Framework for Java and JPA.
* https://github.com/babyfish-ct/babyfish
*
* Copyright (c) 2008-2015, Tao Chen
*
* 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.
*
* Please visit "http://opensource.org/licenses/LGPL-3.0" to know more.
*
* 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.
*/
package org.babyfish.hibernate.collection.spi.persistence;
import java.io.Serializable;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.babyfish.collection.ArrayList;
import org.babyfish.collection.HashMap;
import org.babyfish.collection.MACollections;
import org.babyfish.collection.MAMap;
import org.babyfish.collection.TreeMap;
import org.babyfish.collection.UnifiedComparator;
import org.babyfish.collection.XCollection;
import org.babyfish.collection.XMap;
import org.babyfish.lang.Arguments;
import org.babyfish.lang.IllegalProgramException;
import org.babyfish.lang.Ref;
import org.babyfish.util.LazyResource;
import org.hibernate.FlushMode;
import org.hibernate.HibernateException;
import org.hibernate.criterion.Restrictions;
import org.hibernate.engine.internal.JoinHelper;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.internal.CriteriaImpl;
import org.hibernate.loader.CollectionAliases;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.collection.QueryableCollection;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.OuterJoinLoadable;
import org.hibernate.type.Type;
/**
* @author Tao Chen
*/
public abstract class MapBasePersistence extends AbstractBasePersistence {
private static final long serialVersionUID = -5020841795509944819L;
private static final LazyResource LAZY_COMMON_RESOURCE =
LazyResource.of(CommonResource.class);
private static final String MIDDLE_TABLE_ALIAS = "babyfish_mt_alias_";
protected abstract MAMap getBase();
protected abstract void initBase(MAMap base);
protected abstract XMap getQueuedOrphans();
protected abstract void preformQueuedOrphans();
@SuppressWarnings("unchecked")
@Override
public V getElement(Object entry) {
return ((Entry)entry).getValue();
}
@Override
public Iterator> entries(CollectionPersister persister) {
return MACollections.unmodifiable(this.getBase().entrySet()).iterator();
//Not MACollections.unmodifiable(this.getBase().entrySet().iterator());
//Entry is readonly to so that Entry.setValue can not work normally.
}
@SuppressWarnings("unchecked")
@Override
public V readFrom(
ResultSet rs,
CollectionPersister persister,
CollectionAliases descriptor,
Object owner) throws HibernateException, SQLException {
V value = (V)persister.readElement( rs, owner, descriptor.getSuffixedElementAliases(), getSession() );
K key = (K)persister.readIndex( rs, descriptor.getSuffixedIndexAliases(), getSession() );
if ( value != null ) {
this.getBase().put(key, value);
}
return value;
}
@SuppressWarnings("unchecked")
@Override
public Collection getOrphans(Serializable snapshot, String entityName)
throws HibernateException {
XMap sn = (XMap)snapshot;
return getOrphans(sn.values(), this.getBase().values(), entityName, getSession());
}
@Override
public Iterator queuedAdditionIterator() {
return MACollections.emptySet().iterator();
}
@Override
public Collection getQueuedOrphans(String entityName) {
XMap map = this.getQueuedOrphans();
if (!map.isEmpty()) {
XCollection removals = new ArrayList(map.valueUnifiedComparator(), map.size());
for (V value : map.values()) {
removals.add(value);
}
return getOrphans(removals, MACollections.emptySet(), entityName, this.getSession());
}
else {
return MACollections.emptySet();
}
}
@Override
public boolean empty() {
return this.getBase().isEmpty();
}
@Override
public void beginRead() {
this.setInitializing(true);
}
@Override
public boolean endRead() {
return this.afterInitialize();
}
@Override
public boolean afterInitialize() {
setInitialized();
//do this bit after setting initialized to true or it will recurse
if (this.hasQueuedOperations()) {
this.preformQueuedOrphans();
//cacheSize = -1;
return false;
}
return true;
}
@SuppressWarnings("unchecked")
@Override
public void initializeFromCache(
CollectionPersister persister,
Serializable disassembled,
Object owner) throws HibernateException {
Serializable[] array = (Serializable[])disassembled;
int size = array.length;
beforeInitialize(persister, size);
MAMap baseMap = this.getBase();
for ( int i = 0; i < size; i+=2 ) {
baseMap.put(
(K)persister.getIndexType().assemble(array[i], getSession(), owner),
(V)persister.getElementType().assemble(array[i+1], getSession(), owner));
}
}
@SuppressWarnings("unchecked")
@Override
public K getIndex(Object entry, int i, CollectionPersister persister) {
return ((Entry)entry).getKey();
}
@SuppressWarnings("unchecked")
@Override
public Object getSnapshotElement(Object entry, int i) {
XMap sn = (XMap)getSnapshot();
return sn.get(((Entry)entry).getKey());
}
@SuppressWarnings("unchecked")
@Override
public void beforeInitialize(CollectionPersister persister, int anticipatedSize) {
Object instantiate = persister.getCollectionType().instantiate(anticipatedSize);
if (!(instantiate instanceof MAMap, ?>)) {
throw new IllegalProgramException(
LAZY_COMMON_RESOURCE.get().illegalInstantiate(
persister.getCollectionType().getClass(),
MAMap.class
)
);
}
this.initBase((MAMap)instantiate);
}
@SuppressWarnings("unchecked")
@Override
public boolean equalsSnapshot(CollectionPersister persister) throws HibernateException {
Type elementType = persister.getElementType();
XMap snapshotMap = (XMap)this.getSnapshot();
MAMap baseMap = this.getBase();
if (snapshotMap.size() != baseMap.size()) {
return false;
}
Iterator> iter = baseMap.entrySet().iterator();
while (iter.hasNext()) {
Entry entry = iter.next();
if (elementType.isDirty(entry.getValue(), snapshotMap.get(entry.getKey()), this.getSession())) {
return false;
}
}
return true;
}
@Override
public boolean isSnapshotEmpty(Serializable snapshot) {
return ((XMap, ?>)snapshot).isEmpty();
}
@Override
public Serializable disassemble(CollectionPersister persister) throws HibernateException {
MAMap baseMap = this.getBase();
Serializable[] result = new Serializable[baseMap.size() << 1];
Iterator> iter = baseMap.entrySet().iterator();
int i=0;
while (iter.hasNext()) {
Entry e = iter.next();
result[i++] = persister.getIndexType().disassemble(e.getKey(), getSession(), null);
result[i++] = persister.getElementType().disassemble(e.getValue(), getSession(), null);
}
return result;
}
@SuppressWarnings("unchecked")
@Override
public Serializable getSnapshot(CollectionPersister persister) throws HibernateException {
MAMap baseMap = this.getBase();
Map clonedMap;
UnifiedComparator super K> keyUnifiedComparator = baseMap.keyUnifiedComparator();
if (keyUnifiedComparator.comparator() != null) {
clonedMap = new TreeMap(
keyUnifiedComparator.comparator(),
baseMap.valueUnifiedComparator());
} else {
clonedMap = new HashMap(
keyUnifiedComparator.equalityComparator(),
baseMap.valueUnifiedComparator(),
baseMap.size() + 1,
1.F);
}
Iterator> iter = baseMap.entrySet().iterator();
while ( iter.hasNext() ) {
Entry e = (Entry)iter.next();
final V copy = (V)persister.getElementType().deepCopy(
e.getValue(), persister.getFactory());
clonedMap.put(e.getKey(), copy);
}
return (Serializable)clonedMap;
}
@Override
public boolean entryExists(Object entry, int i) {
return ((Entry, ?>)entry).getValue() != null;
}
@SuppressWarnings("unchecked")
@Override
public boolean needsInserting(Object entry, int i, Type elemType) throws HibernateException {
final XMap, ?> snapshot = (XMap)this.getSnapshot();
Entry, ?> e = (Entry, ?>) entry;
return e.getValue() != null && snapshot.get(e.getKey()) == null;
}
@SuppressWarnings("unchecked")
@Override
public boolean needsUpdating(Object entry, int i, Type elemType) throws HibernateException {
final XMap sn = (XMap)this.getSnapshot();
Entry e = (Entry)entry;
V snValue = sn.get(e.getKey());
return
e.getValue() != null &&
snValue!=null &&
elemType.isDirty(snValue, e.getValue(), this.getSession());
}
@Override
public boolean isRowUpdatePossible() {
return true;
}
@SuppressWarnings("unchecked")
@Override
public Iterator> getDeletes(CollectionPersister persister,
boolean indexIsFormula) throws HibernateException {
MAMap baseMap = this.getBase();
List