/*
 * Copyright (c) 2011 Haulmont Technology Ltd. All Rights Reserved.
 * Haulmont Technology proprietary and confidential.
 * Use is subject to license terms.
 */

package com.haulmont.cuba.core.app.cache;

import com.haulmont.chile.core.model.MetaClass;
import com.haulmont.cuba.core.EntityManager;
import com.haulmont.cuba.core.Persistence;
import com.haulmont.cuba.core.Query;
import com.haulmont.cuba.core.Transaction;
import com.haulmont.cuba.core.entity.Entity;
import com.haulmont.cuba.core.global.Metadata;
import com.haulmont.cuba.core.global.Scripting;
import com.haulmont.cuba.core.global.View;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.inject.Inject;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * JPQL cache loader <br/>
 * Load objects tree with jpql query and view
 * <p>$Id$</p>
 *
 * @author artamonov
 */
@SuppressWarnings({"unused"})
public class StandardCacheLoader implements CacheLoader {

    @Inject
    private Persistence persistence;

    @Inject
    private Metadata metadata;

    @Inject
    private Scripting scripting;

    private static Log log = LogFactory.getLog(ObjectsCache.class);

    private String viewName;
    private String queryPath;
    private String metaClassName;

    private String dbQuery;

    public String getViewName() {
        return viewName;
    }

    public void setViewName(String viewName) {
        this.viewName = viewName;
    }

    public String getQueryPath() {
        return queryPath;
    }

    public void setQueryPath(String queryPath) {
        this.queryPath = queryPath;
    }

    public String getMetaClassName() {
        return metaClassName;
    }

    public void setMetaClassName(String metaClassName) {
        this.metaClassName = metaClassName;
    }

    @Override
    @SuppressWarnings("unchecked")
    public CacheSet loadData(ObjectsCache cache) throws CacheException {
        CacheSet cacheSet;

        if (StringUtils.isEmpty(dbQuery)) {
            try {
                dbQuery = scripting.getResourceAsString(queryPath);
            } catch (Exception e) {
                log.error("Broken or missing query file for cache: " + cache.getName());
                throw new CacheException(e);
            }
        }

        MetaClass metaClass = metadata.getSession().getClass(metaClassName);
        View view = metadata.getViewRepository().getView(metaClass, viewName);

        Transaction tx = persistence.createTransaction();

        try {
            EntityManager em = persistence.getEntityManager();
            em.setView(view);
            Query query = em.createQuery(dbQuery);

            List<Object> resultList = query.getResultList();
            cacheSet = new CacheSet(resultList);
            tx.commit();
        } catch (Exception e) {
            throw new CacheException(e);
        } finally {
            tx.end();
        }

        return cacheSet;
    }

    @Override
    public void updateData(CacheSet cacheSet, Map<String, Object> params) throws CacheException {
        Collection<Object> items = cacheSet.getItems();

        List updateItems = (List) params.get("items");

        if ((updateItems != null) && (updateItems.size() > 0)) {
            MetaClass metaClass = metadata.getSession().getClass(metaClassName);
            View view = metadata.getViewRepository().getView(metaClass, viewName);

            Transaction tx = persistence.createTransaction();

            try {
                EntityManager em = persistence.getEntityManager();
                em.setView(view);

                for (Object item : updateItems) {
                    Entity entity = (Entity) item;
                    entity = em.find(entity.getClass(), entity.getId());

                    items.remove(item);
                    items.add(entity);
                }

                tx.commit();
            } catch (Exception e) {
                throw new CacheException(e);
            } finally {
                tx.end();
            }
        } else {
            log.debug("Nothing to update");
        }
    }
}
@@ -464,21 +464,29 @@
 ore.
-entity.Entity
+app.PersistenceConfig
 ;%0D%0Ai
@@ -518,72 +518,21 @@
 ore.
-global.Metadata;%0D%0Aimport com.haulmont.cuba.core.global.Scripting
+entity.Entity
 ;%0D%0Ai
@@ -567,20 +567,17 @@
 .global.
-View
+*
 ;%0D%0Aimpor
@@ -1177,24 +1177,81 @@
 ripting;%0D%0A%0D%0A
+    @Inject%0D%0A    private Configuration configuration;%0D%0A%0D%0A
     private 
@@ -2828,26 +2828,80 @@
 (dbQuery);%0D%0A
+            query.setMaxResults(getMaxQueryResults());
 %0D%0A
-
             
@@ -3299,32 +3299,127 @@
 cheException %7B%0D%0A
+        if (configuration.getConfig(GlobalConfig.class).getTestMode())%0D%0A            return;%0D%0A%0D%0A
         Collecti
@@ -4462,24 +4462,24 @@
  update%22);%0D%0A
-
         %7D%0D%0A 
@@ -4483,10 +4483,233 @@
 %0D%0A    %7D%0D
+%0A%0D%0A    protected int getMaxQueryResults() %7B%0D%0A        return configuration.getConfig(GlobalConfig.class).getTestMode() ?%0D%0A                500 : configuration.getConfig(PersistenceConfig.class).getDefaultMaxFetchUI();%0D%0A    %7D%0D
 %0A%7D

Test mode support