Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.codehaus.jackson.map.deser.SettableBeanProperty Maven / Gradle / Ivy
Go to download
Data Mapper package is a high-performance data binding package
built on Jackson JSON processor
package org.codehaus.jackson.map.deser;
import java.io.IOException;
import java.lang.reflect.*;
import org.codehaus.jackson.*;
import org.codehaus.jackson.map.*;
import org.codehaus.jackson.type.JavaType;
import org.codehaus.jackson.util.InternCache;
/**
* Base class for settable properties of a bean: contains
* both type and name definitions, and reflection-based set functionality.
* Concrete sub-classes implement details, so that both field- and
* setter-backed properties can be handled
*/
public abstract class SettableBeanProperty
{
/**
* Logical name of the property (often but not always derived
* from the setter method name)
*/
final String _propName;
final JavaType _type;
protected JsonDeserializer _valueDeserializer;
/**
* If value will contain type information (to support
* polymorphic handling), this is the type deserializer
* used to handle type resolution.
*/
protected TypeDeserializer _valueTypeDeserializer;
/**
* Value to be used when 'null' literal is encountered in Json.
* For most types simply Java null, but for primitive types must
* be a non-null value (like Integer.valueOf(0) for int).
*/
protected Object _nullValue;
/*
/**********************************************************
/* Life-cycle (construct & configure)
/**********************************************************
*/
protected SettableBeanProperty(String propName, JavaType type,
TypeDeserializer typeDeser)
{
/* 09-Jan-2009, tatu: Intern()ing makes sense since Jackson parsed
* field names are (usually) interned too, hence lookups will be faster.
*/
// 23-Oct-2009, tatu: should this be disabled wrt [JACKSON-180]?
if (propName == null || propName.length() == 0) {
_propName = "";
} else {
_propName = InternCache.instance.intern(propName);
}
_type = type;
_valueTypeDeserializer = typeDeser;
}
public void setValueDeserializer(JsonDeserializer deser)
{
if (_valueDeserializer != null) { // sanity check
throw new IllegalStateException("Already had assigned deserializer for property '"+_propName+"' (class "+getDeclaringClass().getName()+")");
}
_valueDeserializer = deser;
_nullValue = _valueDeserializer.getNullValue();
}
protected abstract Class> getDeclaringClass();
/*
/**********************************************************
/* Accessors
/**********************************************************
*/
public String getPropertyName() { return _propName; }
public JavaType getType() { return _type; }
public boolean hasValueDeserializer() { return (_valueDeserializer != null); }
/**
* Method to use for accessing index of the property (related to
* other properties in the same context); currently only applicable
* to "Creator properties".
*
* Base implementation returns -1 to indicate that no index exists
* for the property.
*/
public int getCreatorIndex() { return -1; }
/*
/**********************************************************
/* Public API
/**********************************************************
*/
/**
* Method called to deserialize appropriate value, given parser (and
* context), and set it using appropriate mechanism.
* Pre-condition is that passed parser must point to the first token
* that should be consumed to produce the value (the only value for
* scalars, multiple for Objects and Arrays).
*/
public abstract void deserializeAndSet(JsonParser jp, DeserializationContext ctxt,
Object instance)
throws IOException, JsonProcessingException;
public abstract void set(Object instance, Object value)
throws IOException;
/**
* This method is needed by some specialized bean deserializers,
* and also called by some {@link #deserializeAndSet} implementations.
*
* Pre-condition is that passed parser must point to the first token
* that should be consumed to produce the value (the only value for
* scalars, multiple for Objects and Arrays).
*/
public final Object deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.VALUE_NULL) {
return _nullValue;
}
if (_valueTypeDeserializer != null) {
return _valueDeserializer.deserializeWithType(jp, ctxt, _valueTypeDeserializer);
}
return _valueDeserializer.deserialize(jp, ctxt);
}
/*
/**********************************************************
/* Helper methods
/**********************************************************
*/
/**
* Method that takes in exception of any type, and casts or wraps it
* to an IOException or its subclass.
*/
protected void _throwAsIOE(Exception e, Object value)
throws IOException
{
if (e instanceof IllegalArgumentException) {
String actType = (value == null) ? "[NULL]" : value.getClass().getName();
StringBuilder msg = new StringBuilder("Problem deserializing property '").append(getPropertyName());
msg.append("' (expected type: ").append(getType());
msg.append("; actual type: ").append(actType).append(")");
String origMsg = e.getMessage();
if (origMsg != null) {
msg.append(", problem: ").append(origMsg);
} else {
msg.append(" (no error message provided)");
}
throw new JsonMappingException(msg.toString(), null, e);
}
_throwAsIOE(e);
}
protected IOException _throwAsIOE(Exception e)
throws IOException
{
if (e instanceof IOException) {
throw (IOException) e;
}
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
}
// let's wrap the innermost problem
Throwable th = e;
while (th.getCause() != null) {
th = th.getCause();
}
throw new JsonMappingException(th.getMessage(), null, th);
}
@Override public String toString() { return "[property '"+_propName+"']"; }
/*
/**********************************************************
/* Impl classes
/**********************************************************
*/
/**
* This concrete sub-class implements property that is set
* using regular "setter" method.
*/
public final static class MethodProperty
extends SettableBeanProperty
{
/**
* Setter method for modifying property value; used for
* "regular" method-accessible properties.
*/
protected final Method _setter;
public MethodProperty(String propName, JavaType type, TypeDeserializer typeDeser,
Method setter)
{
super(propName, type, typeDeser);
_setter = setter;
}
protected Class> getDeclaringClass()
{
return _setter.getDeclaringClass();
}
public void deserializeAndSet(JsonParser jp, DeserializationContext ctxt,
Object instance)
throws IOException, JsonProcessingException
{
set(instance, deserialize(jp, ctxt));
}
public final void set(Object instance, Object value)
throws IOException
{
try {
_setter.invoke(instance, value);
} catch (Exception e) {
_throwAsIOE(e, value);
}
}
}
/**
* This concrete sub-class implements Collection or Map property that is
* indirectly by getting the property value and directly modifying it.
*/
public final static class SetterlessProperty
extends SettableBeanProperty
{
/**
* Get method for accessing property value used to access property
* (of Collection or Map type) to modify.
*/
protected final Method _getter;
public SetterlessProperty(String propName, JavaType type, TypeDeserializer typeDeser,
Method getter)
{
super(propName, type, typeDeser);
_getter = getter;
}
protected Class> getDeclaringClass()
{
return _getter.getDeclaringClass();
}
public final void deserializeAndSet(JsonParser jp, DeserializationContext ctxt,
Object instance)
throws IOException, JsonProcessingException
{
JsonToken t = jp.getCurrentToken();
if (t == JsonToken.VALUE_NULL) {
/* Hmmh. Is this a problem? We won't be setting anything, so it's
* equivalent of empty Collection/Map in this case
*/
return;
}
// Ok: then, need to fetch Collection/Map to modify:
Object toModify;
try {
toModify = _getter.invoke(instance);
} catch (Exception e) {
_throwAsIOE(e);
return; // never gets here
}
/* Note: null won't work, since we can't then inject anything
* in. At least that's not good in common case. However,
* theoretically the case where we get Json null might
* be compatible. If so, implementation could be changed.
*/
if (toModify == null) {
throw new JsonMappingException("Problem deserializing 'setterless' property '"+getPropertyName()+"': get method returned null");
}
_valueDeserializer.deserialize(jp, ctxt, toModify);
}
public final void set(Object instance, Object value)
throws IOException
{
throw new UnsupportedOperationException("Should never call 'set' on setterless property");
}
}
/**
* This concrete sub-class implements property that is set
* directly assigning to a Field.
*/
public final static class FieldProperty
extends SettableBeanProperty
{
/**
* Actual field to set when deserializing this property.
*/
protected final Field _field;
public FieldProperty(String propName, JavaType type, TypeDeserializer typeDeser,
Field f)
{
super(propName, type, typeDeser);
_field = f;
}
protected Class> getDeclaringClass()
{
return _field.getDeclaringClass();
}
public void deserializeAndSet(JsonParser jp, DeserializationContext ctxt,
Object instance)
throws IOException, JsonProcessingException
{
set(instance, deserialize(jp, ctxt));
}
public final void set(Object instance, Object value)
throws IOException
{
try {
_field.set(instance, value);
} catch (Exception e) {
_throwAsIOE(e, value);
}
}
}
/**
* This concrete sub-class implements property that is passed
* via Creator (constructor or static factory method).
*/
public final static class CreatorProperty
extends SettableBeanProperty
{
final Class> _declaringClass;
/**
* Index of the property
*/
final int _index;
public CreatorProperty(String propName, JavaType type,
TypeDeserializer typeDeser,
Class> declaringClass, int index)
{
super(propName, type, typeDeser);
_declaringClass = declaringClass;
_index = index;
}
/**
* Method to use for accessing index of the property (related to
* other properties in the same context); currently only applicable
* to "Creator properties".
*
* Base implementation returns -1 to indicate that no index exists
* for the property.
*/
public int getCreatorIndex() { return _index; }
protected Class> getDeclaringClass()
{
return _declaringClass;
}
public void deserializeAndSet(JsonParser jp, DeserializationContext ctxt,
Object instance)
throws IOException, JsonProcessingException
{
set(instance, deserialize(jp, ctxt));
}
public void set(Object instance, Object value)
throws IOException
{
/* Hmmmh. Should we return quietly (NOP), or error?
* For now, let's just bail out without fuss.
*/
//throw new IllegalStateException("Method should never be called on a "+getClass().getName());
}
}
}