/**
   * input/output simple records.
   *
   * @throws Exception if test was failed
   */
  @SuppressWarnings("unchecked")
  @Test
  public void simple_record() throws Exception {
    ModelLoader loader = generate();

    Class<?> type = loader.modelType("Simple");
    assertThat(type.isAnnotationPresent(ModelInputLocation.class), is(true));
    assertThat(type.isAnnotationPresent(ModelOutputLocation.class), is(true));

    ModelWrapper object = loader.newModel("Simple");
    DataOutputBuffer output = new DataOutputBuffer();
    ModelOutput<Object> modelOut =
        (ModelOutput<Object>)
            type.getAnnotation(ModelOutputLocation.class)
                .value()
                .getDeclaredConstructor(RecordEmitter.class)
                .newInstance(new TsvEmitter(new OutputStreamWriter(output, "UTF-8")));

    object.set("sid", 1L);
    object.set("value", new Text("hello"));
    modelOut.write(object.unwrap());

    object.set("sid", 2L);
    object.set("value", new Text("world"));
    modelOut.write(object.unwrap());

    object.set("sid", 3L);
    object.set("value", null);
    modelOut.write(object.unwrap());
    modelOut.close();

    DataInputBuffer input = new DataInputBuffer();
    input.reset(output.getData(), output.getLength());
    ModelInput<Object> modelIn =
        (ModelInput<Object>)
            type.getAnnotation(ModelInputLocation.class)
                .value()
                .getDeclaredConstructor(RecordParser.class)
                .newInstance(new TsvParser(new InputStreamReader(input, "UTF-8")));
    ModelWrapper copy = loader.newModel("Simple");

    modelIn.readTo(copy.unwrap());
    assertThat(copy.get("sid"), is((Object) 1L));
    assertThat(copy.get("value"), is((Object) new Text("hello")));

    modelIn.readTo(copy.unwrap());
    assertThat(copy.get("sid"), is((Object) 2L));
    assertThat(copy.get("value"), is((Object) new Text("world")));

    modelIn.readTo(copy.unwrap());
    assertThat(copy.get("sid"), is((Object) 3L));
    assertThat(copy.getOption("value").isNull(), is(true));

    assertThat(input.read(), is(-1));
    modelIn.close();
  }
  /**
   * all primitive types.
   *
   * @throws Exception if test was failed
   */
  @SuppressWarnings("unchecked")
  @Test
  public void primitives() throws Exception {
    ModelLoader loader = generate();

    Class<?> type = loader.modelType("Primitives");
    assertThat(type.isAnnotationPresent(ModelInputLocation.class), is(true));
    assertThat(type.isAnnotationPresent(ModelOutputLocation.class), is(true));

    ModelWrapper object = loader.newModel("Primitives");

    object.set("type_boolean", true);
    object.set("type_byte", (byte) 64);
    object.set("type_short", (short) 256);
    object.set("type_int", 100);
    object.set("type_long", 200L);
    object.set("type_float", 300.f);
    object.set("type_double", 400.d);
    object.set("type_decimal", new BigDecimal("1234.567"));
    object.set("type_text", new Text("Hello, world!"));
    object.set("type_date", new Date(2011, 3, 31));
    object.set("type_datetime", new DateTime(2011, 3, 31, 23, 30, 1));

    DataOutputBuffer output = new DataOutputBuffer();
    ModelOutput<Object> modelOut =
        (ModelOutput<Object>)
            type.getAnnotation(ModelOutputLocation.class)
                .value()
                .getDeclaredConstructor(RecordEmitter.class)
                .newInstance(new TsvEmitter(new OutputStreamWriter(output, "UTF-8")));
    modelOut.write(object.unwrap());
    modelOut.write(object.unwrap());
    modelOut.write(object.unwrap());
    modelOut.close();

    DataInputBuffer input = new DataInputBuffer();
    input.reset(output.getData(), output.getLength());
    ModelInput<Object> modelIn =
        (ModelInput<Object>)
            type.getAnnotation(ModelInputLocation.class)
                .value()
                .getDeclaredConstructor(RecordParser.class)
                .newInstance(new TsvParser(new InputStreamReader(input, "UTF-8")));
    ModelWrapper copy = loader.newModel("Primitives");
    modelIn.readTo(copy.unwrap());
    assertThat(object.unwrap(), equalTo(copy.unwrap()));
    assertThat(input.read(), is(-1));
    modelIn.close();
  }
  /** generate a simple model class. */
  @Test
  public void simple() {
    ModelLoader loader = generate();
    ModelWrapper object = loader.newModel("Simple");
    object.set("value", 100);
    assertThat(object.get("value"), eq(100));
    assertThat(object.getOption("value"), eq(new IntOption(100)));
    object.setOption("value", new IntOption(200));
    assertThat(object.get("value"), eq(200));

    ModelWrapper copy = loader.newModel("Simple");
    copy.copyFrom(object);

    object.reset();
    assertThat(object.getOption("value").isNull(), eq(true));
    assertThat(copy.get("value"), eq(200));
  }
  /** change own namespace. */
  @Test
  public void namespace() {
    ModelLoader loader = generate();
    loader.setNamespace("other");
    ModelWrapper object = loader.newModel("Simple");

    object.set("value", 100);
    assertThat(object.get("value"), eq(100));
  }
  /** all primitive types. */
  @Test
  public void primitives() {
    ModelLoader loader = generate();
    ModelWrapper object = loader.newModel("Primitives");

    object.set("type_boolean", true);
    assertThat(object.is("type_boolean"), eq(true));

    object.set("type_byte", (byte) 64);
    assertThat(object.get("type_byte"), eq((byte) 64));

    object.set("type_short", (short) 256);
    assertThat(object.get("type_short"), eq((short) 256));

    object.set("type_int", 100);
    assertThat(object.get("type_int"), eq(100));

    object.set("type_long", 200L);
    assertThat(object.get("type_long"), eq(200L));

    object.set("type_float", 300.f);
    assertThat(object.get("type_float"), eq(300.f));

    object.set("type_double", 400.d);
    assertThat(object.get("type_double"), eq(400.d));

    object.set("type_decimal", new BigDecimal("1234.567"));
    assertThat(object.get("type_decimal"), eq(new BigDecimal("1234.567")));

    object.set("type_text", new Text("Hello, world!"));
    assertThat(object.get("type_text"), eq(new Text("Hello, world!")));

    object.set("type_date", new Date(2011, 3, 31));
    assertThat(object.get("type_date"), eq(new Date(2011, 3, 31)));

    object.set("type_datetime", new DateTime(2011, 3, 31, 23, 30, 1));
    assertThat(object.get("type_datetime"), eq(new DateTime(2011, 3, 31, 23, 30, 1)));
  }