package com.github.rschmitt.dynamicobject;

import org.junit.Test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import static com.github.rschmitt.dynamicobject.DynamicObject.deserialize;
import static com.github.rschmitt.dynamicobject.DynamicObject.newInstance;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

public class CollectionsTest {
    @Test
    public void listOfStrings() {
        ListSchema listSchema = deserialize("{:strings [\"one\" \"two\" \"three\"]}", ListSchema.class);
        List<String> stringList = listSchema.strings();
        assertEquals("one", stringList.get(0));
        assertEquals("two", stringList.get(1));
        assertEquals("three", stringList.get(2));
    }

    // This is just here to prove a point about Java<->Clojure interop.
    @Test
    public void listStream() {
        ListSchema listSchema = deserialize("{:strings [\"one\" \"two\" \"three\"]}", ListSchema.class);
        List<String> stringList = listSchema.strings();

        List<Integer> collect = stringList.stream().map(x -> x.length()).collect(Collectors.toList());

        assertEquals(3, collect.get(0).intValue());
        assertEquals(3, collect.get(1).intValue());
        assertEquals(5, collect.get(2).intValue());
    }

    @Test
    public void setOfStrings() {
        SetSchema setSchema = deserialize("{:strings #{\"one\" \"two\" \"three\"}}", SetSchema.class);
        Set<String> stringSet = setSchema.strings();
        assertEquals(3, stringSet.size());
        assertTrue(stringSet.contains("one"));
        assertTrue(stringSet.contains("two"));
        assertTrue(stringSet.contains("three"));
    }

    @Test
    public void embeddedMap() {
        String edn = "{:dictionary {\"key\" \"value\"}}";
        MapSchema mapSchema = deserialize(edn, MapSchema.class);
        assertEquals("value", mapSchema.dictionary().get("key"));
        assertEquals(1, mapSchema.dictionary().size());
    }

    @Test
    public void listOfIntegers() {
        ListSchema deserialized = deserialize("{:ints [nil 2 nil 4 nil]}", ListSchema.class);
        List<Integer> builtList = new ArrayList<>();
        builtList.add(null);
        builtList.add(2);
        builtList.add(null);
        builtList.add(4);
        builtList.add(null);
        ListSchema built = newInstance(ListSchema.class).ints(builtList);

        assertEquals(builtList, deserialized.ints());
        assertEquals(builtList, built.ints());
    }

    @Test
    public void mapOfIntegersToIntegers() {
        MapSchema deserialized = deserialize("{:ints {1 2, 3 4}}", MapSchema.class);
        Map<Integer, Integer> builtMap = new HashMap<>();
        builtMap.put(1, 2);
        builtMap.put(3, 4);
        MapSchema built = newInstance(MapSchema.class).ints(builtMap);

        assertEquals(builtMap, deserialized.ints());
        assertEquals(builtMap, built.ints());
    }
}

interface ListSchema extends DynamicObject<ListSchema> {
    List<String> strings();
    List<Integer> ints();

    ListSchema ints(List<Integer> ints);
}

interface SetSchema extends DynamicObject<SetSchema> {
    Set<String> strings();
}

interface MapSchema extends DynamicObject<MapSchema> {
    Map<String, String> dictionary();
    Map<Integer, Integer> ints();

    MapSchema ints(Map<Integer, Integer> ints);
}

@@ -69,37 +69,8 @@
 %0D%0A%0D%0A
-import java.util.ArrayList;%0D%0A
 impo
@@ -349,24 +349,64 @@
 wInstance;%0D%0A
+import static java.util.Arrays.asList;%0D%0A
 import stati
@@ -2323,172 +2323,41 @@
 t = 
-new ArrayList%3C%3E();%0D%0A        builtList.add(null);%0D%0A        builtList.add(2);%0D%0A        builtList.add(null);%0D%0A        builtList.add(4);%0D%0A        builtList.add(
+asList(null, 2, null, 4, 
 null);%0D%0A
     
@@ -2348,24 +2348,26 @@
  4, null);%0D%0A
+%0D%0A
         List

Simplify setup