// Path: jandy-server/src/main/java/io/jandy/domain/data/ClassObject.java
// @Data
// @Accessors(chain = true)
// public class ClassObject implements Serializable {
//   private String id;
//   private String name;
//   private String packageName;
// 
//   @Override
//   public boolean equals(Object o) {
//     if (this == o) return true;
//     if (o == null || getClass() != o.getClass()) return false;
//     ClassObject that = (ClassObject) o;
//     return Objects.equals(name, that.name) &&
//         Objects.equals(packageName, that.packageName);
//   }
// 
//   @Override
//   public int hashCode() {
//     return Objects.hash(name, packageName);
//   }
// }
// 
// Path: jandy-server/src/main/java/io/jandy/domain/data/ExceptionObject.java
// @Data
// @Accessors(chain = true)
// public class ExceptionObject implements Serializable {
// 
//   private String id;
//   private ClassObject klass;
//   private String message;
// }
// 
// Path: jandy-server/src/main/java/io/jandy/util/sql/conditional/Where.java
// public static Where eq(String key, Object value) {
//   Where w = new Where();
//   w.type = WhereType.EQUALS;
//   w.key = key;
//   w.value = value;
// 
//   return w;
// }


import io.jandy.domain.data.ClassObject;
import io.jandy.domain.data.ExceptionObject;
import io.jandy.domain.data.MethodObject;
import io.jandy.domain.data.TreeNode;
import io.jandy.service.ProfService;
import io.jandy.util.sql.BatchUpdateQueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import static io.jandy.util.sql.Query.*;
import static io.jandy.util.sql.Query.select;
import static io.jandy.util.sql.Query.subQuery;
import static io.jandy.util.sql.conditional.Where.eq;
        List<ExceptionObject> exceptionObjects = treeNodes.stream().map(n -> n.getAcc() == null ? null : n.getAcc().getException()).filter(Objects::nonNull).collect(Collectors.toList());

        if (classObjects.size() > 0) {
            insert().ignore().into("prof_class")
                    .columns("name", "package_name")
                    .values(classObjects.stream().map(co -> new Object[] {co.getName(), co.getPackageName()}))
                    .execute(jdbc);
        }

        if (methodObjects.size() > 0) {
            insert().ignore().into("prof_method")
                    .columns("name", "access", "descriptor", "owner_id")
                    .values(methodObjects.stream().map(mo -> new Object[]{
                            mo.getName(), mo.getAccess(), mo.getDescriptor(),
                            mo.getOwner() == null ? null : subQuery(
                                    select().columns("id").from("prof_class").where(
                                            eq("name", mo.getOwner().getName()).and(eq("package_name", mo.getOwner().getPackageName()))
                                    )
                            )
                    }))
                    .execute(jdbc);
        }

        if (exceptionObjects.size() > 0) {
            insert().ignore().into("prof_exception")
                    .columns("id", "message", "klass_id")
                    .values(exceptionObjects.stream().map(eo -> new Object[]{
                            eo.getId(), eo.getMessage(),
                            eo.getKlass() == null ? null : subQuery(
                                    select().columns("id").from("prof_class").where(
// Path: jandy-server/src/main/java/io/jandy/domain/data/ClassObject.java
// @Data
// @Accessors(chain = true)
// public class ClassObject implements Serializable {
//   private String id;
//   private String name;
//   private String packageName;
// 
//   @Override
//   public boolean equals(Object o) {
//     if (this == o) return true;
//     if (o == null || getClass() != o.getClass()) return false;
//     ClassObject that = (ClassObject) o;
//     return Objects.equals(name, that.name) &&
//         Objects.equals(packageName, that.packageName);
//   }
// 
//   @Override
//   public int hashCode() {
//     return Objects.hash(name, packageName);
//   }
// }
// 
// Path: jandy-server/src/main/java/io/jandy/domain/data/ExceptionObject.java
// @Data
// @Accessors(chain = true)
// public class ExceptionObject implements Serializable {
// 
//   private String id;
//   private ClassObject klass;
//   private String message;
// }
// 
// Path: jandy-server/src/main/java/io/jandy/util/sql/conditional/Where.java
// public static Where eq(String key, Object value) {
//   Where w = new Where();
//   w.type = WhereType.EQUALS;
//   w.key = key;
//   w.value = value;
// 
//   return w;
// }


// Path: jandy-server/src/main/java/io/jandy/service/impl/ProfServiceForMySQL.java
import io.jandy.domain.data.ClassObject;
import io.jandy.domain.data.ExceptionObject;
import io.jandy.domain.data.MethodObject;
import io.jandy.domain.data.TreeNode;
import io.jandy.service.ProfService;
import io.jandy.util.sql.BatchUpdateQueryBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Profile;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import static io.jandy.util.sql.Query.*;
import static io.jandy.util.sql.Query.select;
import static io.jandy.util.sql.Query.subQuery;
import static io.jandy.util.sql.conditional.Where.eq;

        List<ExceptionObject> exceptionObjects = treeNodes.stream().map(n -> n.getAcc() == null ? null : n.getAcc().getException()).filter(Objects::nonNull).collect(Collectors.toList());

        if (classObjects.size() > 0) {
            insert().ignore().into("prof_class")
                    .columns("name", "package_name")
                    .values(classObjects.stream().map(co -> new Object[] {co.getName(), co.getPackageName()}))
                    .execute(jdbc);
        }

        if (methodObjects.size() > 0) {
            insert().ignore().into("prof_method")
                    .columns("name", "access", "descriptor", "owner_id")
                    .values(methodObjects.stream().map(mo -> new Object[]{
                            mo.getName(), mo.getAccess(), mo.getDescriptor(),
                            mo.getOwner() == null ? null : subQuery(
                                    select().columns("id").from("prof_class").where(
                                            eq("name", mo.getOwner().getName()).and(eq("package_name", mo.getOwner().getPackageName()))
                                    )
                            )
                    }))
                    .execute(jdbc);
        }

        if (exceptionObjects.size() > 0) {
            insert().ignore().into("prof_exception")
                    .columns("id", "message", "klass_id")
                    .values(exceptionObjects.stream().map(eo -> new Object[]{
                            eo.getId(), eo.getMessage(),
                            eo.getKlass() == null ? null : subQuery(
                                    select().columns("id").from("prof_class").where(
                                            eq("name", eo.getKlass().getName()).and(eq("package_name", eo.getKlass().getPackageName()))