package org.hibernate.tuple.component;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.boot.internal.ClassLoaderAccessImpl;
import org.hibernate.boot.registry.classloading.spi.ClassLoaderService;
import org.hibernate.boot.registry.classloading.spi.ClassLoadingException;
import org.hibernate.boot.spi.BootstrapContext;
import org.hibernate.boot.spi.ClassLoaderAccess;
import org.hibernate.boot.spi.MetadataBuildingOptions;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.mapping.Component;
public class ComponentTuplizerFactory implements Serializable {
private static final Class[] COMPONENT_TUP_CTOR_SIG = new Class[] { Component.class };
private Map<EntityMode,Class<? extends ComponentTuplizer>> defaultImplClassByMode = buildBaseMapping();
private final ClassLoaderAccess classLoaderAccess;
@Deprecated
public ComponentTuplizerFactory(MetadataBuildingOptions metadataBuildingOptions) {
classLoaderAccess = new ClassLoaderAccessImpl(
metadataBuildingOptions.getTempClassLoader(),
metadataBuildingOptions.getServiceRegistry().getService( ClassLoaderService.class )
);
}
public ComponentTuplizerFactory(BootstrapContext bootstrapContext) {
classLoaderAccess = bootstrapContext.getClassLoaderAccess();
}
@SuppressWarnings({ "UnusedDeclaration" })
public void registerDefaultTuplizerClass(EntityMode entityMode, Class<? extends ComponentTuplizer> tuplizerClass) {
assert isComponentTuplizerImplementor( tuplizerClass )
: "Specified tuplizer class [" + tuplizerClass.getName() + "] does not implement " + ComponentTuplizer.class.getName();
assert hasProperConstructor( tuplizerClass )
: "Specified tuplizer class [" + tuplizerClass.getName() + "] is not properly instantiatable";
defaultImplClassByMode.put( entityMode, tuplizerClass );
}
@SuppressWarnings({ "unchecked" })
public ComponentTuplizer constructTuplizer(String tuplizerClassName, Component metadata) {
try {
Class<? extends ComponentTuplizer> tuplizerClass = classLoaderAccess.classForName( tuplizerClassName );
return constructTuplizer( tuplizerClass, metadata );
}
catch ( ClassLoadingException e ) {
throw new HibernateException( "Could not locate specified tuplizer class [" + tuplizerClassName + "]" );
}
}
public ComponentTuplizer constructTuplizer(Class<? extends ComponentTuplizer> tuplizerClass, Component metadata) {
Constructor<? extends ComponentTuplizer> constructor = getProperConstructor( tuplizerClass );
assert constructor != null : "Unable to locate proper constructor for tuplizer [" + tuplizerClass.getName() + "]";
try {
return constructor.newInstance( metadata );
}
catch ( Throwable t ) {
throw new HibernateException( "Unable to instantiate default tuplizer [" + tuplizerClass.getName() + "]", t );
}
}
public ComponentTuplizer constructDefaultTuplizer(EntityMode entityMode, Component metadata) {
Class<? extends ComponentTuplizer> tuplizerClass = defaultImplClassByMode.get( entityMode );
if ( tuplizerClass == null ) {
throw new HibernateException( "could not determine default tuplizer class to use [" + entityMode + "]" );
}
return constructTuplizer( tuplizerClass, metadata );
}
private boolean isComponentTuplizerImplementor(Class tuplizerClass) {
return ReflectHelper.implementsInterface( tuplizerClass, ComponentTuplizer.class );
}
@SuppressWarnings({ "unchecked" })
private boolean hasProperConstructor(Class tuplizerClass) {
return getProperConstructor( tuplizerClass ) != null;
}
@SuppressWarnings("unchecked")
private Constructor<? extends ComponentTuplizer> getProperConstructor(Class<? extends ComponentTuplizer> clazz) {
Constructor<? extends ComponentTuplizer> constructor = null;
try {
constructor = clazz.getDeclaredConstructor( COMPONENT_TUP_CTOR_SIG );
try {
ReflectHelper.ensureAccessibility( constructor );
}
catch ( SecurityException e ) {
constructor = null;
}
}
catch ( NoSuchMethodException ignore ) {
}
return constructor;
}
private static Map<EntityMode,Class<? extends ComponentTuplizer>> buildBaseMapping() {
Map<EntityMode,Class<? extends ComponentTuplizer>> map = new ConcurrentHashMap<EntityMode,Class<? extends ComponentTuplizer>>();
map.put( EntityMode.POJO, PojoComponentTuplizer.class );
map.put( EntityMode.MAP, DynamicMapComponentTuplizer.class );
return map;
}
}