Json schemas

This adds schema validation for component inputs with the following changes:
* a `declareSchema` method is added to `InputCollector`
* a `declareSchema` method is added to the base `Component` interface (through which it is added to the component's `InputCollector`)
* the `declareSchema` methods accept a `JsonSchema` instance
* each `JsonSchema` can create a `JsonValidator` instance, which can validate any `JsonElement` (`JsonObject` or `JsonArray`)
* the `ObjectSchema` and `ArraySchema` classes are the basic object and array schema implementations
* each field in `ObjectSchema` can define a data type and/or a schema (for cases where the required value is a `JsonObject` or `JsonArray`)
* the `ArraySchema` can define the data type or schema of its elements
* also adds `Field` and `Fields` classes which represent a field and a collection of fields respecively

Example:

`MathVerticle.java`

```java
vertigo.createBasicWorker().start(new Handler<AsyncResult<BasicWorker>>() {
  public void handle(AsyncResult<BasicWorker> result) {
    if (result.failed()) {
      return;
    }

    final BasicWorker worker = result.result();

    // Create a schema that requires a message structure like:
    // {
    //   "operator": "+",
    //   "values": [1, 2, 3]
    "" }
    ObjectSchema schema = new ObjectSchema();
    schema.addField("operator", String.class);
    schema.addField("values", new ArraySchema().setType(Integer.class));

    // Add the schema to the worker.
    worker.declareSchema(schema);

    // Register a message handler that calculates a value.
    worker.messageHandler(new Handler<JsonMessage>() {
      public void handle(JsonMessage message) {
        // We can be confident that the "operator" field exists and is a String.
        String operator = message.body().getString("operator");
        switch (operator) {
          case "+":
            int sum = 0;
            // We can be confident that each of these values are integers.
            for (Object num : message.body().getArray("values")) {
              sum += Integer.valueOf(num);
            }
            worker.emit(new JsonObject().putString("sum", sum), message);
            break;
          case "*":
            int product = 0;
            // Again, we're still confident these are integers.
            for (Object num : message.body().getArray("values")) {
              product *= Integer.valueOf(num);
            }
            worker.emit(new JsonObject().putString("product", product), message);
            break;
          default:
            worker.fail(message);
            break;
        }
      }
    });
  }
});
```