Package org.codehaus.jackson.map.deser

Source Code of org.codehaus.jackson.map.deser.Creator$PropertyBased

package org.codehaus.jackson.map.deser;

import java.io.IOException;
import java.lang.reflect.*;
import java.util.*;

import org.codehaus.jackson.*;
import org.codehaus.jackson.type.JavaType;
import org.codehaus.jackson.map.*;
import org.codehaus.jackson.map.introspect.AnnotatedConstructor;
import org.codehaus.jackson.map.introspect.AnnotatedMember;
import org.codehaus.jackson.map.introspect.AnnotatedMethod;
import org.codehaus.jackson.map.introspect.BasicBeanDescription;
import org.codehaus.jackson.map.type.TypeBindings;
import org.codehaus.jackson.map.util.ClassUtil;

/**
* Container for different kinds of Creators; objects capable of instantiating
* (and possibly partially or completely initializing) POJOs.
*/
abstract class Creator
{
    // Class only used for namespacing, not as base class
    private Creator() { }

    /**
     * Creator implementation that can handle simple deserialization from
     * Json String values.
     */
    final static class StringBased
    {
        protected final Class<?> _valueClass;
        protected final Method _factoryMethod;
        protected final Constructor<?> _ctor;

        public StringBased(Class<?> valueClass, AnnotatedConstructor ctor,
                             AnnotatedMethod factoryMethod)
        {
            _valueClass = valueClass;
            _ctor = (ctor == null) ? null : ctor.getAnnotated();
            _factoryMethod = (factoryMethod == null) ? null : factoryMethod.getAnnotated();
        }

        public Object construct(String value)
        {
            try {
                if (_ctor != null) {
                    return _ctor.newInstance(value);
                }
                if (_factoryMethod != null) {
                    return _factoryMethod.invoke(_valueClass, value);
                }
            } catch (Exception e) {
                ClassUtil.unwrapAndThrowAsIAE(e);
            }
            return null;
        }
    }

    /**
     * Creator implementation that can handle simple deserialization from
     * Json Number values.
     */
    final static class NumberBased
    {
        protected final Class<?> _valueClass;

        protected final Constructor<?> _intCtor;
        protected final Constructor<?> _longCtor;

        protected final Method _intFactoryMethod;
        protected final Method _longFactoryMethod;

        public NumberBased(Class<?> valueClass,
                          AnnotatedConstructor intCtor, AnnotatedMethod ifm,
                          AnnotatedConstructor longCtor, AnnotatedMethod lfm)
        {
            _valueClass = valueClass;
            _intCtor = (intCtor == null) ? null : intCtor.getAnnotated();
            _longCtor = (longCtor == null) ? null : longCtor.getAnnotated();
            _intFactoryMethod = (ifm == null) ? null : ifm.getAnnotated();
            _longFactoryMethod = (lfm == null) ? null : lfm.getAnnotated();
        }

        public Object construct(int value)
        {
            // First: "native" int methods work best:
            try {
                if (_intCtor != null) {
                    return _intCtor.newInstance(value);
                }
                if (_intFactoryMethod != null) {
                    return _intFactoryMethod.invoke(_valueClass, Integer.valueOf(value));
                }
            } catch (Exception e) {
                ClassUtil.unwrapAndThrowAsIAE(e);
            }
            // but if not, can do widening conversion
            return construct((long) value);
        }

        public Object construct(long value)
        {
            /* For longs we don't even try casting down to ints;
             * theoretically could try if value fits... but let's
             * leave that as a future improvement
             */
            try {
                if (_longCtor != null) {
                    return _longCtor.newInstance(value);
                }
                if (_longFactoryMethod != null) {
                    return _longFactoryMethod.invoke(_valueClass, Long.valueOf(value));
                }
            } catch (Exception e) {
                ClassUtil.unwrapAndThrowAsIAE(e);
            }
            return null;
        }
    }

    /**
     * Creator implementation used for cases where parts of deserialization
     * are delegated to another serializer, by first binding to an intermediate
     * object, and then passing that object to the delegate creator (and
     * then deserializer).
     */
    final static class Delegating
    {
        /**
         * Annotated creator object (single-argument constructor or
         * single-argument static method) that is used for instantation;
         * as well as for providing contextual information.
         */
        protected final AnnotatedMember _creator;
       
  /**
   * Type to deserialize JSON to, as well as the type to pass to
   * creator (constructor, factory method)
   */
  protected final JavaType _valueType;

        protected final Constructor<?> _ctor;
        protected final Method _factoryMethod;

