package com.fasterxml.jackson.datatype.hibernate4;
import java.beans.Introspector;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import javax.persistence.EntityNotFoundException;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.fasterxml.jackson.databind.ser.impl.PropertySerializerMap;
import com.fasterxml.jackson.databind.util.NameTransformer;
import org.hibernate.engine.spi.Mapping;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.hibernate.proxy.pojo.BasicLazyInitializer;
public class HibernateProxySerializer
extends JsonSerializer<HibernateProxy>
implements ContextualSerializer
{
protected final BeanProperty _property;
protected final boolean _forceLazyLoading;
protected final boolean _serializeIdentifier;
protected final boolean _nullMissingEntities;
protected final boolean _wrappedIdentifier;
protected final Mapping _mapping;
protected final NameTransformer _unwrapper;
protected PropertySerializerMap _dynamicSerializers;
@Deprecated
public HibernateProxySerializer(boolean forceLazyLoading)
{
this(forceLazyLoading, false, false, true, null, null, null);
}
@Deprecated
public HibernateProxySerializer(boolean forceLazyLoading, boolean serializeIdentifier) {
this(forceLazyLoading, serializeIdentifier, false, true,
null, null, null);
}
@Deprecated
public HibernateProxySerializer(boolean forceLazyLoading, boolean serializeIdentifier, Mapping mapping) {
this(forceLazyLoading, serializeIdentifier, false, true,
mapping, null, null);
}
@Deprecated
public HibernateProxySerializer(boolean forceLazyLoading, boolean serializeIdentifier,
boolean nullMissingEntities, Mapping mapping) {
this(forceLazyLoading, serializeIdentifier, nullMissingEntities, true,
mapping, null, null);
}
@Deprecated
public HibernateProxySerializer(boolean forceLazyLoading, boolean serializeIdentifier,
boolean nullMissingEntities, Mapping mapping, BeanProperty property) {
this(forceLazyLoading, serializeIdentifier, nullMissingEntities, true,
mapping, property, null);
}
public HibernateProxySerializer(boolean forceLazyLoading, boolean serializeIdentifier,
boolean nullMissingEntities, boolean wrappedIdentifier,
Mapping mapping)
{
this(forceLazyLoading, serializeIdentifier, nullMissingEntities, wrappedIdentifier,
mapping, null, null);
}
public HibernateProxySerializer(boolean forceLazyLoading, boolean serializeIdentifier,
boolean nullMissingEntities, boolean wrappedIdentifier,
Mapping mapping, BeanProperty property, NameTransformer unwrapper)
{
_forceLazyLoading = forceLazyLoading;
_serializeIdentifier = serializeIdentifier;
_nullMissingEntities = nullMissingEntities;
_wrappedIdentifier = wrappedIdentifier;
_mapping = mapping;
_property = property;
_unwrapper = unwrapper;
_dynamicSerializers = PropertySerializerMap.emptyForProperties();
}
protected HibernateProxySerializer(HibernateProxySerializer base,
BeanProperty property, NameTransformer unwrapper)
{
_forceLazyLoading = base._forceLazyLoading;
_serializeIdentifier = base._serializeIdentifier;
_nullMissingEntities = base._nullMissingEntities;
_wrappedIdentifier = base._wrappedIdentifier;
_mapping = base._mapping;
_property = property;
_unwrapper = unwrapper;
_dynamicSerializers = PropertySerializerMap.emptyForProperties();
}
@Override
public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) {
return new HibernateProxySerializer(this, property, _unwrapper);
}
@Override
public JsonSerializer<HibernateProxy> unwrappingSerializer(final NameTransformer unwrapper)
{
return new HibernateProxySerializer(this, _property, unwrapper);
}
@Override
public boolean isUnwrappingSerializer() {
return _unwrapper != null;
}
@Override
public boolean isEmpty(SerializerProvider provider, HibernateProxy value) {
return (value == null) || (findProxied(value) == null);
}
@Override
public void serialize(HibernateProxy value, JsonGenerator jgen, SerializerProvider provider)
throws IOException
{
Object proxiedValue = findProxied(value);
if (proxiedValue == null) {
provider.defaultSerializeNull(jgen);
return;
}
findSerializer(provider, proxiedValue).serialize(proxiedValue, jgen, provider);
}
@Override
public void serializeWithType(HibernateProxy value, JsonGenerator jgen, SerializerProvider provider,
TypeSerializer typeSer)
throws IOException
{
Object proxiedValue = findProxied(value);
if (proxiedValue == null) {
provider.defaultSerializeNull(jgen);
return;
}
findSerializer(provider, proxiedValue).serializeWithType(proxiedValue, jgen, provider, typeSer);
}
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
throws JsonMappingException
{
SerializerProvider prov = visitor.getProvider();
if ((prov == null) || (_property == null)) {
super.acceptJsonFormatVisitor(visitor, typeHint);
} else {
JavaType type = _property.getType();
prov.findPrimaryPropertySerializer(type, _property)
.acceptJsonFormatVisitor(visitor, type);
}
}
protected JsonSerializer<Object> findSerializer(SerializerProvider provider, Object value)
throws IOException
{
Class<?> type = value.getClass();
PropertySerializerMap.SerializerAndMapResult result =
_dynamicSerializers.findAndAddPrimarySerializer(type, provider, _property);
if (_dynamicSerializers != result.map) {
_dynamicSerializers = result.map;
}
if (_unwrapper != null)
{
return result.serializer.unwrappingSerializer(_unwrapper);
}
return result.serializer;
}
protected Object findProxied(final HibernateProxy proxy)
{
LazyInitializer init = proxy.getHibernateLazyInitializer();
if (!_forceLazyLoading && init.isUninitialized()) {
if (_serializeIdentifier) {
final Object idValue = init.getIdentifier();
final Object result;
if (_wrappedIdentifier) {
final HashMap<String, Object> map = new HashMap<>();
map.put(getIdentifierPropertyName(init), idValue);
result = map;
} else {
result = idValue;
}
return result;
}
return null;
}
try {
return init.getImplementation();
} catch (EntityNotFoundException e) {
if (_nullMissingEntities) {
return null;
} else {
throw e;
}
}
}
private String getIdentifierPropertyName(final LazyInitializer init) {
String idName;
if (_mapping != null) {
idName = _mapping.getIdentifierPropertyName(init.getEntityName());
} else {
final SessionImplementor session = init.getSession();
if (session != null) {
idName = session.getFactory().getIdentifierPropertyName(init.getEntityName());
} else {
idName = ProxyReader.getIdentifierPropertyName(init);
if (idName == null) {
idName = init.getEntityName();
}
}
}
return idName;
}
protected static class ProxyReader {
private static final Field getIdentifierMethodField;
static {
try {
getIdentifierMethodField = BasicLazyInitializer.class.getDeclaredField("getIdentifierMethod");
getIdentifierMethodField.setAccessible(true);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static String getIdentifierPropertyName(LazyInitializer init) {
try {
Method idGetter = (Method) getIdentifierMethodField.get(init);
if (idGetter == null) {
return null;
}
String name = idGetter.getName();
if (name.startsWith("get")) {
name = Introspector.decapitalize(name.substring(3));
}
return name;
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
}