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.RuntimeCollectionFieldFactory Maven / Gradle / Ivy
//========================================================================
//Copyright 2007-2011 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 java.io.IOException;
import java.lang.reflect.Modifier;
import java.util.Collection;
import java.util.EnumSet;
import java.util.Map;
import com.dyuproject.protostuff.CollectionSchema.MessageFactory;
import com.dyuproject.protostuff.GraphInput;
import com.dyuproject.protostuff.Input;
import com.dyuproject.protostuff.Message;
import com.dyuproject.protostuff.Morph;
import com.dyuproject.protostuff.Output;
import com.dyuproject.protostuff.Pipe;
import com.dyuproject.protostuff.Schema;
import com.dyuproject.protostuff.Tag;
import com.dyuproject.protostuff.WireFormat.FieldType;
import com.dyuproject.protostuff.runtime.MappedSchema.Field;
/**
* Static utility for creating runtime {@link Collection} fields.
*
* @author David Yu
* @created Jan 26, 2011
*/
final class RuntimeCollectionFieldFactory
{
private RuntimeCollectionFieldFactory() {}
/**
* For lazy initialization called by {@link RuntimeFieldFactory}.
*/
static RuntimeFieldFactory> getFactory()
{
return COLLECTION;
}
static final Accessor.Factory ACCESSOR_FACTORY = RuntimeFieldFactory.ACCESSOR_FACTORY;
/*private static final DerivativeSchema POLYMORPHIC_COLLECTION_VALUE_SCHEMA =
new DerivativeSchema()
{
@SuppressWarnings("unchecked")
protected void doMergeFrom(Input input, Schema derivedSchema,
Object owner) throws IOException
{
final Object value = derivedSchema.newMessage();
// the owner will always be a Collection
((Collection)owner).add(value);
if(input instanceof GraphInput)
{
// update the actual reference.
((GraphInput)input).updateLast(value, owner);
}
derivedSchema.mergeFrom(input, value);
}
};*/
/*private static final ObjectSchema OBJECT_COLLECTION_VALUE_SCHEMA = new ObjectSchema()
{
@SuppressWarnings("unchecked")
protected void setValue(Object value, Object owner)
{
// the owner will always be a Collection
((Collection)owner).add(value);
}
};*/
private static Field createCollectionInlineV(int number, String name,
final java.lang.reflect.Field f, MessageFactory messageFactory,
final Delegate inline)
{
final Accessor accessor = ACCESSOR_FACTORY.create(f);
return new RuntimeCollectionField(
inline.getFieldType(),
number, name, f.getAnnotation(Tag.class),
messageFactory)
{
protected void mergeFrom(Input input, T message) throws IOException
{
accessor.set(message, input.mergeObject(
accessor.>get(message), schema));
}
protected void writeTo(Output output, T message) throws IOException
{
final Collection existing = accessor.get(message);
if (existing != null)
output.writeObject(number, existing, schema, false);
}
protected void transfer(Pipe pipe, Input input, Output output,
boolean repeated) throws IOException
{
output.writeObject(number, pipe, schema.pipeSchema, repeated);
}
protected void addValueFrom(Input input, Collection collection)
throws IOException
{
collection.add(inline.readFrom(input));
}
protected void writeValueTo(Output output, int fieldNumber, Object value,
boolean repeated) throws IOException
{
inline.writeTo(output, fieldNumber, value, repeated);
}
protected void transferValue(Pipe pipe, Input input, Output output,
int number, boolean repeated) throws IOException
{
inline.transfer(pipe, input, output, number, repeated);
}
};
}
private static Field createCollectionEnumV(int number, String name,
final java.lang.reflect.Field f, MessageFactory messageFactory,
Class genericType, IdStrategy strategy)
{
final EnumIO> eio = strategy.getEnumIO(genericType);
final Accessor accessor = ACCESSOR_FACTORY.create(f);
return new RuntimeCollectionField>(
FieldType.ENUM, number, name,
f.getAnnotation(Tag.class),
messageFactory)
{
protected void mergeFrom(Input input, T message) throws IOException
{
accessor.set(message, input.mergeObject(
accessor.>>get(message), schema));
}
protected void writeTo(Output output, T message) throws IOException
{
final Collection> existing = accessor.get(message);
if (existing != null)
output.writeObject(number, existing, schema, false);
}
protected void transfer(Pipe pipe, Input input, Output output,
boolean repeated) throws IOException
{
output.writeObject(number, pipe, schema.pipeSchema, repeated);
}
protected void addValueFrom(Input input, Collection> collection)
throws IOException
{
collection.add(eio.readFrom(input));
}
protected void writeValueTo(Output output, int fieldNumber, Enum> value,
boolean repeated) throws IOException
{
eio.writeTo(output, fieldNumber, value, repeated);
}
protected void transferValue(Pipe pipe, Input input, Output output,
int number, boolean repeated) throws IOException
{
eio.transfer(pipe, input, output, number, repeated);
}
};
}
private static Field createCollectionPojoV(int number, String name,
final java.lang.reflect.Field f, final MessageFactory messageFactory,
final Class genericType, IdStrategy strategy)
{
final HasSchema schemaV = strategy.getSchemaWrapper(genericType, true);
final Accessor accessor = ACCESSOR_FACTORY.create(f);
return new RuntimeCollectionField(
FieldType.MESSAGE, number, name,
f.getAnnotation(Tag.class),
messageFactory)
{
protected void mergeFrom(Input input, T message) throws IOException
{
accessor.set(message, input.mergeObject(
accessor.>get(message), schema));
}
protected void writeTo(Output output, T message) throws IOException
{
final Collection existing = accessor.get(message);
if (existing != null)
output.writeObject(number, existing, schema, false);
}
protected void transfer(Pipe pipe, Input input, Output output,
boolean repeated) throws IOException
{
output.writeObject(number, pipe, schema.pipeSchema, repeated);
}
protected void addValueFrom(Input input, Collection collection)
throws IOException
{
collection.add(input.mergeObject(null, schemaV.getSchema()));
}
protected void writeValueTo(Output output, int fieldNumber, Object value,
boolean repeated) throws IOException
{
if (!genericType.isAssignableFrom(value.getClass()))
{
throw new RuntimeException(f.getDeclaringClass().getName() +
"::" + f.getName() + " - " + value.getClass().getName() +
" is not assignable to " + genericType.getName());
}
output.writeObject(fieldNumber, value, schemaV.getSchema(), repeated);
}
protected void transferValue(Pipe pipe, Input input, Output output,
int number, boolean repeated) throws IOException
{
output.writeObject(number, pipe, schemaV.getPipeSchema(), repeated);
}
@Override
protected Field copy(IdStrategy strategy)
{
return createCollectionPojoV(number, name, f,
messageFactory, genericType, strategy);
}
};
}
private static Field createCollectionPolymorphicV(int number, String name,
final java.lang.reflect.Field f, final MessageFactory messageFactory,
final Class genericType, final IdStrategy strategy)
{
final Accessor accessor = ACCESSOR_FACTORY.create(f);
return new RuntimeCollectionField(
FieldType.MESSAGE, number, name,
f.getAnnotation(Tag.class),
messageFactory)
{
protected void mergeFrom(Input input, T message) throws IOException
{
accessor.set(message, input.mergeObject(
accessor.>get(message), schema));
}
protected void writeTo(Output output, T message) throws IOException
{
final Collection existing = accessor.get(message);
if (existing != null)
output.writeObject(number, existing, schema, false);
}
protected void transfer(Pipe pipe, Input input, Output output,
boolean repeated) throws IOException
{
output.writeObject(number, pipe, schema.pipeSchema, repeated);
}
protected void addValueFrom(Input input, Collection collection)
throws IOException
{
final Object value = input.mergeObject(collection,
strategy.POLYMORPHIC_POJO_ELEMENT_SCHEMA);
if(input instanceof GraphInput &&
((GraphInput)input).isCurrentMessageReference())
{
collection.add(value);
}
}
protected void writeValueTo(Output output, int fieldNumber, Object value,
boolean repeated) throws IOException
{
if (!genericType.isAssignableFrom(value.getClass()))
{
throw new RuntimeException(f.getDeclaringClass().getName() +
"::" + f.getName() + " - " + value.getClass().getName() +
" is not assignable to " + genericType.getName());
}
output.writeObject(fieldNumber, value,
strategy.POLYMORPHIC_POJO_ELEMENT_SCHEMA, repeated);
}
protected void transferValue(Pipe pipe, Input input, Output output,
int number, boolean repeated) throws IOException
{
output.writeObject(number, pipe,
strategy.POLYMORPHIC_POJO_ELEMENT_SCHEMA.pipeSchema, repeated);
}
@Override
protected Field copy(IdStrategy strategy)
{
return createCollectionPolymorphicV(number, name, f,
messageFactory, genericType, strategy);
}
};
}
private static Field createCollectionObjectV(int number, String name,
final java.lang.reflect.Field f, final MessageFactory messageFactory,
final Schema valueSchema, final Pipe.Schema valuePipeSchema,
final IdStrategy strategy)
{
final Accessor accessor = ACCESSOR_FACTORY.create(f);
return new RuntimeCollectionField(
FieldType.MESSAGE, number, name,
f.getAnnotation(Tag.class),
messageFactory)
{
protected void mergeFrom(Input input, T message) throws IOException
{
accessor.set(message, input.mergeObject(
accessor.>get(message), schema));
}
protected void writeTo(Output output, T message) throws IOException
{
final Collection existing = accessor.get(message);
if (existing != null)
output.writeObject(number, existing, schema, false);
}
protected void transfer(Pipe pipe, Input input, Output output,
boolean repeated) throws IOException
{
output.writeObject(number, pipe, schema.pipeSchema, repeated);
}
protected void addValueFrom(Input input, Collection collection)
throws IOException
{
final Object value = input.mergeObject(collection, valueSchema);
if(input instanceof GraphInput &&
((GraphInput)input).isCurrentMessageReference())
{
collection.add(value);
}
}
protected void writeValueTo(Output output, int fieldNumber, Object value,
boolean repeated) throws IOException
{
output.writeObject(fieldNumber, value, valueSchema, repeated);
}
protected void transferValue(Pipe pipe, Input input, Output output,
int number, boolean repeated) throws IOException
{
output.writeObject(number, pipe, valuePipeSchema, repeated);
}
@Override
protected Field copy(IdStrategy strategy)
{
return createCollectionObjectV(number, name, f,
messageFactory, valueSchema, valuePipeSchema, strategy);
}
};
}
private static final RuntimeFieldFactory> COLLECTION = new RuntimeFieldFactory>(RuntimeFieldFactory.ID_COLLECTION)
{
@SuppressWarnings("unchecked")
public Field create(int number, String name, final java.lang.reflect.Field f, IdStrategy strategy)
{
final Class> clazz = f.getType();
if(Modifier.isAbstract(clazz.getModifiers()))
{
if(!clazz.isInterface())
{
// abstract class
return OBJECT.create(number, name, f, strategy);
}
final Morph morph = f.getAnnotation(Morph.class);
if(morph == null)
{
if(RuntimeEnv.MORPH_COLLECTION_INTERFACES)
return OBJECT.create(number, name, f, strategy);
}
else if(morph.value())
return OBJECT.create(number, name, f, strategy);
}
if(EnumSet.class.isAssignableFrom(f.getType()))
{
final Class enumType = (Class)getGenericType(f, 0);
if(enumType == null)
{
// still handle the serialization of EnumSets even without generics
return RuntimeFieldFactory.OBJECT.create(number, name, f, strategy);
}
// TODO optimize
return createCollectionEnumV(number, name, f,
strategy.getEnumIO(enumType).getEnumSetFactory(), enumType, strategy);
}
final MessageFactory messageFactory = strategy.getCollectionFactory(f.getType());
final Class genericType = (Class)getGenericType(f, 0);
if (genericType == null || ((Map.class.isAssignableFrom(genericType) ||
Collection.class.isAssignableFrom(genericType)) &&
!strategy.isRegistered(genericType)))
{
// the value is not a simple parameterized type.
return createCollectionObjectV(number, name, f, messageFactory,
strategy.OBJECT_ELEMENT_SCHEMA,
strategy.OBJECT_ELEMENT_SCHEMA.pipeSchema,
strategy);
}
final Delegate inline = getDelegateOrInline(genericType, strategy);
if(inline != null)
return createCollectionInlineV(number, name, f, messageFactory, inline);
if(Message.class.isAssignableFrom(genericType))
return createCollectionPojoV(number, name, f, messageFactory, genericType, strategy);
if(genericType.isEnum())
return createCollectionEnumV(number, name, f, messageFactory, genericType, strategy);
final PolymorphicSchema ps =
PolymorphicSchemaFactories.getSchemaFromCollectionOrMapGenericType(
genericType, strategy);
if(ps != null)
{
return createCollectionObjectV(number, name, f, messageFactory,
ps,
ps.getPipeSchema(),
strategy);
}
if(pojo(genericType, f.getAnnotation(Morph.class), strategy))
return createCollectionPojoV(number, name, f, messageFactory, genericType, strategy);
if(genericType.isInterface())
{
return createCollectionObjectV(number, name, f, messageFactory,
strategy.OBJECT_ELEMENT_SCHEMA,
strategy.OBJECT_ELEMENT_SCHEMA.pipeSchema,
strategy);
}
return createCollectionPolymorphicV(number, name, f, messageFactory, genericType, strategy);
}
public void transfer(Pipe pipe, Input input, Output output, int number,
boolean repeated) throws IOException
{
throw new UnsupportedOperationException();
}
public Collection> readFrom(Input input) throws IOException
{
throw new UnsupportedOperationException();
}
public void writeTo(Output output, int number, Collection> value,
boolean repeated) throws IOException
{
throw new UnsupportedOperationException();
}
public FieldType getFieldType()
{
throw new UnsupportedOperationException();
}
public Class> typeClass()
{
throw new UnsupportedOperationException();
}
};
}