package cz.encircled.joiner.core.vendor;

import com.querydsl.core.types.EntityPath;
import com.querydsl.jpa.HQLTemplates;
import com.querydsl.jpa.JPQLQuery;
import com.querydsl.jpa.hibernate.HibernateQuery;
import com.querydsl.jpa.impl.JPAQuery;
import cz.encircled.joiner.core.JoinerProperties;
import cz.encircled.joiner.query.JoinerQuery;
import cz.encircled.joiner.query.join.JoinDescription;
import org.hibernate.Session;
import org.hibernate.StatelessSession;
import org.hibernate.query.Query;

import javax.persistence.EntityManager;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * @author Kisel on 21.01.2016.
 */
public class HibernateRepository extends AbstractVendorRepository implements JoinerVendorRepository {

    private static StatelessSession statelessSession;

    private static synchronized StatelessSession getStatelessSession(EntityManager entityManager) {
        if (statelessSession == null || !statelessSession.isOpen()) {
            statelessSession = entityManager.unwrap(Session.class).getSessionFactory().openStatelessSession();
        }
        return statelessSession;
    }

    @Override
    public void addFetch(JPQLQuery<?> query, JoinDescription joinDescription, Collection<JoinDescription> joins, EntityPath<?> rootPath) {
        query.fetchJoin();
    }

    @Override
    public <T> List<T> getResultList(JoinerQuery<?, T> request, JPQLQuery<T> query, JoinerProperties joinerProperties) {
        if (query instanceof HibernateQuery) {
            Query<T> jpaQuery = ((HibernateQuery<T>) query).createQuery();
            for (Map.Entry<String, List<Object>> entry : request.getHints().entrySet()) {
                for (Object value : entry.getValue()) {
                    jpaQuery.setHint(entry.getKey(), value);
                }
            }
            for (Map.Entry<String, List<Object>> entry : joinerProperties.defaultHints.entrySet()) {
                for (Object value : entry.getValue()) {
                    jpaQuery.setHint(entry.getKey(), value);
                }
            }
            return jpaQuery.getResultList();
        }
        return super.getResultList(request, query, joinerProperties);
    }

    @Override
    public <R> JPQLQuery<R> createQuery(EntityManager entityManager, JoinerProperties joinerProperties) {
        if (joinerProperties.useStatelessSessions) {
            StatelessSession session = getStatelessSession(entityManager);
            return new HibernateQuery<>(session);
        }

        return new JPAQuery<>(entityManager, HQLTemplates.DEFAULT);
    }

}

@@ -757,394 +757,8 @@
  %7B%0A%0A
-    private static StatelessSession statelessSession;%0A%0A    private static synchronized StatelessSession getStatelessSession(EntityManager entityManager) %7B%0A        if (statelessSession == null %7C%7C !statelessSession.isOpen()) %7B%0A            statelessSession = entityManager.unwrap(Session.class).getSessionFactory().openStatelessSession();%0A        %7D%0A        return statelessSession;%0A    %7D%0A%0A
     
@@ -1118,16 +1118,27 @@
 ateQuery
+WithSession
 ) %7B%0A    
@@ -1149,29 +1149,42 @@
     
-Query%3CT%3E jpaQuery
+HibernateQueryWithSession%3CT%3E hq
  = 
-(
 (Hib
@@ -1198,19 +1198,100 @@
 uery
-%3CT%3E) query)
+WithSession%3CT%3E) query;%0A            try (hq.session) %7B%0A                Query%3CT%3E jpaQuery = hq
 .cre
@@ -1306,32 +1306,36 @@
 ();%0A            
+    
 for (Map.Entry%3CS
@@ -1404,32 +1404,36 @@
                 
+   
+ 
 for (Object valu
@@ -1448,32 +1448,36 @@
 y.getValue()) %7B%0A
+    
                 
@@ -1529,34 +1529,42 @@
                 
+  
-%7D%0A
+  %7D%0A    
             %7D%0A  
@@ -1553,32 +1553,36 @@
               %7D%0A
+    
             for 
@@ -1658,32 +1658,36 @@
 s.entrySet()) %7B%0A
+    
                 
@@ -1738,32 +1738,36 @@
                 
+    
 jpaQuery.setHint
@@ -1799,34 +1799,42 @@
                 
-%7D%0A
+    %7D%0A    
             %7D%0A  
@@ -1839,24 +1839,28 @@
             
+  
+  
 return jpaQu
@@ -1876,24 +1876,38 @@
 sultList();%0A
+            %7D%0A
         %7D%0A  
@@ -2197,41 +2197,85 @@
 n = 
-getStatelessSession(entityManager
+entityManager.unwrap(Session.class).getSessionFactory().openStatelessSession(
 );%0A 
@@ -2310,16 +2310,27 @@
 ateQuery
+WithSession
 %3C%3E(sessi
@@ -2420,10 +2420,268 @@
 %0A    %7D%0A%0A
+    static class HibernateQueryWithSession%3CT%3E extends HibernateQuery%3CT%3E %7B%0A        final StatelessSession session;%0A%0A        HibernateQueryWithSession(StatelessSession session) %7B%0A            super(session);%0A            this.session = session;%0A        %7D%0A    %7D%0A%0A
 %7D%0A

Fix usage of Hibernate StatelessSession