All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.dyuproject.protostuff.runtime.DerivativeSchema 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 static com.dyuproject.protostuff.runtime.RuntimeFieldFactory.ID_POJO;
import static com.dyuproject.protostuff.runtime.RuntimeFieldFactory.STR_POJO;

import java.io.IOException;

import com.dyuproject.protostuff.Input;
import com.dyuproject.protostuff.Output;
import com.dyuproject.protostuff.Pipe;
import com.dyuproject.protostuff.ProtostuffException;
import com.dyuproject.protostuff.Schema;
import com.dyuproject.protostuff.StatefulOutput;

/**
 * This schema delegates to another schema derived from the input.
 *
 * @author David Yu
 * @created Jan 21, 2011
 */
public abstract class DerivativeSchema implements Schema
{
    
    public final IdStrategy strategy;
    
    public DerivativeSchema(IdStrategy strategy)
    {
        this.strategy = strategy;
    }

    public String getFieldName(int number)
    {
        return number == ID_POJO ? STR_POJO : null;
    }

    public int getFieldNumber(String name)
    {
        return name.length() == 1 && name.charAt(0) == '_' ? ID_POJO : 0;
    }

    public boolean isInitialized(Object owner)
    {
        return true;
    }

    public String messageFullName()
    {
        return Object.class.getName();
    }

    public String messageName()
    {
        return Object.class.getSimpleName();
    }

    public Object newMessage()
    {
        // cannot instantiate because the type is dynamic.
        throw new UnsupportedOperationException();
    }

    public Class typeClass()
    {
        return Object.class;
    }
    
    /**
     * Delegates to the schema derived from the input.
     * The {@code owner} owns the message (polymorphic) that is tied to this schema.
     */
    public void mergeFrom(Input input, final Object owner) throws IOException
    {
        final int first = input.readFieldNumber(this);
        if(first != ID_POJO)
            throw new ProtostuffException("order not preserved.");
        
        doMergeFrom(input, 
                strategy.resolvePojoFrom(input, ID_POJO).getSchema(), 
                owner);
    }
    
    /**
     * Delegates to the schema derived from the {@code value}.
     */
    @SuppressWarnings("unchecked")
    public void writeTo(final Output output, final Object value) throws IOException
    {
        final Schema schema = strategy.writePojoIdTo(
                output, ID_POJO, (Class)value.getClass()).getSchema();
        
        if(output instanceof StatefulOutput)
        {
            // update using the derived schema.
            ((StatefulOutput)output).updateLast(schema, this);
        }
        
        // write the rest of the fields of the exact type
        schema.writeTo(output, value);
    }
    
    /**
     * This pipe schema delegates to another schema derived from the input.
     */
    public final Pipe.Schema pipeSchema = new Pipe.Schema(
            DerivativeSchema.this)
    {
        public void transfer(Pipe pipe, Input input, Output output) throws IOException
        {
            final int first = input.readFieldNumber(DerivativeSchema.this);
            if(first != ID_POJO)
                throw new ProtostuffException("order not preserved.");
            
            final Pipe.Schema pipeSchema = strategy.transferPojoId(
                    input, output, ID_POJO).getPipeSchema();
            
            if(output instanceof StatefulOutput)
            {
                // update using the derived schema.
                ((StatefulOutput)output).updateLast(pipeSchema, this);
            }            
            
            Pipe.transferDirect(pipeSchema, pipe, input, output);
        }
        
    };
    
    protected abstract void doMergeFrom(Input input, Schema derivedSchema, 
            Object owner) throws IOException;

}