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.
io.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 io.protostuff.runtime;
import static io.protostuff.runtime.RuntimeEnv.COLLECTION_SCHEMA_ON_REPEATED_FIELDS;
import static io.protostuff.runtime.RuntimeEnv.MORPH_NON_FINAL_POJOS;
import static io.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 io.protostuff.ByteString;
import io.protostuff.Message;
import io.protostuff.Morph;
/**
* A factory to create runtime {@link 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;
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;
}
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;
}
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 (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 strategy.isRegistered(clazz) ? POJO : 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 Field field} based on reflection.
*/
public abstract Field create(int number, java.lang.String name,
java.lang.reflect.Field field, IdStrategy strategy);
}