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.
com.dyuproject.protostuff.runtime.RuntimeFieldFactory Maven / Gradle / Ivy
//========================================================================
//Copyright 2007-2009 David Yu [email protected]
//------------------------------------------------------------------------
//Licensed under the Apache License, Version 2.0 (the "License");
//you may not use this file except in compliance with the License.
//You may obtain a copy of the License at
//http://www.apache.org/licenses/LICENSE-2.0
//Unless required by applicable law or agreed to in writing, software
//distributed under the License is distributed on an "AS IS" BASIS,
//WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//See the License for the specific language governing permissions and
//limitations under the License.
//========================================================================
package com.dyuproject.protostuff.runtime;
import static com.dyuproject.protostuff.runtime.RuntimeEnv.COLLECTION_SCHEMA_ON_REPEATED_FIELDS;
import static com.dyuproject.protostuff.runtime.RuntimeEnv.MORPH_NON_FINAL_POJOS;
import static com.dyuproject.protostuff.runtime.RuntimeEnv.USE_SUN_MISC_UNSAFE;
import java.lang.reflect.Array;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import com.dyuproject.protostuff.ByteString;
import com.dyuproject.protostuff.Message;
import com.dyuproject.protostuff.Morph;
import com.dyuproject.protostuff.runtime.MappedSchema.Field;
/**
* A factory to create runtime {@link MappedSchema.Field fields} based on reflection.
*
* @author David Yu
* @created Nov 10, 2009
*/
public abstract class RuntimeFieldFactory implements Delegate
{
static final int ID_BOOL = 1, ID_BYTE = 2, ID_CHAR = 3, ID_SHORT = 4,
ID_INT32 = 5, ID_INT64 = 6, ID_FLOAT = 7, ID_DOUBLE = 8,
ID_STRING = 9, ID_BYTES = 10, ID_BYTE_ARRAY = 11,
ID_BIGDECIMAL = 12, ID_BIGINTEGER = 13, ID_DATE = 14,
ID_ARRAY = 15, // 1-15 is encoded as 1 byte on protobuf and protostuff format
ID_OBJECT = 16,
ID_ARRAY_MAPPED = 17,
ID_CLASS = 18,
ID_CLASS_MAPPED = 19,
ID_CLASS_ARRAY = 20,
ID_CLASS_ARRAY_MAPPED = 21,
ID_ENUM_SET = 22,
ID_ENUM_MAP = 23,
ID_ENUM = 24,
ID_COLLECTION = 25,
ID_MAP = 26,
ID_POLYMORPHIC_COLLECTION = 28,
ID_POLYMORPHIC_MAP = 29,
ID_DELEGATE = 30,
ID_ARRAY_DELEGATE = 32,
ID_ARRAY_SCALAR = 33,
ID_ARRAY_ENUM = 34,
ID_ARRAY_POJO = 35,
ID_THROWABLE = 52,
// pojo fields limited to 126 if not explicitly using @Tag annotations
ID_POJO = 127;
static final String STR_BOOL = "a", STR_BYTE = "b", STR_CHAR = "c", STR_SHORT = "d",
STR_INT32 = "e", STR_INT64 = "f", STR_FLOAT = "g", STR_DOUBLE = "h",
STR_STRING = "i", STR_BYTES = "j", STR_BYTE_ARRAY = "k",
STR_BIGDECIMAL = "l", STR_BIGINTEGER = "m", STR_DATE = "n",
STR_ARRAY = "o",
STR_OBJECT = "p",
STR_ARRAY_MAPPED = "q",
STR_CLASS = "r",
STR_CLASS_MAPPED = "s",
STR_CLASS_ARRAY = "t",
STR_CLASS_ARRAY_MAPPED = "u",
STR_ENUM_SET = "v",
STR_ENUM_MAP = "w",
STR_ENUM = "x",
STR_COLLECTION = "y",
STR_MAP = "z",
STR_POLYMORPHIC_COLLECTION = "B",
STR_POLYMOPRHIC_MAP = "C",
STR_DELEGATE = "D",
STR_ARRAY_DELEGATE = "F",
STR_ARRAY_SCALAR = "G",
STR_ARRAY_ENUM = "H",
STR_ARRAY_POJO = "I",
STR_THROWABLE = "Z",
// pojo fields limited to 126 if not explicitly using @Tag annotations
STR_POJO = "_";
private static final HashMap> __inlineValues =
new HashMap>();
static final RuntimeFieldFactory BIGDECIMAL;
static final RuntimeFieldFactory BIGINTEGER;
static final RuntimeFieldFactory BOOL;
static final RuntimeFieldFactory BYTE;
static final RuntimeFieldFactory BYTES;
static final RuntimeFieldFactory BYTE_ARRAY;
static final RuntimeFieldFactory CHAR;
static final RuntimeFieldFactory DATE;
static final RuntimeFieldFactory DOUBLE;
static final RuntimeFieldFactory FLOAT;
static final RuntimeFieldFactory INT32;
static final RuntimeFieldFactory INT64;
static final RuntimeFieldFactory SHORT;
static final RuntimeFieldFactory STRING;
static final RuntimeFieldFactory ENUM;
static final RuntimeFieldFactory OBJECT;
static final RuntimeFieldFactory POJO;
static final RuntimeFieldFactory POLYMORPHIC_POJO;
static final RuntimeFieldFactory> COLLECTION;
static final RuntimeFieldFactory DELEGATE;
// for repeated/collection fields.
static final Accessor.Factory ACCESSOR_FACTORY;
static
{
if(USE_SUN_MISC_UNSAFE)
{
BIGDECIMAL = RuntimeUnsafeFieldFactory.BIGDECIMAL;
BIGINTEGER = RuntimeUnsafeFieldFactory.BIGINTEGER;
BOOL = RuntimeUnsafeFieldFactory.BOOL;
BYTE = RuntimeUnsafeFieldFactory.BYTE;
BYTES = RuntimeUnsafeFieldFactory.BYTES;
BYTE_ARRAY = RuntimeUnsafeFieldFactory.BYTE_ARRAY;
CHAR = RuntimeUnsafeFieldFactory.CHAR;
DATE = RuntimeUnsafeFieldFactory.DATE;
DOUBLE = RuntimeUnsafeFieldFactory.DOUBLE;
FLOAT = RuntimeUnsafeFieldFactory.FLOAT;
INT32 = RuntimeUnsafeFieldFactory.INT32;
INT64 = RuntimeUnsafeFieldFactory.INT64;
SHORT = RuntimeUnsafeFieldFactory.SHORT;
STRING = RuntimeUnsafeFieldFactory.STRING;
ENUM = RuntimeUnsafeFieldFactory.ENUM;
OBJECT = RuntimeUnsafeFieldFactory.OBJECT;
POJO = RuntimeUnsafeFieldFactory.POJO;
POLYMORPHIC_POJO = RuntimeUnsafeFieldFactory.POLYMORPHIC_POJO;
DELEGATE = RuntimeUnsafeFieldFactory.DELEGATE;
ACCESSOR_FACTORY = UnsafeAccessor.FACTORY;
}
else
{
BIGDECIMAL = RuntimeReflectionFieldFactory.BIGDECIMAL;
BIGINTEGER = RuntimeReflectionFieldFactory.BIGINTEGER;
BOOL = RuntimeReflectionFieldFactory.BOOL;
BYTE = RuntimeReflectionFieldFactory.BYTE;
BYTES = RuntimeReflectionFieldFactory.BYTES;
BYTE_ARRAY = RuntimeReflectionFieldFactory.BYTE_ARRAY;
CHAR = RuntimeReflectionFieldFactory.CHAR;
DATE = RuntimeReflectionFieldFactory.DATE;
DOUBLE = RuntimeReflectionFieldFactory.DOUBLE;
FLOAT = RuntimeReflectionFieldFactory.FLOAT;
INT32 = RuntimeReflectionFieldFactory.INT32;
INT64 = RuntimeReflectionFieldFactory.INT64;
SHORT = RuntimeReflectionFieldFactory.SHORT;
STRING = RuntimeReflectionFieldFactory.STRING;
ENUM = RuntimeReflectionFieldFactory.ENUM;
OBJECT = RuntimeReflectionFieldFactory.OBJECT;
POJO = RuntimeReflectionFieldFactory.POJO;
POLYMORPHIC_POJO = RuntimeReflectionFieldFactory.POLYMORPHIC_POJO;
DELEGATE = RuntimeReflectionFieldFactory.DELEGATE;
ACCESSOR_FACTORY = ReflectAccessor.FACTORY;
}
COLLECTION = COLLECTION_SCHEMA_ON_REPEATED_FIELDS ?
RuntimeCollectionFieldFactory.getFactory() :
RuntimeRepeatedFieldFactory.getFactory();
__inlineValues.put(Integer.TYPE.getName(), INT32);
__inlineValues.put(Integer.class.getName(), INT32);
__inlineValues.put(Long.TYPE.getName(), INT64);
__inlineValues.put(Long.class.getName(), INT64);
__inlineValues.put(Float.TYPE.getName(), FLOAT);
__inlineValues.put(Float.class.getName(), FLOAT);
__inlineValues.put(Double.TYPE.getName(), DOUBLE);
__inlineValues.put(Double.class.getName(), DOUBLE);
__inlineValues.put(Boolean.TYPE.getName(), BOOL);
__inlineValues.put(Boolean.class.getName(), BOOL);
__inlineValues.put(Character.TYPE.getName(), CHAR);
__inlineValues.put(Character.class.getName(), CHAR);
__inlineValues.put(Short.TYPE.getName(), SHORT);
__inlineValues.put(Short.class.getName(), SHORT);
__inlineValues.put(Byte.TYPE.getName(), BYTE);
__inlineValues.put(Byte.class.getName(), BYTE);
__inlineValues.put(String.class.getName(), STRING);
__inlineValues.put(ByteString.class.getName(), BYTES);
__inlineValues.put(byte[].class.getName(), BYTE_ARRAY);
__inlineValues.put(BigInteger.class.getName(), BIGINTEGER);
__inlineValues.put(BigDecimal.class.getName(), BIGDECIMAL);
__inlineValues.put(Date.class.getName(), DATE);
}
/**
* Gets the runtime field factory of the given {@code clazz}.
*
* Method overload for backwards compatibility.
*/
public static RuntimeFieldFactory> getFieldFactory(Class> clazz)
{
return getFieldFactory(clazz, RuntimeEnv.ID_STRATEGY);
}
/**
* Gets the runtime field factory of the given {@code clazz}.
*/
public static RuntimeFieldFactory> getFieldFactory(Class> clazz,
IdStrategy strategy)
{
if(strategy.isDelegateRegistered(clazz))
return DELEGATE;
final RuntimeFieldFactory> inline = __inlineValues.get(clazz.getName());
if(inline != null)
return inline;
if(Message.class.isAssignableFrom(clazz))
return POJO;
if(clazz.isEnum())
return ENUM;
// Of all the scalar (inline) fields, java.lang.Number is the only abstract
// super type, hence we can filter it here
// Note that it has 10 built-in subtypes
if(clazz.isArray() || Object.class == clazz || Number.class == clazz
|| Class.class == clazz || Enum.class == clazz
|| Throwable.class.isAssignableFrom(clazz))
{
return OBJECT;
}
if (strategy.isRegistered(clazz))
return clazz.isInterface() ? POJO : POLYMORPHIC_POJO;
if(Map.class.isAssignableFrom(clazz))
return RuntimeMapFieldFactory.MAP;
if(Collection.class.isAssignableFrom(clazz))
{
// repeated fields.
return COLLECTION;
}
// Enums or boxed types of primitives do implement interfaces.
// Although serializing polymorphic pojos declared as interfaces will be a
// little bit slower than before, this is more correct.
//
// In versions prior to 1.0.5, it would serialize a field declared as
// java.lang.Serializable like a polymorphic pojo even though it
// gets assigned enum/string/number types.
//
// If you have declared fields as serializable, it wont be compatible
if(clazz.isInterface())
return OBJECT;
// checks delegated to POLYMORPHIC_POJO
return POLYMORPHIC_POJO;
}
static boolean pojo(Class> clazz, Morph morph, IdStrategy strategy)
{
if(Modifier.isFinal(clazz.getModifiers()))
return true;
// check if user mapped an impl to this class
if(Modifier.isAbstract(clazz.getModifiers()))
return strategy.isRegistered(clazz);
// the user can annotate fields with @Morph to have full control if
// he knows a certain field will be set with a subtype.
// To reverse the behavior (no subtype will be set), annotate with @Morph(false)
// This is an optimization that requires the user's full knowledge of his dataset.
if(morph != null)
return !morph.value();
return !MORPH_NON_FINAL_POJOS;
}
static Class> getGenericType(java.lang.reflect.Field f, int index)
{
try
{
Type type = ((ParameterizedType)f.getGenericType()).getActualTypeArguments()[index];
if(type instanceof GenericArrayType)
{
int dimensions = 1;
Type componentType = ((GenericArrayType)type).getGenericComponentType();
while(componentType instanceof GenericArrayType)
{
dimensions++;
componentType = ((GenericArrayType)componentType).getGenericComponentType();
}
// TODO is there a more efficient way (reflection) to obtain an array class?
if(dimensions == 1)
return Array.newInstance((Class>)componentType, 0).getClass();
final int[] arg = new int[dimensions];
arg[0] = 0;
return Array.newInstance((Class>)componentType, arg).getClass();
}
if(type instanceof ParameterizedType)
{
// TODO in the future, we can opt to do recursive type
// inspection which can avoid including type metadata even with
// very complex nested generic types (E.g a List>>).
// special handling when generic type is either Class> or Enum>
Object rawType = ((ParameterizedType)type).getRawType();
if(Class.class == rawType)
return Class.class;
if(Enum.class == rawType)
return Enum.class;
return null;
}
return (Class>)type;
}
catch(Exception e)
{
return null;
}
}
@SuppressWarnings("unchecked")
static Delegate getDelegateOrInline(Class typeClass,
IdStrategy strategy)
{
Delegate d = strategy.getDelegate(typeClass);
if(d == null)
d = (RuntimeFieldFactory)__inlineValues.get(typeClass.getName());
return d;
}
/**
* Returns the factory for inline (scalar) values.
*/
@SuppressWarnings("unchecked")
public static RuntimeFieldFactory getInline(Class typeClass)
{
return (RuntimeFieldFactory)__inlineValues.get(typeClass.getName());
}
/**
* Returns the factory for inline (scalar) values.
*/
@SuppressWarnings("unchecked")
static RuntimeFieldFactory getInline(String className)
{
return (RuntimeFieldFactory)__inlineValues.get(className);
}
/**
* Used by {@link ObjectSchema} to serialize dynamic (polymorphic) fields.
*/
final int id;
public RuntimeFieldFactory(int id)
{
this.id = id;
}
/**
* Creates a runtime {@link MappedSchema.Field field} based on reflection.
*/
public abstract Field create(int number, java.lang.String name,
java.lang.reflect.Field field, IdStrategy strategy);
}