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.
package io.protostuff.runtime;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
import java.util.Map.Entry;
import io.protostuff.CollectionSchema;
import io.protostuff.GraphInput;
import io.protostuff.Input;
import io.protostuff.MapSchema;
import io.protostuff.MapSchema.MapWrapper;
import io.protostuff.Message;
import io.protostuff.Output;
import io.protostuff.Pipe;
import io.protostuff.ProtostuffException;
import io.protostuff.Schema;
/**
* This base class handles all the IO for reading and writing polymorphic fields. When a field's type is
* polymorphic/dynamic (e.g interface/abstract/object), the type (id) needs to be written (ahead) before its
* value/content to be able to deserialize it correctly.
*
* The underlying impl will determine how the type (id) should be written.
*
* An {@link IdStrategy} is standalone if the {@link #primaryGroup} is not set.
*
* @author Leo Romanoff
* @author David Yu
*/
public abstract class IdStrategy
{
public final IdStrategy primaryGroup;
public final int groupId;
protected IdStrategy(IdStrategy primaryGroup, int groupId)
{
if (primaryGroup != null)
{
if (groupId <= 0 || 0 != (groupId & (groupId - 1)))
{
throw new RuntimeException(
"The groupId must be a power of two (1,2,4,8,etc).");
}
}
else if (groupId != 0)
{
throw new RuntimeException("An IdStrategy without a primaryGroup "
+ "(standalone) must have a groupId of zero.");
}
this.primaryGroup = primaryGroup;
this.groupId = groupId;
}
/**
* Generates a schema from the given class. If this strategy is part of a group, the existing fields of that group's
* schema will be re-used.
*/
protected Schema newSchema(Class typeClass)
{
// check if this is part of a group
if (primaryGroup != null)
{
// only pojos created by runtime schema support groups
final Schema s = primaryGroup.getSchemaWrapper(typeClass, true)
.getSchema();
if (s instanceof RuntimeSchema)
{
final RuntimeSchema rs = (RuntimeSchema) s;
final ArrayList> fields = new ArrayList<>(rs.getFieldCount());
for (Field f : rs.getFields())
{
final int groupFilter = f.groupFilter;
if (groupFilter != 0)
{
final int set; // set for exclusion
if (groupFilter > 0)
{
// inclusion
set = ~groupFilter & 0x7FFFFFFF;
}
else
{
// exclusion
set = -groupFilter;
}
if (0 != (groupId & set))
{
// this field is excluded on the current group id
continue;
}
}
fields.add(f);
}
final int size = fields.size();
if (size == rs.getFieldCount())
{
// nothing is excluded
return rs;
}
if (size == 0)
{
throw new RuntimeException("All fields were excluded for "
+ rs.messageFullName() + " on group " + groupId);
}
return new RuntimeSchema<>(typeClass, fields, rs.instantiator);
}
return s;
}
return RuntimeSchema.createFrom(typeClass, this);
}
/**
* Thrown when a type is not known by the IdStrategy. The DefaultIdStrategy will never throw this exception though.
*/
public static class UnknownTypeException extends RuntimeException
{
private static final long serialVersionUID = 1L;
public UnknownTypeException(String msg)
{
super(msg);
}
}
/**
* Responsible for instantiating custom {@link IdStrategy} impls.
*/
public interface Factory
{
/**
* Creates a new {@link IdStrategy} instance (impl).
*/
public IdStrategy create();
/**
* Called after the method {@link #create()} has been called. This is used to prevent classloader issues.
* RuntimeEnv's {@link RuntimeEnv#ID_STRATEGY} need to be set first.
*/
public void postCreate();
}
/**
* Returns true if there is a {@link Delegate} explicitly registered for the {@code typeClass}.
*/
public abstract boolean isDelegateRegistered(Class> typeClass);
/**
* Returns the {@link Delegate delegate}.
*/
public abstract HasDelegate getDelegateWrapper(
Class super T> typeClass);
/**
* Returns the {@link Delegate delegate}.
*/
public abstract Delegate getDelegate(Class super T> typeClass);
/**
* Returns true if the {@code typeClass} is explicitly registered.
*/
public abstract boolean isRegistered(Class> typeClass);
/**
* Returns the {@link HasSchema schema wrapper}. The caller is responsible that the typeClass is a pojo (e.g not an
* enum/array/etc).
*/
public abstract HasSchema getSchemaWrapper(Class typeClass,
boolean create);
/**
* Returns the {@link EnumIO}. The callers (internal field factories) are responsible that the class provided is an
* enum class.
*/
protected abstract EnumIO extends Enum>> getEnumIO(Class> enumClass);
/**
* Returns the {@link CollectionSchema.MessageFactory}. The callers (internal field factories) are responsible that
* the class provided implements {@link Collection}.
*/
protected abstract CollectionSchema.MessageFactory getCollectionFactory(
Class> clazz);
/**
* Returns the {@link MapSchema.MessageFactory}. The callers (internal field factories}) are responsible that the
* class provided implements {@link Map}.
*/
protected abstract MapSchema.MessageFactory getMapFactory(Class> clazz);
// collection
protected abstract void writeCollectionIdTo(Output output, int fieldNumber,
Class> clazz) throws IOException;
protected abstract void transferCollectionId(Input input, Output output,
int fieldNumber) throws IOException;
protected abstract CollectionSchema.MessageFactory resolveCollectionFrom(
Input input) throws IOException;
// map
protected abstract void writeMapIdTo(Output output, int fieldNumber,
Class> clazz) throws IOException;
protected abstract void transferMapId(Input input, Output output,
int fieldNumber) throws IOException;
protected abstract MapSchema.MessageFactory resolveMapFrom(Input input)
throws IOException;
// enum
protected abstract void writeEnumIdTo(Output output, int fieldNumber,
Class> clazz) throws IOException;
protected abstract void transferEnumId(Input input, Output output,
int fieldNumber) throws IOException;
protected abstract EnumIO> resolveEnumFrom(Input input)
throws IOException;
// pojo
protected abstract HasSchema writePojoIdTo(Output output,
int fieldNumber, Class clazz) throws IOException;
protected abstract HasSchema transferPojoId(Input input,
Output output, int fieldNumber) throws IOException;
protected abstract HasSchema resolvePojoFrom(Input input,
int fieldNumber) throws IOException;
protected abstract Schema writeMessageIdTo(Output output,
int fieldNumber, Message message) throws IOException;
// delegate
/**
* If this method returns null, the clazz was not registered as a delegate.
*/
protected abstract HasDelegate tryWriteDelegateIdTo(Output output,
int fieldNumber, Class clazz) throws IOException;
protected abstract HasDelegate transferDelegateId(Input input,
Output output, int fieldNumber) throws IOException;
protected abstract HasDelegate resolveDelegateFrom(Input input)
throws IOException;
// array
protected abstract void writeArrayIdTo(Output output, Class> componentType)
throws IOException;
protected abstract void transferArrayId(Input input, Output output,
int fieldNumber, boolean mapped) throws IOException;
protected abstract Class> resolveArrayComponentTypeFrom(Input input,
boolean mapped) throws IOException;
// class
protected abstract void writeClassIdTo(Output output,
Class> componentType, boolean array) throws IOException;
protected abstract void transferClassId(Input input, Output output,
int fieldNumber, boolean mapped, boolean array) throws IOException;
protected abstract Class> resolveClassFrom(Input input, boolean mapped,
boolean array) throws IOException;
// polymorphic requirements
final DerivativeSchema POLYMORPHIC_POJO_ELEMENT_SCHEMA = new DerivativeSchema(
this)
{
@Override
@SuppressWarnings("unchecked")
protected void doMergeFrom(Input input, Schema