/*
* This is eMonocot, a global online biodiversity information resource.
*
* Copyright © 2011–2015 The Board of Trustees of the Royal Botanic Gardens, Kew and The University of Oxford
*
* eMonocot is free software: you can redistribute it and/or modify it under the terms of the
* GNU Affero General Public License as published by the Free Software Foundation, either version 3
* of the License, or (at your option) any later version.
*
* eMonocot 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 Affero General Public License for more details.
*
* The complete text of the GNU Affero General Public License is in the source repository as the file
* ‘COPYING’. It is also available from <http://www.gnu.org/licenses/>.
*/
package org.emonocot.model.marshall.json.hibernate;
import java.io.IOException;
import org.hibernate.collection.PersistentCollection;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
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.SerializationConfig;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.jsontype.TypeSerializer;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.fasterxml.jackson.databind.ser.ResolvableSerializer;
/**
* Wrapper serializer used to handle aspects of lazy loading that can be used
* for Hibernate collection datatypes.
*/
public class PersistentCollectionSerializer
extends JsonSerializer<PersistentCollection>
implements ContextualSerializer,
ResolvableSerializer
{
/**
* Property that has collection value to handle
*/
protected final BeanProperty _property;
protected final boolean _forceLazyLoading;
/**
* This is the nominal type used to locate actual serializer to use
* for contents, if this collection is to be serialized.
*/
protected final JavaType _serializationType;
/**
* Serializer to which we delegate if serialization is not blocked.
*/
protected JsonSerializer<Object> _serializer;
/*
/**********************************************************************
/* Life cycle
/**********************************************************************
*/
public PersistentCollectionSerializer(BeanProperty property, JavaType type,
boolean forceLazyLoading)
{
_property = property;
_serializationType = type;
_forceLazyLoading = forceLazyLoading;
}
/**
* We need to resolve actual serializer once we know the context; specifically
* must know type of property being serialized.
* If not known
*/
@Override
public JsonSerializer<?> createContextual(SerializerProvider provider,
BeanProperty property)
throws JsonMappingException
{
/* If we have property, should be able to get actual polymorphic type
* information.
* May need to refine in future, in case nested types are used, since
* 'property' refers to field/method and main type, but contents of
* that type may also be resolved... in which case this would fail.
*/
if (property != null) {
return new PersistentCollectionSerializer(property, property.getType(),
_forceLazyLoading);
}
return this;
}
public void resolve(SerializerProvider provider) throws JsonMappingException
{
_serializer = provider.findValueSerializer(_serializationType, _property);
}
/*
/**********************************************************************
/* JsonSerializer impl
/**********************************************************************
*/
@Override
public void serialize(PersistentCollection coll, JsonGenerator jgen, SerializerProvider provider)
throws IOException, JsonProcessingException
{
// If lazy-loaded, not yet loaded, may serialize as null?
if (!_forceLazyLoading && !coll.wasInitialized()) {
jgen.writeNull();
return;
}
Object value = coll.getValue();
if (value == null) {
provider.defaultSerializeNull(jgen);
} else {
if (_serializer == null) { // sanity check...
throw new JsonMappingException("PersitentCollection does not have serializer set");
}
_serializer.serialize(value, jgen, provider);
}
}
public void serializeWithType(PersistentCollection coll, JsonGenerator jgen, SerializerProvider provider,
TypeSerializer typeSer)
throws IOException, JsonProcessingException
{
if (!_forceLazyLoading && !coll.wasInitialized()) {
jgen.writeNull();
return;
}
Object value = coll.getValue();
if (value == null) {
provider.defaultSerializeNull(jgen);
} else {
if (_serializer == null) { // sanity check...
throw new JsonMappingException("PersitentCollection does not have serializer set");
}
_serializer.serializeWithType(value, jgen, provider, typeSer);
}
}
}