PARQUET-79: add a streaming Thrift API, to enable processing the metadata as we read it and skipping unnecessary fields.

This pull request provides an API to read thrift in a streaming fashion.
This enables ignoring fields that are not needed without loading them into memory.
It also aloow treating the data as it comes instead of when it's fully loaded in memory.
I propose another implementation here:
With current implementation:
There is a information duplication for the DelegateContext, which stores both the TypedConsumer and TypedConsumerProvider where the TypedConsumerProvider simply returns the TypedConsumer.
The reason there is this duplication of information I guess it due to the fact in EventBasedThriftEventReader, when readElement getsCalled, it ask the provider for the right type of consumer. Also the TypedConsumerProvider defines every getter method for each type of TypedConsumer. We can see the TypedConsumerProvider is just an extra layer for type safety(otherwise one would need to cast the TypedConsumer to proper type)

That layer is not necessary if we replace this layer with polymorphism. Using polymorphism and generics also push the implementation to the client, make the code easier to extend for new types. In detail, we could:
1. define a TypedConsumer<T> interface that consumes a TProtocol, and read a value of type T.  It's responsibility is like "give me a protocol, and I will read a value for you"

2. The subclasses of TypedConsumer now has more responsibility rather than just delegation. It's responsible for decoding the protocol to proper type. This change makes more sense than the eventThriftProtocol helping it to decode the protocol. For example the BoolConsumer would be:
abstract public static class BoolConsumer extends TypedProtocolConsumer<Bool> {
 abstract public void consume(Bool value)
 @ override
public void consumeProtocol(TType type, TProtocol protocol) {
   if (type!=TType.BOOL)
     throws new RuntimeException("Consumer type and field type mismatch!!!!")
   }
  consume(protocol.readBool())
}

So here the different Consumers has the polymorphism to read protocol in their own way. With that, we can get rid of the huge switch case block in the readElement method.
Also the layer of provider class can also be removed. so the getDelegate method simply returns the TypedConsumer for a given fiedID rather than return the provider

This implementation uses generics and polymorphism so all the "moving parts" are on the top level where the client defines the consumer.