package org.mongodb.morphia.mapping.lazy;
import com.thoughtworks.proxy.factory.CglibProxyFactory;
import com.thoughtworks.proxy.toys.delegate.DelegationMode;
import com.thoughtworks.proxy.toys.dispatch.Dispatching;
import org.mongodb.morphia.Datastore;
import org.mongodb.morphia.Key;
import org.mongodb.morphia.mapping.lazy.proxy.ProxiedEntityReference;
import org.mongodb.morphia.mapping.lazy.proxy.ProxiedEntityReferenceList;
import org.mongodb.morphia.mapping.lazy.proxy.ProxiedEntityReferenceMap;
import org.mongodb.morphia.mapping.lazy.proxy.CollectionObjectReference;
import org.mongodb.morphia.mapping.lazy.proxy.EntityObjectReference;
import org.mongodb.morphia.mapping.lazy.proxy.MapObjectReference;
import java.io.Serializable;
import java.util.Collection;
import java.util.Map;
@SuppressWarnings("unchecked")
public class CGLibLazyProxyFactory implements LazyProxyFactory {
private final CglibProxyFactory factory = new CglibProxyFactory();
@Override
public <T extends Collection> T createListProxy(final Datastore datastore, final T listToProxy, final Class referenceObjClass,
final boolean ignoreMissing) {
final Class<? extends Collection> targetClass = listToProxy.getClass();
final CollectionObjectReference objectReference = new CollectionObjectReference(listToProxy, referenceObjClass, ignoreMissing,
datastore);
final T backend = (T) new NonFinalizingHotSwappingInvoker(new Class[]{targetClass, Serializable.class}, factory, objectReference,
DelegationMode.SIGNATURE).proxy();
return (T) Dispatching.proxy(targetClass, new Class[]{ProxiedEntityReferenceList.class, targetClass, Serializable.class})
.with(objectReference, backend)
.build(factory);
}
@Override
public <T extends Map> T createMapProxy(final Datastore datastore, final T mapToProxy, final Class referenceObjClass,
final boolean ignoreMissing) {
final Class<? extends Map> targetClass = mapToProxy.getClass();
final MapObjectReference objectReference = new MapObjectReference(datastore, mapToProxy, referenceObjClass, ignoreMissing);
final T backend = (T) new NonFinalizingHotSwappingInvoker(new Class[]{targetClass, Serializable.class}, factory, objectReference,
DelegationMode.SIGNATURE).proxy();
return (T) Dispatching.proxy(targetClass, new Class[]{ProxiedEntityReferenceMap.class, targetClass, Serializable.class})
.with(objectReference, backend)
.build(factory);
}
@Override
public <T> T createProxy(final Datastore datastore, final Class<T> targetClass, final Key<T> key, final boolean ignoreMissing) {
final EntityObjectReference objectReference = new EntityObjectReference(datastore, targetClass, key, ignoreMissing);
final T backend = (T) new NonFinalizingHotSwappingInvoker(new Class[]{targetClass, Serializable.class}, factory, objectReference,
DelegationMode.SIGNATURE).proxy();
return (T) Dispatching.proxy(targetClass, new Class[]{ProxiedEntityReference.class, targetClass, Serializable.class})
.with(objectReference, backend)
.build(factory);
}
}