aplcache

Details

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 7e785df..d9b4f9c 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
@@ -14,8 +14,6 @@ import java.io.FileNotFoundException;
 import java.io.FileReader;
 import java.io.FileWriter;
 import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.function.Supplier;
@@ -33,7 +31,7 @@ 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 Map<String, Map<String, Long>> APLCACHE_METHOD_HAS_CACHEABLE_PARAMETERS = new HashMap<>();
     private static final String APLCACHE_LOG
             = System.getenv("APLCACHE_LOG") != null && !System.getenv("APLCACHE_LOG").isEmpty() && !System.getenv("APLCACHE_LOG").equals("null")
             ? System.getenv("APLCACHE_LOG") : null;
@@ -55,11 +53,17 @@ public class APLCache<V> {
             JsonParser jsonParser = new JsonParser();
             JsonObject jsonObject = jsonParser.parse(fileReader).getAsJsonObject();
             jsonObject.entrySet().forEach(entry -> {
-                Collection<String> parameters = new ArrayList<>();
-                entry.getValue().getAsJsonArray().forEach(parameter -> {
-                    parameters.add(parameter.getAsString());
-                });
-                APLCACHE_METHOD_HAS_CACHEABLE_PARAMETERS.put(entry.getKey(), parameters);
+                Map<String, Long> inputsHasTTL = new HashMap<>();
+                if (entry.getValue().isJsonArray()) {
+                    entry.getValue().getAsJsonArray().forEach(parameter -> {
+                        inputsHasTTL.put(parameter.getAsString(), 0L);
+                    });
+                } else {
+                    entry.getValue().getAsJsonObject().entrySet().forEach(innerEntry -> {
+                        inputsHasTTL.put(innerEntry.getKey(), innerEntry.getValue().getAsLong());
+                    });
+                }
+                APLCACHE_METHOD_HAS_CACHEABLE_PARAMETERS.put(entry.getKey(), inputsHasTTL);
             });
             LOGGER.log(Level.INFO, "cache file loaded");
         } catch (FileNotFoundException ex) {
@@ -96,14 +100,14 @@ public class APLCache<V> {
             LOGGER.log(Level.WARNING, "no method is cacheable");
             return false;
         }
-        Collection<String> cacheableParameters = APLCACHE_METHOD_HAS_CACHEABLE_PARAMETERS.get(method);
-        if (cacheableParameters == null) {
+        Map<String, Long> cacheableInputsHasTTL = APLCACHE_METHOD_HAS_CACHEABLE_PARAMETERS.get(method);
+        if (cacheableInputsHasTTL == null) {
             LOGGER.log(Level.WARNING, "method not cacheable: {0}", method);
             return false;
         }
         String serialisedParameters = Stream.of(parameters).map(JSONSerialiser::serialise)
                 .collect(Collectors.joining(",", "[", "]"));
-        if (cacheableParameters.contains(serialisedParameters)) {
+        if (cacheableInputsHasTTL.containsKey(serialisedParameters)) {
             return true;
         }
         log(this.multiCache.getCachePerformance().getName() + " : " + serialisedParameters);
@@ -116,18 +120,32 @@ public class APLCache<V> {
             LOGGER.log(Level.WARNING, "no method is cacheable");
             return false;
         }
-        Collection<String> cacheableParameters = APLCACHE_METHOD_HAS_CACHEABLE_PARAMETERS.get(method);
+        Map<String, Long> 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)) {
+        if (cacheableParameters.containsKey(parameters)) {
             return true;
         }
         log(this.multiCache.getCachePerformance().getName() + " : " + parameters);
         return false;
     }
 
+    public long getTTLforInput(String method, String input) {
+        loadCacheableParameters();
+        if (APLCACHE_METHOD_HAS_CACHEABLE_PARAMETERS.isEmpty()) {
+            LOGGER.log(Level.WARNING, "no method is cacheable");
+            return 0;
+        }
+        Map<String, Long> cacheableInputsHasTTL = APLCACHE_METHOD_HAS_CACHEABLE_PARAMETERS.get(method);
+        if (cacheableInputsHasTTL == null) {
+            LOGGER.log(Level.WARNING, "method not cacheable: {0}", method);
+            return 0;
+        }
+        return cacheableInputsHasTTL.get(input);
+    }
+
     public V computeIfAbsent(Thread currentThread, Object[] parameters, Supplier<V> supplier, long timeToLive) {
         StackTraceElement[] stackTrace = currentThread.getStackTrace();
         StackTraceElement stackTraceElement;
@@ -146,7 +164,13 @@ public class APLCache<V> {
             } catch (KeyNotFoundException ex) {
                 V get = supplier.get();
                 if (isCacheable(methodName, serialisedParameters)) {
-                    this.multiCache.put(serialisedParameters, get, timeToLive);
+                    long recommendedTTLforInput = getTTLforInput(methodName, serialisedParameters);
+                    if (recommendedTTLforInput == 0) {
+                        this.multiCache.put(serialisedParameters, get, timeToLive);
+                    } else {
+                        LOGGER.log(Level.WARNING, "provided TTL being replaced for recommemded");
+                        this.multiCache.put(serialisedParameters, get, recommendedTTLforInput);
+                    }
                 }
                 return get;
             }
@@ -171,7 +195,12 @@ public class APLCache<V> {
             } catch (KeyNotFoundException ex) {
                 V get = supplier.get();
                 if (isCacheable(methodName, serialisedParameters)) {
-                    this.multiCache.put(serialisedParameters, get);
+                    long ttLforInput = getTTLforInput(methodName, serialisedParameters);
+                    if (ttLforInput == 0) {
+                        this.multiCache.put(serialisedParameters, get);
+                    } else {
+                        this.multiCache.put(serialisedParameters, get, ttLforInput);
+                    }
                 }
                 return get;
             }