aplcache

added computeIfAbsent methods to behave as a cache that stores

6/12/2019 10:39:41 AM

Details

pom.xml 5(+5 -0)

diff --git a/pom.xml b/pom.xml
index 5689d62..f67e940 100644
--- a/pom.xml
+++ b/pom.xml
@@ -33,6 +33,11 @@
             <artifactId>JSONSerialiser</artifactId>
             <version>1.0</version>
         </dependency>
+        <dependency>
+            <groupId>br.ufrgs.inf.prosoft.cache</groupId>
+            <artifactId>Cache</artifactId>
+            <version>1.0</version>
+        </dependency>
     </dependencies>
     
     <build>
diff --git a/src/main/java/br/ufrgs/inf/prosoft/aplcache/caching/APLCache.java b/src/main/java/br/ufrgs/inf/prosoft/aplcache/caching/APLCache.java
index 30ae0c7..faf1573 100644
--- a/src/main/java/br/ufrgs/inf/prosoft/aplcache/caching/APLCache.java
+++ b/src/main/java/br/ufrgs/inf/prosoft/aplcache/caching/APLCache.java
@@ -5,6 +5,7 @@
  */
 package br.ufrgs.inf.prosoft.aplcache.caching;
 
+import br.ufrgs.inf.prosoft.cache.MultiCache;
 import br.ufrgs.inf.prosoft.jsonserialiser.JSONSerialiser;
 import com.google.gson.JsonObject;
 import com.google.gson.JsonParser;
@@ -16,6 +17,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.function.Supplier;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.stream.Collectors;
@@ -24,13 +26,23 @@ import java.util.stream.Stream;
 /**
  *
  * @author romulo
+ * @param <V>
  */
-public class APLCache {
+public class APLCache<V> {
 
     private static final Logger LOGGER = Logger.getLogger(APLCache.class.getName());
     private static String APLCACHE_CACHEABLE_PARAMETERS = System.getenv("APLCACHE_CACHEABLE_PARAMETERS");
     private static final Map<String, Collection<String>> APLCACHE_METHOD_HAS_CACHEABLE_PARAMETERS = new HashMap<>();
     private static final String APLCACHE_LOG = System.getenv("APLCACHE_LOG");
+    private final MultiCache<String, V> multiCache;
+
+    public APLCache() {
+        this.multiCache = new MultiCache<>();
+    }
+
+    public APLCache(String name) {
+        this.multiCache = new MultiCache<>(name);
+    }
 
     private static void loadCacheableParameters() {
         if (APLCACHE_CACHEABLE_PARAMETERS == null) {
@@ -94,8 +106,62 @@ public class APLCache {
         log("uncacheable " + method + " : " + serialisedParameters);
         return false;
     }
-    
-        private static void log(String message) {
+
+    public static boolean isCacheable(String method, String parameters) {
+        loadCacheableParameters();
+        if (APLCACHE_METHOD_HAS_CACHEABLE_PARAMETERS.isEmpty()) {
+            LOGGER.log(Level.WARNING, "no method is cacheable");
+            return false;
+        }
+        Collection<String> cacheableParameters = APLCACHE_METHOD_HAS_CACHEABLE_PARAMETERS.get(method);
+        if (cacheableParameters == null) {
+            LOGGER.log(Level.WARNING, "method not cacheable: {0}", method);
+            return false;
+        }
+        if (cacheableParameters.contains(parameters)) {
+            return true;
+        }
+        log("uncacheable " + method + " : " + parameters);
+        return false;
+    }
+
+    public V computeIfAbsent(Thread currentThread, Object[] parameters, Supplier<V> supplier, long timeToLive) {
+        StackTraceElement[] stackTrace = currentThread.getStackTrace();
+        StackTraceElement stackTraceElement;
+        try {
+            stackTraceElement = stackTrace[2];
+        } catch (ArrayIndexOutOfBoundsException ex) {
+            stackTraceElement = stackTrace[0];
+        }
+        String methodName = stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName();
+
+        String serialisedParameters = Stream.of(parameters).map(JSONSerialiser::serialise)
+                .collect(Collectors.joining(",", "[", "]"));
+        if (isCacheable(methodName, serialisedParameters)) {
+            return this.multiCache.computeIfAbsent(serialisedParameters, supplier, timeToLive);
+        }
+        return supplier.get();
+    }
+
+    public V computeIfAbsent(Thread currentThread, Object[] parameters, Supplier<V> supplier) {
+        StackTraceElement[] stackTrace = currentThread.getStackTrace();
+        StackTraceElement stackTraceElement;
+        try {
+            stackTraceElement = stackTrace[2];
+        } catch (ArrayIndexOutOfBoundsException ex) {
+            stackTraceElement = stackTrace[0];
+        }
+        String methodName = stackTraceElement.getClassName() + "." + stackTraceElement.getMethodName();
+
+        String serialisedParameters = Stream.of(parameters).map(JSONSerialiser::serialise)
+                .collect(Collectors.joining(",", "[", "]"));
+        if (isCacheable(methodName, serialisedParameters)) {
+            return this.multiCache.computeIfAbsent(serialisedParameters, supplier);
+        }
+        return supplier.get();
+    }
+
+    private static void log(String message) {
         if (APLCACHE_LOG == null) {
             return;
         }