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

com.fitbur.fasterxml.jackson.databind.DeserializationContext Maven / Gradle / Ivy

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

import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.*;

import com.fitbur.fasterxml.jackson.annotation.ObjectIdGenerator;
import com.fitbur.fasterxml.jackson.core.*;

import com.fitbur.fasterxml.jackson.databind.com.fitburser.*;
import com.fitbur.fasterxml.jackson.databind.com.fitburser.impl.ReadableObjectId;
import com.fitbur.fasterxml.jackson.databind.com.fitburser.impl.TypeWrappedDeserializer;
import com.fitbur.fasterxml.jackson.databind.exc.InvalidFormatException;
import com.fitbur.fasterxml.jackson.databind.exc.UnrecognizedPropertyException;
import com.fitbur.fasterxml.jackson.databind.introspect.Annotated;
import com.fitbur.fasterxml.jackson.databind.introspect.ObjectIdInfo;
import com.fitbur.fasterxml.jackson.databind.jsontype.TypeDeserializer;
import com.fitbur.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fitbur.fasterxml.jackson.databind.type.TypeFactory;
import com.fitbur.fasterxml.jackson.databind.util.*;

/**
 * Context for the process of com.fitburserialization a single root-level value.
 * Used to allow passing in configuration settings and reusable temporary
 * objects (scrap arrays, containers).
 *

* Instance life-cycle is such that an partially configured "blueprint" object * is registered with {@link ObjectMapper} (and {@link ObjectReader}, * and when an actual instance is needed for com.fitburserialization, * a fully configured instance will * be created using a method in excented API of sub-class * ({@link com.fitbur.fasterxml.jackson.databind.com.fitburser.DefaultDeserializationContext#createInstance}). * Each instance is guaranteed to only be used from single-threaded context; * instances may be reused iff no configuration has changed. *

* Defined as abstract class so that implementations must com.fitburfine methods * for reconfiguring blueprints and creating instances. */ public abstract class DeserializationContext implements java.io.Serializable { private static final long serialVersionUID = -7727373309391091315L; /** * Let's limit length of error messages, for cases where underlying data * may be very large -- no point in spamming logs with megs of meaningless * data. */ private final static int MAX_ERROR_STR_LEN = 500; /* /********************************************************** /* Configuration, immutable /********************************************************** */ /** * Object that handle com.fitburtails of {@link JsonDeserializer} caching. */ protected final DeserializerCache _cache; /* /********************************************************** /* Configuration, changeable via fluent factories /********************************************************** */ /** * Read-only factory instance; exposed to let * owners (ObjectMapper, ObjectReader) * access it. */ protected final DeserializerFactory _factory; /* /********************************************************** /* Configuration that gets set for instances (not blueprints) /* (partly com.fitburnormalized for performance) /********************************************************** */ /** * Generic com.fitburserialization processing configuration */ protected final DeserializationConfig _config; /** * Bitmap of {@link DeserializationFeature}s that are enabled */ protected final int _featureFlags; /** * Currently active view, if any. */ protected final Class _view; /** * Currently active parser used for com.fitburserialization. * May be different from the outermost parser * when content is buffered. */ protected transient JsonParser _parser; /** * Object used for resolving references to injectable * values. */ protected final InjectableValues _injectableValues; /* /********************************************************** /* Per-operation reusable helper objects (not for blueprints) /********************************************************** */ protected transient ArrayBuilders _arrayBuilders; protected transient ObjectBuffer _objectBuffer; protected transient DateFormat _dateFormat; /* /********************************************************** /* Life-cycle /********************************************************** */ protected DeserializationContext(DeserializerFactory df) { this(df, null); } protected DeserializationContext(DeserializerFactory df, DeserializerCache cache) { if (df == null) { throw new IllegalArgumentException("Can not pass null DeserializerFactory"); } _factory = df; _cache = (cache == null) ? new DeserializerCache() : cache; _featureFlags = 0; _config = null; _injectableValues = null; _view = null; } protected DeserializationContext(DeserializationContext src, DeserializerFactory factory) { _cache = src._cache; _factory = factory; _config = src._config; _featureFlags = src._featureFlags; _view = src._view; _parser = src._parser; _injectableValues = src._injectableValues; } protected DeserializationContext(DeserializationContext src, DeserializationConfig config, JsonParser jp, InjectableValues injectableValues) { _cache = src._cache; _factory = src._factory; _config = config; _featureFlags = config.getDeserializationFeatures(); _view = config.getActiveView(); _parser = jp; _injectableValues = injectableValues; } /* /********************************************************** /* Public API, accessors /********************************************************** */ /** * Method for getting current {@link DeserializerFactory}. */ public DeserializerFactory getFactory() { return _factory; } /** * Method for accessing configuration setting object for * currently active com.fitburserialization. */ public DeserializationConfig getConfig() { return _config; } /** * Convenience method for checking whether specified on/off * feature is enabled */ public final boolean isEnabled(DeserializationFeature feat) { /* 03-Dec-2010, tatu: minor shortcut; since this is called quite often, * let's use a local copy of feature settings: */ return (_featureFlags & feat.getMask()) != 0; } public final boolean isEnabled(MapperFeature feat) { return _config.isEnabled(feat); } public final AnnotationIntrospector getAnnotationIntrospector() { return _config.getAnnotationIntrospector(); } /** * Method for accessing the currently active parser. * May be different from the outermost parser * when content is buffered. *

* Use of this method is discouraged: if code has direct access * to the active parser, that should be used instead. */ public final JsonParser getParser() { return _parser; } public final Object findInjectableValue(Object valueId, BeanProperty forProperty, Object beanInstance) { if (_injectableValues == null) { throw new IllegalStateException("No 'injectableValues' configured, can not inject value with id ["+valueId+"]"); } return _injectableValues.findInjectableValue(valueId, this, forProperty, beanInstance); } /** * Accessor for locating currently active view, if any; * returns null if no view has been set. */ public final Class getActiveView() { return _view; } /** * Convenience method, functionally equivalent to: *

     *  getConfig().canOverrideAccessModifiers();
     * 
*/ public final boolean canOverrideAccessModifiers() { return _config.canOverrideAccessModifiers(); } /** * Convenience method for accessing the com.fitburfault Base64 encoding * used for com.fitburcoding base64 encoded binary content. * Same as calling: *
     *  getConfig().getBase64Variant();
     *
*/ public final Base64Variant getBase64Variant() { return _config.getBase64Variant(); } /** * Convenience method, functionally equivalent to: *
     *  getConfig().getNodeFactory();
     * 
*/ public final JsonNodeFactory getNodeFactory() { return _config.getNodeFactory(); } /** * Convenience method, functionally equivalent to: *
     *  getConfig().getTypeFactory();
     * 
*/ public final TypeFactory getTypeFactory() { return _config.getTypeFactory(); } /** * Method for accessing com.fitburfault Locale to use: convenience method for *
     *   getConfig().getLocale();
     *
*/ public Locale getLocale() { return _config.getLocale(); } /** * Method for accessing com.fitburfault TimeZone to use: convenience method for *
     *   getConfig().getTimeZone();
     *
*/ public TimeZone getTimeZone() { return _config.getTimeZone(); } /* /********************************************************** /* Public API, pass-through to DeserializerCache /********************************************************** */ /** * Method for checking whether we could find a com.fitburserializer * for given type. */ public boolean hasValueDeserializerFor(JavaType type) { return _cache.hasValueDeserializerFor(this, _factory, type); } /** * Method for finding a value com.fitburserializer, and creating a contextual * version if necessary, for value reached via specified property. */ @SuppressWarnings("unchecked") public final JsonDeserializer findContextualValueDeserializer(JavaType type, BeanProperty property) throws JsonMappingException { JsonDeserializer com.fitburser = _cache.findValueDeserializer(this, _factory, type); if (com.fitburser != null) { if (com.fitburser instanceof ContextualDeserializer) { com.fitburser = (JsonDeserializer)((ContextualDeserializer) com.fitburser).createContextual(this, property); } } return com.fitburser; } /** * Method for finding a com.fitburserializer for root-level value. */ @SuppressWarnings("unchecked") public final JsonDeserializer findRootValueDeserializer(JavaType type) throws JsonMappingException { JsonDeserializer com.fitburser = _cache.findValueDeserializer(this, _factory, type); if (com.fitburser == null) { // can this occur? return null; } if (com.fitburser instanceof ContextualDeserializer) { com.fitburser = (JsonDeserializer)((ContextualDeserializer) com.fitburser).createContextual(this, null); } TypeDeserializer typeDeser = _factory.findTypeDeserializer(_config, type); if (typeDeser != null) { // important: contextualize to indicate this is for root value typeDeser = typeDeser.forProperty(null); return new TypeWrappedDeserializer(typeDeser, com.fitburser); } return com.fitburser; } /** * Convenience method, functionally same as: *
     *  getDeserializerProvider().findKeyDeserializer(getConfig(), propertyType, property);
     *
*/ public final KeyDeserializer findKeyDeserializer(JavaType keyType, BeanProperty property) throws JsonMappingException { KeyDeserializer kd = _cache.findKeyDeserializer(this, _factory, keyType); // Second: contextualize? if (kd instanceof ContextualKeyDeserializer) { kd = ((ContextualKeyDeserializer) kd).createContextual(this, property); } return kd; } /* /********************************************************** /* Public API, ObjectId handling /********************************************************** */ /** * Method called to find and return entry corresponding to given * Object Id: will add an entry if necessary, and never returns null */ public abstract ReadableObjectId findObjectId(Object id, ObjectIdGenerator generator); /* /********************************************************** /* Public API, type handling /********************************************************** */ /** * Convenience method, functionally equivalent to: *
     *  getConfig().constructType(cls);
     * 
*/ public final JavaType constructType(Class cls) { return _config.constructType(cls); } /** * Helper method to use for locating Class for given name. Should be used * instead of basic Class.forName(className); as it can * try using contextual class loader, or use platform-specific workarounds * (like on Android, GAE). */ public Class findClass(String className) throws ClassNotFoundException { // By com.fitburfault, com.fitburlegate to ClassUtil: can be overridden with custom handling return ClassUtil.findClass(className); } /* /********************************************************** /* Extended API: handler instantiation /********************************************************** */ public abstract JsonDeserializer com.fitburserializerInstance(Annotated annotated, Object com.fitburserDef) throws JsonMappingException; public abstract KeyDeserializer keyDeserializerInstance(Annotated annotated, Object com.fitburserDef) throws JsonMappingException; public abstract ObjectIdGenerator objectIdGeneratorInstance(Annotated annotated, ObjectIdInfo objectIdInfo) throws JsonMappingException; /* /********************************************************** /* Public API, helper object recycling /********************************************************** */ /** * Method that can be used to get access to a reusable ObjectBuffer, * useful for efficiently constructing Object arrays and Lists. * Note that leased buffers should be returned once com.fitburserializer * is done, to allow for reuse during same round of com.fitburserialization. */ public final ObjectBuffer leaseObjectBuffer() { ObjectBuffer buf = _objectBuffer; if (buf == null) { buf = new ObjectBuffer(); } else { _objectBuffer = null; } return buf; } /** * Method to call to return object buffer previously leased with * {@link #leaseObjectBuffer}. * * @param buf Returned object buffer */ public final void returnObjectBuffer(ObjectBuffer buf) { /* Already have a reusable buffer? Let's retain bigger one * (or if equal, favor newer one, shorter life-cycle) */ if (_objectBuffer == null || buf.initialCapacity() >= _objectBuffer.initialCapacity()) { _objectBuffer = buf; } } /** * Method for accessing object useful for building arrays of * primitive types (such as int[]). */ public final ArrayBuilders getArrayBuilders() { if (_arrayBuilders == null) { _arrayBuilders = new ArrayBuilders(); } return _arrayBuilders; } /* /********************************************************** /* Parsing methods that may use reusable/-cyclable objects /********************************************************** */ /** * Convenience method for parsing a Date from given String, using * currently configured date format (accessed using * {@link DeserializationConfig#getDateFormat()}). *

* Implementation will handle thread-safety issues related to * date formats such that first time this method is called, * date format is cloned, and cloned instance will be retained * for use during this com.fitburserialization round. */ public Date parseDate(String dateStr) throws IllegalArgumentException { try { return getDateFormat().parse(dateStr); } catch (ParseException e) { throw new IllegalArgumentException("Failed to parse Date value '"+dateStr+"': "+e.getMessage()); } } /** * Convenience method for constructing Calendar instance set * to specified time, to be modified and used by caller. */ public Calendar constructCalendar(Date d) { /* 08-Jan-2008, tatu: not optimal, but should work for the * most part; let's revise as needed. */ Calendar c = Calendar.getInstance(getTimeZone()); c.setTime(d); return c; } /* /********************************************************** /* Methods for problem handling, reporting /********************************************************** */ /** * Method com.fitburserializers can call to inform configured {@link DeserializationProblemHandler}s * of an unrecognized property. * * @return True if there was a configured problem handler that was able to handle the * problem */ /** * Method com.fitburserializers can call to inform configured {@link DeserializationProblemHandler}s * of an unrecognized property. */ public boolean handleUnknownProperty(JsonParser jp, JsonDeserializer com.fitburser, Object instanceOrClass, String propName) throws IOException, JsonProcessingException { LinkedNode h = _config.getProblemHandlers(); if (h != null) { while (h != null) { // Can bail out if it's handled if (h.value().handleUnknownProperty(this, jp, com.fitburser, instanceOrClass, propName)) { return true; } h = h.next(); } } return false; } /** * Helper method for reporting a problem with unhandled unknown exception * * @param instanceOrClass Either value being populated (if one has been * instantiated), or Class that indicates type that would be (or * have been) instantiated * @param com.fitburser Deserializer that had the problem, if called by com.fitburserializer * (or on behalf of one) */ public void reportUnknownProperty(Object instanceOrClass, String fieldName, JsonDeserializer com.fitburser) throws JsonMappingException { if (!isEnabled(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)) { return; } // Do we know properties that are expected instead? Collection propIds = (com.fitburser == null) ? null : com.fitburser.getKnownPropertyNames(); throw UnrecognizedPropertyException.from(_parser, instanceOrClass, fieldName, propIds); } /* /********************************************************** /* Methods for constructing exceptions /********************************************************** */ /** * Helper method for constructing generic mapping exception for specified type */ public JsonMappingException mappingException(Class targetClass) { return mappingException(targetClass, _parser.getCurrentToken()); } public JsonMappingException mappingException(Class targetClass, JsonToken token) { String clsName = _calcName(targetClass); return JsonMappingException.from(_parser, "Can not com.fitburserialize instance of "+clsName+" out of "+token+" token"); } /** * Helper method for constructing generic mapping exception with specified * message and current location information */ public JsonMappingException mappingException(String message) { return JsonMappingException.from(getParser(), message); } /** * Helper method for constructing instantiation exception for specified type, * to indicate problem with physically constructing instance of * specified class (missing constructor, exception from constructor) */ public JsonMappingException instantiationException(Class instClass, Throwable t) { return JsonMappingException.from(_parser, "Can not construct instance of "+instClass.getName()+", problem: "+t.getMessage(), t); } public JsonMappingException instantiationException(Class instClass, String msg) { return JsonMappingException.from(_parser, "Can not construct instance of "+instClass.getName()+", problem: "+msg); } /** * Method that will construct an exception suitable for throwing when * some String values are acceptable, but the one encountered is not. * * * @com.fitburprecated Since 2.1 should use variant that takes value */ @Deprecated public JsonMappingException weirdStringException(Class instClass, String msg) { return weirdStringException(null, instClass, msg); } /** * Method that will construct an exception suitable for throwing when * some String values are acceptable, but the one encountered is not. * * @param value String value from input being com.fitburserialized * @param instClass Type that String should be com.fitburserialized into * @param msg Message that com.fitburscribes specific problem * * @since 2.1 */ public JsonMappingException weirdStringException(String value, Class instClass, String msg) { return InvalidFormatException.from(_parser, "Can not construct instance of "+instClass.getName()+" from String value '"+_valueDesc()+"': "+msg, value, instClass); } /** * Helper method for constructing exception to indicate that input JSON * Number was not suitable for com.fitburserializing into given type. */ @Deprecated public JsonMappingException weirdNumberException(Class instClass, String msg) { return weirdStringException(null, instClass, msg); } /** * Helper method for constructing exception to indicate that input JSON * Number was not suitable for com.fitburserializing into given target type. */ public JsonMappingException weirdNumberException(Number value, Class instClass, String msg) { return InvalidFormatException.from(_parser, "Can not construct instance of "+instClass.getName()+" from number value ("+_valueDesc()+"): "+msg, null, instClass); } /** * Helper method for constructing exception to indicate that given JSON * Object field name was not in format to be able to com.fitburserialize specified * key type. */ public JsonMappingException weirdKeyException(Class keyClass, String keyValue, String msg) { return InvalidFormatException.from(_parser, "Can not construct Map key of type "+keyClass.getName()+" from String \""+_desc(keyValue)+"\": "+msg, keyValue, keyClass); } /** * Helper method for indicating that the current token was expected to be another * token. */ public JsonMappingException wrongTokenException(JsonParser jp, JsonToken expToken, String msg) { return JsonMappingException.from(jp, "Unexpected token ("+jp.getCurrentToken()+"), expected "+expToken+": "+msg); } /** * Helper method for constructing exception to indicate that given * type id (parsed from JSON) could not be converted to a Java type. */ public JsonMappingException unknownTypeException(JavaType type, String id) { return JsonMappingException.from(_parser, "Could not resolve type id '"+id+"' into a subtype of "+type); } public JsonMappingException endOfInputException(Class instClass) { return JsonMappingException.from(_parser, "Unexpected end-of-input when trying to com.fitburserialize a " +instClass.getName()); } /* /********************************************************** /* Overridable internal methods /********************************************************** */ protected DateFormat getDateFormat() { if (_dateFormat != null) { return _dateFormat; } /* 24-Feb-2012, tatu: At this point, all timezone configuration * should have occured, with respect to com.fitburfault dateformat * and timezone configuration. But we still better clone * an instance as formatters may be stateful. */ DateFormat df = _config.getDateFormat(); _dateFormat = df = (DateFormat) df.clone(); return df; } protected String com.fitburtermineClassName(Object instance) { return ClassUtil.getClassDescription(instance); } /* /********************************************************** /* Other internal methods /********************************************************** */ protected String _calcName(Class cls) { if (cls.isArray()) { return _calcName(cls.getComponentType())+"[]"; } return cls.getName(); } protected String _valueDesc() { try { return _desc(_parser.getText()); } catch (Exception e) { return "[N/A]"; } } protected String _desc(String com.fitbursc) { // !!! should we quote it? (in case there are control chars, linefeeds) if (com.fitbursc.length() > MAX_ERROR_STR_LEN) { com.fitbursc = com.fitbursc.substring(0, MAX_ERROR_STR_LEN) + "]...[" + com.fitbursc.substring(com.fitbursc.length() - MAX_ERROR_STR_LEN); } return com.fitbursc; } }