package com.continuuity.explore.client;

import com.continuuity.common.utils.ImmutablePair;
import com.google.common.base.Objects;
import com.google.common.reflect.TypeToken;
import org.junit.Assert;
import org.junit.Test;

import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * Test DatasetExploreFacade.
 */
public class DatasetExploreFacadeTest {
  enum Enum { FOO, BAR }

  @SuppressWarnings("unused")
  static class Record {
    int a;
    long b;
    boolean c;
    float d;
    double e;
    String f;
    byte[] g;
    Enum[] h;
    Collection<Boolean> i;
    Map<Integer, String> j;
  }

  @SuppressWarnings("unused")
  static class Int {
    Integer value;
  }

  @SuppressWarnings("unused")
  static class Longg {
    long value;
  }

  public static class KeyValue {
    private final String key;
    private final Value value;

    public KeyValue(String key, Value value) {
      this.key = key;
      this.value = value;
    }

    @SuppressWarnings("UnusedDeclaration")
    public String getKey() {
      return key;
    }

    @SuppressWarnings("UnusedDeclaration")
    public Value getValue() {
      return value;
    }

    @Override
    public boolean equals(Object o) {
      if (this == o) {
        return true;
      }
      if (o == null || getClass() != o.getClass()) {
        return false;
      }

      KeyValue that = (KeyValue) o;

      return Objects.equal(this.key, that.key) &&
        Objects.equal(this.value, that.value);
    }

    @Override
    public int hashCode() {
      return Objects.hashCode(key, value);
    }

    public static class Value {
      private final String name;
      private final List<Integer> ints;

      public Value(String name, List<Integer> ints) {
        this.name = name;
        this.ints = ints;
      }

      @SuppressWarnings("UnusedDeclaration")
      public String getName() {
        return name;
      }

      @SuppressWarnings("UnusedDeclaration")
      public List<Integer> getInts() {
        return ints;
      }

      @Override
      public boolean equals(Object o) {
        if (this == o) {
          return true;
        }
        if (o == null || getClass() != o.getClass()) {
          return false;
        }

        Value that = (Value) o;

        return Objects.equal(this.name, that.name) &&
          Objects.equal(this.ints, that.ints);
      }

      @Override
      public int hashCode() {
        return Objects.hashCode(name, ints);
      }
    }
  }

  @Test
  public void testHiveSchemaFor() throws Exception {

    Assert.assertEquals("(value INT)", DatasetExploreFacade.hiveSchemaFor(Int.class));
    Assert.assertEquals("(value BIGINT)", DatasetExploreFacade.hiveSchemaFor(Longg.class));
    Assert.assertEquals("(first INT, second STRING)",
                        DatasetExploreFacade.hiveSchemaFor(new TypeToken<ImmutablePair<Integer, String>>() {
                        }.getType()));
    Assert.assertEquals("(a INT, b BIGINT, c BOOLEAN, d FLOAT, e DOUBLE, f STRING, g BINARY, " +
                          "h ARRAY<STRING>, i ARRAY<BOOLEAN>, j MAP<INT,STRING>)",
                        DatasetExploreFacade.hiveSchemaFor(Record.class));

    Assert.assertEquals("(key STRING, value STRUCT<ints:ARRAY<INT>, name:STRING>)",
                        DatasetExploreFacade.hiveSchemaFor(KeyValue.class));
  }

}

@@ -85,16 +85,77 @@
 lePair;%0A
+import com.continuuity.internal.io.UnsupportedTypeException;%0A
 import c
@@ -274,24 +274,55 @@
 unit.Test;%0A%0A
+import java.lang.reflect.Type;%0A
 import java.
@@ -3437,10 +3437,636 @@
 );%0A  %7D%0A%0A
+%0A  private void verifyUnsupportedSchema(Type type) %7B%0A    String schema;%0A    try %7B%0A      schema = DatasetExploreFacade.hiveSchemaFor(type);%0A    %7D catch (UnsupportedTypeException e) %7B%0A      // expected%0A      return;%0A    %7D%0A    Assert.fail(%22Type %22 + type + %22 should not be supported and cause exception but returned %22 + schema);%0A  %7D%0A%0A  @Test%0A  public void testUnsupportedTypes() %7B%0A    verifyUnsupportedSchema(Integer.class);%0A    verifyUnsupportedSchema(String.class);%0A    verifyUnsupportedSchema(new TypeToken%3CList%3CInteger%3E%3E() %7B %7D.getType());%0A    verifyUnsupportedSchema(new TypeToken%3CMap%3CString, Integer%3E%3E() %7B %7D.getType());%0A  %7D%0A%0A
 %7D%0A

add unit test to verify that non-record types are rejected