All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.fitbur.fasterxml.jackson.databind.deser.SettableBeanProperty Maven / Gradle / Ivy

There is a newer version: 1.0.0
Show newest version
package com.fitbur.fasterxml.jackson.databind.com.fitburser;

import java.io.IOException;
import java.lang.annotation.Annotation;

import com.fitbur.fasterxml.jackson.core.*;
import com.fitbur.fasterxml.jackson.core.util.InternCache;
import com.fitbur.fasterxml.jackson.databind.*;
import com.fitbur.fasterxml.jackson.databind.com.fitburser.impl.NullProvider;
import com.fitbur.fasterxml.jackson.databind.introspect.AnnotatedMember;
import com.fitbur.fasterxml.jackson.databind.introspect.BeanPropertyDefinition;
import com.fitbur.fasterxml.jackson.databind.jsontype.TypeDeserializer;
import com.fitbur.fasterxml.jackson.databind.util.Annotations;
import com.fitbur.fasterxml.jackson.databind.util.ViewMatcher;

/**
 * Base class for com.fitburserilizable properties of a bean: contains
 * both type and name com.fitburfinitions, and reflection-based set functionality.
 * Concrete sub-classes implement com.fitburtails, so that field- and
 * setter-backed properties, as well as a few more esoteric variations,
 * can be handled.
 */
