package com.psddev.dari.db;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.psddev.dari.util.AbstractFilter;
import com.psddev.dari.util.Settings;

/** Enables various per-request database result caching. */
public class CachingDatabaseFilter extends AbstractFilter {

    public static final String CACHE_PARAMETER = "_cache";

    // --- AbstractFilter support ---
    @Override
    protected void doForward(
            HttpServletRequest request,
            HttpServletResponse response,
            FilterChain chain)
            throws IOException, ServletException {
        doRequest(request, response, chain);
    }

    @Override
    protected void doRequest(
            HttpServletRequest request,
            HttpServletResponse response,
            FilterChain chain)
            throws IOException, ServletException {

        if (Settings.getOrDefault(boolean.class, "dari/isCachingFilterEnabled", true) &&
                !Boolean.FALSE.toString().equals(request.getParameter(CACHE_PARAMETER))) {

            CachingDatabase caching = new CachingDatabase();
            caching.setDelegate(Database.Static.getDefault());

            try {
                Database.Static.overrideDefault(caching);

                chain.doFilter(request, response);

            } finally {
                Database.Static.restoreDefault();
            }

        } else {
            chain.doFilter(request, response);
        }
    }
}

@@ -49,16 +49,87 @@
 ception;
+%0Aimport java.util.Set;%0Aimport java.util.HashSet;%0Aimport java.util.UUID;
 %0A%0Aimport
@@ -372,16 +372,100 @@
 tings;%0A%0A
+import com.google.common.cache.Cache;%0Aimport com.google.common.cache.CacheBuilder;%0A%0A
 /** Enab
@@ -637,16 +637,129 @@
 ache%22;%0A%0A
+    private static final Cache%3CString, Set%3CUUID%3E%3E idCache = CacheBuilder.newBuilder().maximumSize(250).build();%0A%0A
     // -
@@ -1579,124 +1579,880 @@
     
-try %7B%0A                Database.Static.overrideDefault(caching);%0A%0A                chain.doFilter(request, response);%0A
+String url = request.getServletPath() + %22?%22 + request.getQueryString();%0A            boolean preload = Settings.getOrDefault(boolean.class, %22dari/isCachingFilterPreloadEnabled%22, false);%0A%0A            try %7B%0A                Database.Static.overrideDefault(caching);%0A%0A                if (preload) %7B%0A                    Set%3CUUID%3E objectIds = idCache.getIfPresent(url);%0A                    if (objectIds != null) %7B%0A                        Query.from(Record.class).using(caching).where(%22id = ?%22, objectIds).selectAll();%0A                    %7D%0A                %7D%0A%0A                chain.doFilter(request, response);%0A%0A                if (preload) %7B%0A                    Set%3CUUID%3E objectIds = new HashSet%3CUUID%3E(caching.getObjectCache().keySet());%0A                    if (objectIds.size() %3E 0) %7B%0A                        idCache.put(url, objectIds);%0A                    %7D%0A                %7D
 %0A   

Enable preloading of references.