@SuppressWarnings("unchecked")
    static Object readObjectFrom(Input input, Schema<?> schema, Object owner,
            IdStrategy strategy, final int number) throws IOException
    {
        final boolean graph = input instanceof GraphInput;
        Object ret = null;
        switch (number)
        {
            case ID_EMPTY_SET:
                if (0 != input.readUInt32())
                    throw new ProtostuffException("Corrupt input.");

                if (graph)
                {
                    // update the actual reference.
                    ((GraphInput) input).updateLast(Collections.EMPTY_SET, owner);
                }

                ret = Collections.EMPTY_SET;
                break;

            case ID_EMPTY_LIST:
                if (0 != input.readUInt32())
                    throw new ProtostuffException("Corrupt input.");

                if (graph)
                {
                    // update the actual reference.
                    ((GraphInput) input).updateLast(Collections.EMPTY_LIST, owner);
                }

                ret = Collections.EMPTY_LIST;
                break;

            case ID_SINGLETON_SET:
            {
                if (0 != input.readUInt32())
                    throw new ProtostuffException("Corrupt input.");

                final Object collection = iSingletonSet.newInstance();
                if (graph)
                {
                    // update the actual reference.
                    ((GraphInput) input).updateLast(collection, owner);
                }

                final int next = input.readFieldNumber(schema);
                if (next == 0)
                {
                    // null element
                    return collection;
                }

                if (next != 1)
                    throw new ProtostuffException("Corrupt input");

                final Wrapper wrapper = new Wrapper();
                Object element = input.mergeObject(wrapper, strategy.OBJECT_SCHEMA);
                if (!graph || !((GraphInput) input).isCurrentMessageReference())
                    element = wrapper.value;

                try
                {
                    fSingletonSet_element.set(collection, element);
                }
                catch (IllegalAccessException e)
                {
                    throw new RuntimeException(e);
                }
                catch (IllegalArgumentException e)
                {
                    throw new RuntimeException(e);
                }

                ret = collection;
                break;
            }

            case ID_SINGLETON_LIST:
            {
                if (0 != input.readUInt32())
                    throw new ProtostuffException("Corrupt input.");

                final Object collection = iSingletonList.newInstance();
                if (graph)
                {
                    // update the actual reference.
                    ((GraphInput) input).updateLast(collection, owner);
                }

                final int next = input.readFieldNumber(schema);
                if (next == 0)
                {
                    // null element
                    return collection;
                }

                if (next != 1)
                    throw new ProtostuffException("Corrupt input.");

                final Wrapper wrapper = new Wrapper();
                Object element = input.mergeObject(wrapper, strategy.OBJECT_SCHEMA);
                if (!graph || !((GraphInput) input).isCurrentMessageReference())
                    element = wrapper.value;

                try
                {
                    fSingletonList_element.set(collection, element);
                }
                catch (IllegalAccessException e)
                {
                    throw new RuntimeException(e);
                }
                catch (IllegalArgumentException e)
                {
                    throw new RuntimeException(e);
                }

                ret = collection;
                break;
            }

            case ID_SET_FROM_MAP:
            {
                final Object collection = iSetFromMap.newInstance();
                if (graph)
                {
                    // update the actual reference.
                    ((GraphInput) input).updateLast(collection, owner);
                }

                final Wrapper wrapper = new Wrapper();
                Object m = input.mergeObject(wrapper,
                        strategy.POLYMORPHIC_MAP_SCHEMA);
                if (!graph || !((GraphInput) input).isCurrentMessageReference())
                    m = wrapper.value;

                try
                {
                    fSetFromMap_m.set(collection, m);
                    fSetFromMap_s.set(collection, ((Map<?, ?>) m).keySet());
                }
                catch (IllegalAccessException e)
                {
                    throw new RuntimeException(e);
                }
                catch (IllegalArgumentException e)
                {
                    throw new RuntimeException(e);
                }

                ret = collection;
                break;
            }

            case ID_COPIES_LIST:
            {
                if (0 != input.readUInt32())
                    throw new ProtostuffException("Corrupt input.");

                final Object collection = iCopiesList.newInstance();
                if (graph)
                {
                    // update the actual reference.
                    ((GraphInput) input).updateLast(collection, owner);
                }

                if (1 != input.readFieldNumber(schema))
                    throw new ProtostuffException("Corrupt input.");

                final int n = input.readUInt32(), next = input
                        .readFieldNumber(schema);

                if (next == 0)
                {
                    // null element
                    try
                    {
                        fCopiesList_n.setInt(collection, n);
                    }
                    catch (IllegalAccessException e)
                    {
                        throw new RuntimeException(e);
                    }
                    catch (IllegalArgumentException e)
                    {
                        throw new RuntimeException(e);
                    }

                    return collection;
                }

                if (next != 2)
                    throw new ProtostuffException("Corrupt input.");

                final Wrapper wrapper = new Wrapper();
                Object element = input.mergeObject(wrapper, strategy.OBJECT_SCHEMA);
                if (!graph || !((GraphInput) input).isCurrentMessageReference())
                    element = wrapper.value;

                try
                {
                    fCopiesList_n.setInt(collection, n);
                    fCopiesList_element.set(collection, element);
                }
                catch (IllegalAccessException e)
                {
                    throw new RuntimeException(e);
                }
                catch (IllegalArgumentException e)
                {
                    throw new RuntimeException(e);
                }

                ret = collection;
                break;
            }

            case ID_UNMODIFIABLE_COLLECTION:
                ret = readUnmodifiableCollectionFrom(input, schema, owner,
                        strategy, graph, iUnmodifiableCollection.newInstance(),
                        false, false);
                break;
            case ID_UNMODIFIABLE_SET:
                ret = readUnmodifiableCollectionFrom(input, schema, owner,
                        strategy, graph, iUnmodifiableSet.newInstance(), false,
                        false);
                break;
            case ID_UNMODIFIABLE_SORTED_SET:
                ret = readUnmodifiableCollectionFrom(input, schema, owner,
                        strategy, graph, iUnmodifiableSortedSet.newInstance(),
                        true, false);
                break;
            case ID_UNMODIFIABLE_LIST:
                ret = readUnmodifiableCollectionFrom(input, schema, owner,
                        strategy, graph, iUnmodifiableList.newInstance(), false,
                        true);
                break;
            case ID_UNMODIFIABLE_RANDOM_ACCESS_LIST:
                ret = readUnmodifiableCollectionFrom(input, schema, owner,
                        strategy, graph,
                        iUnmodifiableRandomAccessList.newInstance(), false, true);
                break;

            case ID_SYNCHRONIZED_COLLECTION:
                ret = readSynchronizedCollectionFrom(input, schema, owner,
                        strategy, graph, iSynchronizedCollection.newInstance(),
                        false, false);
                break;
            case ID_SYNCHRONIZED_SET:
                ret = readSynchronizedCollectionFrom(input, schema, owner,
                        strategy, graph, iSynchronizedSet.newInstance(), false,
                        false);
                break;
            case ID_SYNCHRONIZED_SORTED_SET:
                ret = readSynchronizedCollectionFrom(input, schema, owner,
                        strategy, graph, iSynchronizedSortedSet.newInstance(),
                        true, false);
                break;
            case ID_SYNCHRONIZED_LIST:
                ret = readSynchronizedCollectionFrom(input, schema, owner,
                        strategy, graph, iSynchronizedList.newInstance(), false,
                        true);
                break;
            case ID_SYNCHRONIZED_RANDOM_ACCESS_LIST:
                ret = readSynchronizedCollectionFrom(input, schema, owner,
                        strategy, graph,
                        iSynchronizedRandomAccessList.newInstance(), false, true);
                break;

            case ID_CHECKED_COLLECTION:
                ret = readCheckedCollectionFrom(input, schema, owner, strategy,
                        graph, iCheckedCollection.newInstance(), false, false);
                break;
            case ID_CHECKED_SET:
                ret = readCheckedCollectionFrom(input, schema, owner, strategy,
                        graph, iCheckedSet.newInstance(), false, false);
                break;
            case ID_CHECKED_SORTED_SET:
                ret = readCheckedCollectionFrom(input, schema, owner, strategy,
                        graph, iCheckedSortedSet.newInstance(), true, false);
                break;
            case ID_CHECKED_LIST:
                ret = readCheckedCollectionFrom(input, schema, owner, strategy,
                        graph, iCheckedList.newInstance(), false, true);
                break;
            case ID_CHECKED_RANDOM_ACCESS_LIST:
                ret = readCheckedCollectionFrom(input, schema, owner, strategy,
                        graph, iCheckedRandomAccessList.newInstance(), false, true);
                break;

            case ID_ENUM_SET:
            {
                final Collection<?> es = strategy.resolveEnumFrom(input)
                        .newEnumSet();

                if (graph)
                {
                    // update the actual reference.
                    ((GraphInput) input).updateLast(es, owner);
                }

                // TODO enum schema
                strategy.COLLECTION_SCHEMA
                        .mergeFrom(input, (Collection<Object>) es);
                return es;
            }

            case ID_COLLECTION:
            {
                final Collection<Object> collection = strategy
                        .resolveCollectionFrom(input).newMessage();

                if (graph)
                {
                    // update the actual reference.
                    ((GraphInput) input).updateLast(collection, owner);
                }

                strategy.COLLECTION_SCHEMA.mergeFrom(input, collection);

                return collection;
            }

            default:
                throw new ProtostuffException("Corrupt input.");
        }

        if (0 != input.readFieldNumber(schema))
            throw new ProtostuffException("Corrupt input.");

        return ret;
    }
Used when the type is an interface (Collection/List/Set/SortedSet).

@author David Yu
@created Apr 24, 2012
protostuff-runtime/src/main/java/io/protostuff/runtime/PolymorphicCollectionSchema.java