001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.commons.collections; 018 019import static org.apache.juneau.commons.utils.Shorts.*; 020 021/** 022 * Cache modes for {@link Cache} and related cache classes. 023 * 024 * <p> 025 * Defines how cache storage is implemented and when cached entries may be evicted. 026 * 027 * <h5 class='section'>See Also:</h5> 028 * <ul> 029 * <li class='jc'>{@link Cache} 030 * <li class='jc'>{@link Cache2} 031 * <li class='jc'>{@link Cache3} 032 * <li class='jc'>{@link Cache4} 033 * <li class='jc'>{@link Cache5} 034 * </ul> 035 */ 036public enum CacheMode { 037 038 /** 039 * No caching - all lookups invoke the supplier. 040 * 041 * <p> 042 * When this mode is used, the cache will not store any values. Every call to 043 * {@link Cache#get(Object)} or {@link Cache#get(Object, java.util.function.Supplier)} 044 * will invoke the supplier to compute the value. 045 * 046 * <p> 047 * This mode is useful for: 048 * <ul> 049 * <li>Testing scenarios where you want fresh computation each time 050 * <li>Development environments where caching might hide issues 051 * <li>Temporarily disabling caching without code changes 052 * </ul> 053 */ 054 NONE, 055 056 /** 057 * Weak caching - uses {@link java.util.WeakHashMap} for storage. 058 * 059 * <p> 060 * Cache entries can be garbage collected when keys are no longer strongly referenced elsewhere. 061 * The WeakHashMap is wrapped with {@link java.util.Collections#synchronizedMap(java.util.Map)} 062 * for thread safety. 063 * 064 * <p> 065 * This mode is useful for: 066 * <ul> 067 * <li>Caching metadata about objects that may be unloaded (e.g., {@link Class} objects) 068 * <li>Memory-sensitive applications where cache entries should not prevent garbage collection 069 * <li>Scenarios where keys have limited lifetimes 070 * </ul> 071 * 072 * <p> 073 * <b>Note:</b> Weak caching comes with performance trade-offs: 074 * <ul> 075 * <li>Slightly slower access due to synchronization overhead 076 * <li>Entries may be removed unpredictably by the garbage collector 077 * <li>Not suitable for high-concurrency scenarios 078 * </ul> 079 * 080 * <p> 081 * <b>Composite-key caches:</b> {@link Cache2}, {@link Cache3}, {@link Cache4}, and {@link Cache5} synthesize 082 * an internal composite-key object (e.g. a {@code TupleN}) on every lookup, and that object is never exposed 083 * to the caller - it is reachable only from the cache's own backing map. As a result, a WEAK-mode entry in 084 * one of these caches becomes GC-eligible <b>immediately</b> after insertion and may be reclaimed at the very 085 * next garbage collection, i.e. WEAK effectively behaves like {@link #NONE} once any GC has occurred. This is 086 * best-effort, <b>not retention-guaranteed</b> weak-key caching by design (not a bug) and is <i>not</i> 087 * equivalent to WEAK on the single-key {@link Cache}, where retention instead tracks the caller's own key and 088 * an entry survives for as long as that key remains strongly reachable elsewhere. If guaranteed retention is 089 * required, use {@link #FULL} (the default mode) instead of WEAK for the composite-key caches. 090 */ 091 WEAK, 092 093 /** 094 * Full caching - uses {@link java.util.concurrent.ConcurrentHashMap} for storage. 095 * 096 * <p> 097 * Provides the best performance with lock-free reads and writes. Cached entries 098 * will remain in memory until explicitly removed or the cache is cleared due to 099 * exceeding the maximum size. 100 * 101 * <p> 102 * This is the default and recommended mode for most use cases, offering: 103 * <ul> 104 * <li>Excellent performance with no synchronization overhead for reads 105 * <li>Thread-safe concurrent access 106 * <li>Predictable memory usage (entries stay until evicted) 107 * <li>Suitable for high-concurrency scenarios 108 * </ul> 109 */ 110 FULL; 111 112 // Constant values for parsing 113 private static final String CONST_NONE = "NONE"; 114 private static final String CONST_WEAK = "WEAK"; 115 private static final String CONST_FULL = "FULL"; 116 117 /** 118 * Parses a string value into a {@link CacheMode}. 119 * 120 * <p> 121 * Performs case-insensitive matching against the enum constant names. 122 * 123 * <h5 class='section'>Examples:</h5> 124 * <p class='bjava'> 125 * CacheMode.<jsm>parse</jsm>(<js>"none"</js>); <jc>// Returns NONE</jc> 126 * CacheMode.<jsm>parse</jsm>(<js>"WEAK"</js>); <jc>// Returns WEAK</jc> 127 * CacheMode.<jsm>parse</jsm>(<js>"Full"</js>); <jc>// Returns FULL</jc> 128 * CacheMode.<jsm>parse</jsm>(<jk>null</jk>); <jc>// Returns FULL (default)</jc> 129 * CacheMode.<jsm>parse</jsm>(<js>"invalid"</js>); <jc>// Returns FULL (default)</jc> 130 * </p> 131 * 132 * @param value The string value to parse. Can be <jk>null</jk>. 133 * @return The corresponding {@link CacheMode}, or {@link #FULL} if the value is <jk>null</jk> or invalid. 134 */ 135 public static CacheMode parse(String value) { 136 if (value == null) 137 return FULL; 138 return switch (ucr(value)) { 139 case CONST_NONE -> NONE; 140 case CONST_WEAK -> WEAK; 141 case CONST_FULL -> FULL; 142 default -> FULL; 143 }; 144 } 145}