  /**
   * Delegate deserializer to use for actual deserialization, before
   * instantiating value
   */
  protected JsonDeserializer<Object> _deserializer;

        public Delegating(BasicBeanDescription beanDesc, AnnotatedConstructor ctor, AnnotatedMethod factory)
        {
            TypeBindings bindings = beanDesc.bindingsForBeanType();
            if (ctor != null) {
                _creator = ctor;
                _ctor = ctor.getAnnotated();
                _factoryMethod = null;
                _valueType = bindings.resolveType(ctor.getParameterType(0));
            } else if (factory != null) {
                _creator = factory;
                _ctor = null;
                _factoryMethod = factory.getAnnotated();
                _valueType = bindings.resolveType(factory.getParameterType(0));
            } else {
                throw new IllegalArgumentException("Internal error: neither delegating constructor nor factory method passed");
            }
  }

  public JavaType getValueType() { return _valueType; }

  public AnnotatedMember getCreator() { return _creator; }
 
  public void setDeserializer(JsonDeserializer<Object> deser)
  {
      _deserializer = deser;
  }

  public Object deserialize(JsonParser jp, DeserializationContext ctxt)
      throws IOException, JsonProcessingException
  {
      Object value = _deserializer.deserialize(jp, ctxt);
            try {
                if (_ctor != null) {
                    return _ctor.newInstance(value);
                }
                // static method, 'obj' can be null
    return _factoryMethod.invoke(null, value);
            } catch (Exception e) {
                ClassUtil.unwrapAndThrowAsIAE(e);
    return null;
            }
  }
    }

    /**
     * Creator implementation used to handle details of using a "non-default"
     * creator (constructor or factory that takes one or more arguments
     * that represent logical bean properties)
     */
    final static class PropertyBased
    {
        protected final Constructor<?> _ctor;
        protected final Method _factoryMethod;
       
        /**
         * Map that contains property objects for either constructor or factory
         * method (whichever one is null: one property for each
         * parameter for that one), keyed by logical property name
         */
        protected final HashMap<String, SettableBeanProperty> _properties;

        /**
         * If some property values must always have a non-null value (like
         * primitive types do), this array contains such default values.
         */
        protected final Object[]  _defaultValues;
       
        public PropertyBased(AnnotatedConstructor ctor, SettableBeanProperty[] ctorProps,
                AnnotatedMethod factory, SettableBeanProperty[] factoryProps)
        {
            // We will only use one: and constructor has precedence over factory
            SettableBeanProperty[] props;
            if (ctor != null) {
                _ctor = ctor.getAnnotated();
                _factoryMethod = null;
                props = ctorProps;
            } else if (factory != null) {
                _ctor = null;
                _factoryMethod = factory.getAnnotated();
                props = factoryProps;
            } else {
                throw new IllegalArgumentException("Internal error: neither delegating constructor nor factory method passed");
            }
            _properties = new HashMap<String, SettableBeanProperty>();
            // [JACKSON-372]: primitive types need extra care
            Object[] defValues = null;
            for (int i = 0, len = props.length; i < len; ++i) {
                SettableBeanProperty prop = props[i];
                _properties.put(prop.getName(), prop);
                if (prop.getType().isPrimitive()) {
                    if (defValues == null) {
                        defValues = new Object[len];
                    }
                    defValues[i] = ClassUtil.defaultValue(prop.getType().getRawClass());
                }
            }
            _defaultValues = defValues;
        }
       
        public Collection<SettableBeanProperty> properties() {
            return _properties.values();
        }
       
        public SettableBeanProperty findCreatorProperty(String name) {
            return _properties.get(name);
        }
       
        /**
         * Method called when starting to build a bean instance.
         */
        public PropertyValueBuffer startBuilding(JsonParser jp, DeserializationContext ctxt)
        {
            return new PropertyValueBuffer(jp, ctxt, _properties.size());
        }
       
        public Object build(PropertyValueBuffer buffer)
            throws Exception
        {
            Object bean;
            try {
                if (_ctor != null) {
                    bean = _ctor.newInstance(buffer.getParameters(_defaultValues));
                } else {
                    bean =  _factoryMethod.invoke(null, buffer.getParameters(_defaultValues));
                }
            } catch (Exception e) {
                ClassUtil.throwRootCause(e);
                return null; // never gets here
            }
            // Anything buffered?
            for (PropertyValue pv = buffer.buffered(); pv != null; pv = pv.next) {
                pv.assign(bean);
            }
            return bean;
        }
    }
}
TOP

Related Classes of org.codehaus.jackson.map.deser.Creator$PropertyBased

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.