@SuppressWarnings("unchecked")
    static void writeObjectTo(Output output, Object value,
            Schema<?> currentSchema, IdStrategy strategy) throws IOException
    {
        final Class<Object> clazz = (Class<Object>) value.getClass();

        final HasDelegate<Object> hd = strategy.tryWriteDelegateIdTo(output,
                ID_DELEGATE, clazz);

        if (hd != null)
        {
            hd.delegate.writeTo(output, 1, value, false);
            return;
        }

        final RuntimeFieldFactory<Object> inline = RuntimeFieldFactory.getInline(clazz);
        if (inline != null)
        {
            // scalar value
            inline.writeTo(output, inline.id, value, false);
            return;
        }
        
        if (clazz.isArray())
        {
            writeArrayTo(output, value, currentSchema, strategy, clazz);
            return;
        }
        
        Class<?> c = clazz;
        if (clazz.isEnum() || (null != (c = clazz.getSuperclass()) && c.isEnum()))
        {
            EnumIO<?> eio = strategy.getEnumIO(c);
            strategy.writeEnumIdTo(output, ID_ENUM, c);
            eio.writeTo(output, ID_ENUM_VALUE, false, (Enum<?>) value);
            return;
        }

        if (Object.class == clazz)
        {
            output.writeUInt32(ID_OBJECT, 0, false);
            return;
        }

        if (Class.class == value.getClass())
        {
            // its a class
            c = (Class<?>)value;
            if (c.isArray())
            {
                int dimensions = 1;
                c = c.getComponentType();
                while (c.isArray())
                {
                    dimensions++;
                    c = c.getComponentType();
                }

                strategy.writeClassIdTo(output, c, true);
                // write the dimensions of the array
                output.writeUInt32(ID_ARRAY_DIMENSION, dimensions, false);
            }
            else
            {
                strategy.writeClassIdTo(output, c, false);
            }
            return;
        }
        
        if (Message.class.isAssignableFrom(clazz))
        {
            final Schema<Object> schema = strategy.writeMessageIdTo(
                    output, ID_POJO, (Message<Object>) value);

            if (output instanceof StatefulOutput)
            {
                // update using the derived schema.
                ((StatefulOutput) output).updateLast(schema, currentSchema);
            }

            schema.writeTo(output, value);
            return;
        }
        
        HasSchema<Object> hs = strategy.tryWritePojoIdTo(output, ID_POJO, clazz, false);
        if (hs != null)
        {
            final Schema<Object> schema = hs.getSchema();
            
            if (output instanceof StatefulOutput)
            {
                // update using the derived schema.
                ((StatefulOutput) output).updateLast(schema, currentSchema);
            }

            schema.writeTo(output, value);
            return;
        }
        
        if (Throwable.class.isAssignableFrom(clazz))
        {
            // throwable
            PolymorphicThrowableSchema.writeObjectTo(output, value, currentSchema,
                    strategy);
            return;
        }
        
        if (Map.class.isAssignableFrom(clazz))
        {
            if (Collections.class == clazz.getDeclaringClass())
            {
                output.writeUInt32(ID_POLYMORPHIC_MAP, 0, false);

                if (output instanceof StatefulOutput)
                {
                    // update using the derived schema.
                    ((StatefulOutput) output).updateLast(
                            strategy.POLYMORPHIC_MAP_SCHEMA, currentSchema);
                }

                PolymorphicMapSchema.writeNonPublicMapTo(output, value,
                        strategy.POLYMORPHIC_MAP_SCHEMA, strategy);
                return;
            }

            if (EnumMap.class.isAssignableFrom(clazz))
            {
                strategy.writeEnumIdTo(output, ID_ENUM_MAP,
                        EnumIO.getKeyTypeFromEnumMap(value));
            }
            else
            {
                strategy.writeMapIdTo(output, ID_MAP, clazz);
            }

            if (output instanceof StatefulOutput)
            {
                // update using the derived schema.
                ((StatefulOutput) output).updateLast(strategy.MAP_SCHEMA, currentSchema);
            }

            strategy.MAP_SCHEMA.writeTo(output, (Map<Object, Object>) value);
            return;
        }

        if (Collection.class.isAssignableFrom(clazz))
        {
            if (Collections.class == clazz.getDeclaringClass())
            {
                output.writeUInt32(ID_POLYMORPHIC_COLLECTION, 0, false);

                if (output instanceof StatefulOutput)
                {
                    // update using the derived schema.
                    ((StatefulOutput) output).updateLast(
                            strategy.POLYMORPHIC_COLLECTION_SCHEMA, currentSchema);
                }

                PolymorphicCollectionSchema.writeNonPublicCollectionTo(output, value,
                        strategy.POLYMORPHIC_COLLECTION_SCHEMA, strategy);
                return;
            }

            if (EnumSet.class.isAssignableFrom(clazz))
            {
                strategy.writeEnumIdTo(output, ID_ENUM_SET,
                        EnumIO.getElementTypeFromEnumSet(value));
            }
            else
            {
                strategy.writeCollectionIdTo(output, ID_COLLECTION, clazz);
            }

            if (output instanceof StatefulOutput)
            {
                // update using the derived schema.
                ((StatefulOutput) output).updateLast(strategy.COLLECTION_SCHEMA, currentSchema);
            }

            strategy.COLLECTION_SCHEMA.writeTo(output, (Collection<Object>) value);
            return;
        }
        
        // pojo
        final Schema<Object> schema = strategy.writePojoIdTo(
                output, ID_POJO, clazz).getSchema();

        if (output instanceof StatefulOutput)
        {
            // update using the derived schema.
            ((StatefulOutput) output).updateLast(schema, currentSchema);
        }

        schema.writeTo(output, value);
    }
A schema for dynamic types (fields where the type is {@link Object}).

@author David Yu
@created Feb 1, 2011
protostuff-runtime/src/main/java/io/protostuff/runtime/ObjectSchema.java