001/* 002 * Copyright 2020 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.core.util; 017 018import java.util.Collection; 019 020import org.ametys.core.cache.AbstractCacheManager; 021import org.ametys.core.cache.AbstractCacheManager.CacheType; 022import org.ametys.core.cache.Cache; 023import org.ametys.runtime.i18n.I18nizableText; 024 025/** 026 * Trait for easily cache some elements, in multiple Caches if necessary. 027 * <br>This is the preferred way to manage the caching of elements (over {@link CachingComponent}), as it will use 028 * the {@link AbstractCacheManager CacheManager mechanism}, and as it is an interface, it will not interfere in the class hierarchy 029 * of the implementing component. 030 * <br> 031 * <br>The methods to implement are: 032 * <ul> 033 * <li>{@link #getManagedCaches}: for describing the managed caches;</li> 034 * <li>{@link #getCacheManager}: for binding the reference of {@link AbstractCacheManager};</li> 035 * <li>{@link #isCachingEnabled}: for implementing the potential business logic to determine if the caching is enabled.</li> 036 * </ul> 037 * <br> 038 * <br>The methods to call are: 039 * <ul> 040 * <li>{@link #createCaches}: for creating the managed caches;</li> 041 * <li>{@link #removeCaches}: for removing the managed caches;</li> 042 * <li>{@link #getCache}: for getting a reference to a managed cache.</li> 043 * </ul> 044 */ 045public interface Cacheable 046{ 047 /** 048 * A configuration for describing to {@link Cacheable} interface the managed {@link Cache caches} to {@link AbstractCacheManager#createMemoryCache create}. 049 * <br>It simply composes a cache id, a label and a description. 050 */ 051 public static final class SingleCacheConfiguration 052 { 053 private String _id; 054 private I18nizableText _label; 055 private I18nizableText _description; 056 057 private SingleCacheConfiguration(String id, I18nizableText label, I18nizableText description) 058 { 059 _id = id; 060 _label = label; 061 _description = description; 062 } 063 064 /** 065 * Builds a {@link SingleCacheConfiguration} 066 * @param id The id of the cache 067 * @param label The label of the cache 068 * @param description The description of the cache 069 * @return A {@link SingleCacheConfiguration} 070 */ 071 public static SingleCacheConfiguration of(String id, I18nizableText label, I18nizableText description) 072 { 073 return new SingleCacheConfiguration(id, label, description); 074 } 075 } 076 077 /** 078 * Gets the managed caches. 079 * <br>This <b>is</b> meant to be implemented in order to describe the managed caches and automatically 080 * create and remove the corresponding caches in {@link #createCaches} and {@link #removeCaches} default methods. 081 * <br>This <b>is not</b> meant to be called manually. 082 * @return A collection of {@link SingleCacheConfiguration}s to manage 083 */ 084 Collection<SingleCacheConfiguration> getManagedCaches(); 085 086 /** 087 * Returns <code>true</code> if the cache is enabled 088 * <br>The default implementation returns <code>true</code>. 089 * <br>You <b>can</b> override this method to modify the behavior. 090 * @return <code>true</code> if the cache is enabled 091 */ 092 default boolean isCachingEnabled() 093 { 094 return true; 095 } 096 097 /** 098 * Returns the instance of the implementation of {@link AbstractCacheManager} to use. 099 * <br>This <b>is not</b> meant to be called manually. 100 * @return The {@link AbstractCacheManager} to bind 101 */ 102 AbstractCacheManager getCacheManager(); 103 104 /** 105 * Gets the managed cache with the given id. 106 * <br>It is advised to create its own business methods which call this method in order to retrieve the caches. 107 * <br>For instance, if the implementing class {@link #getManagedCaches declares} two caches, 108 * you can create the two methods: 109 * <ul> 110 * <li><code>Cache<String, Double> getCachePriceByProductId()</code></li> 111 * <li>and <code>Cache<Integer, Boolean> getCacheAvailabilityByProductIndex()</code></li> 112 * </ul> 113 * which simply call this method, so as to have methods to retrieve the caches with more semantic. 114 * @param <K> The type of the keys in the cache 115 * @param <V> The type of the values in the cache 116 * @param cacheId The cache id 117 * @return The managed {@link Cache} 118 */ 119 default <K, V> Cache<K, V> getCache(String cacheId) 120 { 121 return getCacheManager().get(cacheId); 122 } 123 124 /** 125 * Creates the managed caches. 126 * <br>This <b>is</b> meant to be called manually, at the beginning of the lifecycle of the implementing class, 127 * in order to create and initialize the corresponding caches. 128 * <br>This <b>is not</b> meant to be overridden. 129 */ 130 default void createCaches() 131 { 132 if (isCachingEnabled()) 133 { 134 for (SingleCacheConfiguration cacheConfig : getManagedCaches()) 135 { 136 _createCache(cacheConfig._id, cacheConfig._label, cacheConfig._description); 137 } 138 } 139 } 140 141 private void _createCache(String id, I18nizableText label, I18nizableText description) 142 { 143 getCacheManager().createMemoryCache( 144 id, 145 label, 146 description, 147 hasComputableSize(), 148 null); 149 } 150 151 /** 152 * Removes the managed caches. 153 * <br>This <b>is</b> meant to be called manually, at the end of the lifecycle of the implementing class, 154 * in order to remove the corresponding caches. 155 * <br>This <b>is not</b> meant to be overridden. 156 */ 157 default void removeCaches() 158 { 159 if (isCachingEnabled()) 160 { 161 for (SingleCacheConfiguration cacheConfig : getManagedCaches()) 162 { 163 getCacheManager().removeCache(cacheConfig._id, CacheType.MEMORY); 164 } 165 } 166 } 167 168 /** 169 * Determines if the cache has a computable size. This operation can be very slow. 170 * @return <code>true</code> if we can compute the size on the cache. 171 */ 172 default boolean hasComputableSize() 173 { 174 return true; 175 } 176}