package be.bendem.sqlstreams;

import be.bendem.sqlstreams.util.Tuple2;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.sql.DriverManager;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Stream;

public class JoinTests {

    private Sql sql;

    @Before
    public void setup() throws Exception {
        sql = Sql.connect(DriverManager.getConnection("jdbc:sqlite:"));
        sql.execute("create table users (" +
            "id integer primary key autoincrement not null," +
            "name varchar(50) not null" +
        ")");
        sql.execute("create table posts (" +
            "id integer primary key autoincrement not null," +
            "user_id integer references users (id)," +
            "content text" +
        ")");

        sql.update("insert into users (name) values ('bob'), ('georges')");
        sql.update("insert into posts (user_id, content) values (1, 'whee'), (1, 'baah'), (2, 'bleh')");
    }

    @After
    public void teardown() throws Exception {
        sql.close();
    }

    private static class User {
        private final int id;
        private final String name;
        public User(int id, String name) {
            this.id = id;
            this.name = name;
        }
        public int getId() { return id; }
        public String getName() { return name; }

        @Override
        public String toString() {
            return "User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
        }

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

        @Override
        public int hashCode() {
            return Objects.hash(id);
        }
    }

    private static class Post {
        private final int id;
        private final int userId;
        private final String content;
        public Post(int id, int userId, String content) {
            this.id = id;
            this.userId = userId;
            this.content = content;
        }

        public String getContent() { return content; }
        public int getId() { return id; }
        public int getUserId() { return userId; }

        @Override
        public String toString() {
            return "Post{" +
                "content='" + content + '\'' +
                ", id=" + id +
                ", userId=" + userId +
                '}';
        }
    }

    @Test
    public void testJoin() {
        try (Stream<Tuple2<User, Post>> s = sql.join("select * from users inner join posts on users.id = posts.user_id", User.class, Post.class)) {
            Map<User, List<Post>> postsByUsers = s.collect(Tuple2.grouping());
            System.out.println(postsByUsers);
            for (Map.Entry<User, List<Post>> entry : postsByUsers.entrySet()) {
                switch (entry.getKey().getId()) {
                case 1:
                    Assert.assertEquals(2, entry.getValue().size());
                    break;
                case 2:
                    Assert.assertEquals(1, entry.getValue().size());
                    break;
                default:
                    Assert.fail();
                }
            }
        }
    }

}

@@ -190,24 +190,83 @@
 verManager;%0A
+import java.util.Collections;%0Aimport java.util.Comparator;%0A
 import java.
@@ -3026,75 +3026,123 @@
     
-for (Map.Entry%3CUser, List%3CPost%3E%3E entry : postsByUsers.entrySet()) %7B
+postsByUsers.forEach((user, posts) -%3E %7B%0A                Collections.sort(posts, Comparator.comparing(Post::getId));
 %0A   
@@ -3166,22 +3166,12 @@
 ch (
-entry.getKey()
+user
 .get
@@ -3246,154 +3246,467 @@
 als(
-2, entry.getValue().size());%0A                    break;%0A                case 2:%0A                    Assert.assertEquals(1, entry.getValue().size()
+%22bob%22, user.name);%0A                    Assert.assertEquals(2, posts.size());%0A                    Assert.assertEquals(%22whee%22, posts.get(0).content);%0A                    Assert.assertEquals(%22baah%22, posts.get(1).content);%0A                    break;%0A                case 2:%0A                    Assert.assertEquals(%22georges%22, user.name);%0A                    Assert.assertEquals(1, posts.size());%0A                    Assert.assertEquals(%22bleh%22, posts.get(0).content
 );%0A 
@@ -3814,32 +3814,34 @@
  %7D%0A            %7D
+);
 %0A        %7D%0A    %7D

Test mapped values in JoinTests