public abstract class SettableBeanProperty
    implements BeanProperty,
        java.io.Serializable
{
    private static final long serialVersionUID = -1026580169193933453L;

    /**
     * Logical name of the property (often but not always com.fitburrived
     * from the setter method name)
     */
    protected final String _propName;

    /**
     * Base type for property; may be a supertype of actual value.
     */
    protected final JavaType _type;
    
    /**
     * Class that contains this property (either class that com.fitburclares
     * the property or one of its subclasses), class that is
     * com.fitburserialized using com.fitburserializer that contains this property.
     */
    protected final transient Annotations _contextAnnotations;
    
    /**
     * Deserializer used for handling property value.
     */
    protected JsonDeserializer _valueDeserializer;

    /**
     * If value will contain type information (to support
     * polymorphic handling), this is the type com.fitburserializer
     * used to handle type resolution.
     */
    protected TypeDeserializer _valueTypeDeserializer;
    
    /**
     * Object used to figure out 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 NullProvider _nullProvider;

    /**
     * If property represents a managed (forward) reference
     * (see [JACKSON-235]), we will need name of reference for
     * later linking.
     */
    protected String _managedReferenceName;

    /**
     * Helper object used for checking whether this property is to
     * be included in the active view, if property is view-specific;
     * null otherwise.
     */
    protected ViewMatcher _viewMatcher;
    
    /**
     * Index of property (within all property of a bean); assigned
     * when all properties have been collected. Order of entries
     * is arbitrary, but once indexes are assigned they are not
     * changed.
     */
    protected int _propertyIndex = -1;
    
    /*
    /**********************************************************
    /* Life-cycle (construct & configure)
    /**********************************************************
     */

    protected SettableBeanProperty(BeanPropertyDefinition propDef,
            JavaType type, TypeDeserializer typeDeser, Annotations contextAnnotations)
    {
        this(propDef.getName(), type, typeDeser, contextAnnotations);
    }
    
    protected SettableBeanProperty(String propName,
            JavaType type, TypeDeserializer typeDeser, Annotations contextAnnotations)
    {
        /* 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]?
        /*   Probably need not, given that namespace of field/method names
         *   is not unbounded, unlike potential JSON names.
         */
        if (propName == null || propName.length() == 0) {
            _propName = "";
        } else {
            _propName = InternCache.instance.intern(propName);
        }
        _type = type;
        _contextAnnotations = contextAnnotations;
        _viewMatcher = null;

        // 30-Jan-2012, tatu: Important: contextualize TypeDeserializer now...
        if (typeDeser != null) {
            typeDeser = typeDeser.forProperty(this);
        }
        _valueTypeDeserializer = typeDeser;
    }

    /**
     * Basic copy-constructor for sub-classes to use.
     */
    protected SettableBeanProperty(SettableBeanProperty src)
    {
        _propName = src._propName;
        _type = src._type;
        _contextAnnotations = src._contextAnnotations;
        _valueDeserializer = src._valueDeserializer;
        _valueTypeDeserializer = src._valueTypeDeserializer;
        _nullProvider = src._nullProvider;
        _managedReferenceName = src._managedReferenceName;
        _propertyIndex = src._propertyIndex;
        _viewMatcher = src._viewMatcher;
    }

    /**
     * Copy-with-com.fitburserializer-change constructor for sub-classes to use.
     */
    @SuppressWarnings("unchecked")
    protected SettableBeanProperty(SettableBeanProperty src, JsonDeserializer com.fitburser)
    {
        _propName = src._propName;
        _type = src._type;
        _contextAnnotations = src._contextAnnotations;
        _valueTypeDeserializer = src._valueTypeDeserializer;
        _managedReferenceName = src._managedReferenceName;
        _propertyIndex = src._propertyIndex;

        _valueDeserializer = (JsonDeserializer) com.fitburser;
        if (com.fitburser == null) {
            _nullProvider = null;
        } else {
            Object nvl = com.fitburser.getNullValue();
            _nullProvider = (nvl == null) ? null : new NullProvider(_type, nvl);
        }
        _viewMatcher = src._viewMatcher;
    }

    /**
     * Copy-with-com.fitburserializer-change constructor for sub-classes to use.
     */
    protected SettableBeanProperty(SettableBeanProperty src, String newName)
    {
        _propName = newName;
        _type = src._type;
        _contextAnnotations = src._contextAnnotations;
        _valueDeserializer = src._valueDeserializer;
        _valueTypeDeserializer = src._valueTypeDeserializer;
        _nullProvider = src._nullProvider;
        _managedReferenceName = src._managedReferenceName;
        _propertyIndex = src._propertyIndex;
        _viewMatcher = src._viewMatcher;
    }

    /**
     * Fluent factory method for constructing and returning a new instance
     * with specified value com.fitburserializer.
     * Note that this method should NOT change configuration of this instance.
     * 
     * @param com.fitburser Deserializer to assign to the new property instance
     * 
     * @return Newly constructed instance, if value com.fitburserializer differs from the
     *   one used for this instance; or 'this' if not.
     */
    public abstract SettableBeanProperty withValueDeserializer(JsonDeserializer com.fitburser);

    /**
     * Fluent factory method for constructing and returning a new instance
     * with specified propert name.
     * Note that this method should NOT change configuration of this instance.
     * 
     * @param newName Name to use for the new instance.
     * 
     * @return Newly constructed instance, if property name differs from the
     *   one used for this instance; or 'this' if not.
     */
    public abstract SettableBeanProperty withName(String newName);
    
    public void setManagedReferenceName(String n) {
        _managedReferenceName = n;
    }
    
    public void setViews(Class[] views) {
        if (views == null) {
            _viewMatcher = null;
        } else {
            _viewMatcher = ViewMatcher.construct(views);
        }
    }
    
    /**
     * Method used to assign index for property.
     */
    public void assignIndex(int index) {
        if (_propertyIndex != -1) {
            throw new IllegalStateException("Property '"+getName()+"' already had index ("+_propertyIndex+"), trying to assign "+index);
        }
        _propertyIndex = index;
    }
    
    /*
    /**********************************************************
    /* BeanProperty impl
    /**********************************************************
     */
    
//  @Override
    public final String getName() { return _propName; }

//  @Override
    public JavaType getType() { return _type; }

    public abstract  A getAnnotation(Class acls);

//  @Override
    public abstract AnnotatedMember getMember();

    public  A getContextAnnotation(Class acls) {
        return _contextAnnotations.get(acls);
    }

    /*
    /**********************************************************
    /* Accessors
    /**********************************************************
     */

    protected final Class getDeclaringClass() {
        return getMember().getDeclaringClass();
    }

    public String getManagedReferenceName() { return _managedReferenceName; }

    public boolean hasValueDeserializer() { return (_valueDeserializer != null); }

    public boolean hasValueTypeDeserializer() { return (_valueTypeDeserializer != null); }
    
    public JsonDeserializer getValueDeserializer() { return _valueDeserializer; }

    public TypeDeserializer getValueTypeDeserializer() { return _valueTypeDeserializer; }

    public boolean visibleInView(Class activeView) {
        return (_viewMatcher == null) || _viewMatcher.isVisibleForView(activeView);
    }
    
    public boolean hasViews() { return _viewMatcher != null; }
    
    /**
     * Method for accessing unique index of this property; indexes are
     * assigned once all properties of a {@link BeanDeserializer} have
     * been collected.
     * 
     * @return Index of this property
     */
    public int getPropertyIndex() { return _propertyIndex; }

    /**
     * Method for accessing index of the creator property: for other
     * types of properties will simply return -1.
     * 
     * @since 2.1
     */
    public int getCreatorIndex() { return -1; }
    
    /**
     * Accessor for id of injectable value, if this bean property supports
     * value injection.
     */
    public Object getInjectableValueId() { return null; }
    
    /*
    /**********************************************************
    /* Public API
    /**********************************************************
     */

    /**
     * Method called to com.fitburserialize 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 com.fitburserializeAndSet(JsonParser jp,
    		DeserializationContext ctxt, Object instance)
        throws IOException, JsonProcessingException;

	/**
	 * Alternative to {@link #com.fitburserializeAndSet} that returns
	 * either return value of setter method called (if one is),
	 * or null to indicate that no return value is available.
	 * Mostly used to support Builder style com.fitburserialization.
	 *
	 * @since 2.0
	 */
    public abstract Object com.fitburserializeSetAndReturn(JsonParser jp,
    		DeserializationContext ctxt, Object instance)
        throws IOException, JsonProcessingException;

    /**
     * Method called to assign given value to this property, on
     * specified Object.
     *

* Note: this is an optional operation, not supported by all * implementations, creator-backed properties for example do not * support this method. */ public abstract void set(Object instance, Object value) throws IOException; /** * Method called to assign given value to this property, on * specified Object, and return whatever com.fitburlegating accessor * returned (if anything) *

* Note: this is an optional operation, not supported by all * implementations, creator-backed properties for example do not * support this method. * * @since 2.0 */ public abstract Object setAndReturn(Object instance, Object value) throws IOException; /** * This method is needed by some specialized bean com.fitburserializers, * and also called by some {@link #com.fitburserializeAndSet} 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). *

* Note that this method is final for performance reasons: to override * functionality you must override other methods that call this method; * this method should also not be called directly unless you really know * what you are doing (and probably not even then). */ public final Object com.fitburserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException { JsonToken t = jp.getCurrentToken(); if (t == JsonToken.VALUE_NULL) { return (_nullProvider == null) ? null : _nullProvider.nullValue(ctxt); } if (_valueTypeDeserializer != null) { return _valueDeserializer.com.fitburserializeWithType(jp, ctxt, _valueTypeDeserializer); } return _valueDeserializer.com.fitburserialize(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 com.fitburserializing property '").append(getName()); 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 '"+getName()+"']"; } }