001package org.apache.commons.jcs3.auxiliary;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 *
012 *   http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.io.IOException;
023import java.util.HashMap;
024import java.util.Map;
025import java.util.Objects;
026import java.util.Set;
027import java.util.stream.Collectors;
028
029import org.apache.commons.jcs3.engine.behavior.ICacheElement;
030import org.apache.commons.jcs3.engine.behavior.IElementSerializer;
031import org.apache.commons.jcs3.engine.logging.CacheEvent;
032import org.apache.commons.jcs3.engine.logging.behavior.ICacheEvent;
033import org.apache.commons.jcs3.engine.logging.behavior.ICacheEventLogger;
034import org.apache.commons.jcs3.engine.match.KeyMatcherPatternImpl;
035import org.apache.commons.jcs3.engine.match.behavior.IKeyMatcher;
036import org.apache.commons.jcs3.utils.serialization.StandardSerializer;
037
038/** This holds convenience methods used by most auxiliary caches. */
039public abstract class AbstractAuxiliaryCache<K, V>
040    implements AuxiliaryCache<K, V>
041{
042    /** An optional event logger */
043    private ICacheEventLogger cacheEventLogger;
044
045    /** The serializer. Uses a standard serializer by default. */
046    private IElementSerializer elementSerializer = new StandardSerializer();
047
048    /** Key matcher used by the getMatching API */
049    private IKeyMatcher<K> keyMatcher = new KeyMatcherPatternImpl<>();
050
051    /**
052     * Gets multiple items from the cache based on the given set of keys.
053     *
054     * @param keys
055     * @return a map of K key to ICacheElement&lt;K, V&gt; element, or an empty map if there is no
056     *         data in cache for any of these keys
057     */
058    protected Map<K, ICacheElement<K, V>> processGetMultiple(final Set<K> keys) throws IOException
059    {
060        if (keys != null)
061        {
062            return keys.stream()
063                .map(key -> {
064                    try
065                    {
066                        return get(key);
067                    }
068                    catch (final IOException e)
069                    {
070                        return null;
071                    }
072                })
073                .filter(Objects::nonNull)
074                .collect(Collectors.toMap(
075                        ICacheElement::getKey,
076                        element -> element));
077        }
078
079        return new HashMap<>();
080    }
081
082    /**
083     * Gets the item from the cache.
084     *
085     * @param key
086     * @return ICacheElement, a wrapper around the key, value, and attributes
087     * @throws IOException
088     */
089    @Override
090    public abstract ICacheElement<K, V> get( K key ) throws IOException;
091
092    /**
093     * Logs an event if an event logger is configured.
094     * <p>
095     * @param item
096     * @param eventName
097     * @return ICacheEvent
098     */
099    protected ICacheEvent<K> createICacheEvent( final ICacheElement<K, V> item, final String eventName )
100    {
101        if ( cacheEventLogger == null )
102        {
103            return new CacheEvent<>();
104        }
105        final String diskLocation = getEventLoggingExtraInfo();
106        String regionName = null;
107        K key = null;
108        if ( item != null )
109        {
110            regionName = item.getCacheName();
111            key = item.getKey();
112        }
113        return cacheEventLogger.createICacheEvent( getAuxiliaryCacheAttributes().getName(), regionName, eventName,
114                                                   diskLocation, key );
115    }
116
117    /**
118     * Logs an event if an event logger is configured.
119     * <p>
120     * @param regionName
121     * @param key
122     * @param eventName
123     * @return ICacheEvent
124     */
125    protected <T> ICacheEvent<T> createICacheEvent( final String regionName, final T key, final String eventName )
126    {
127        if ( cacheEventLogger == null )
128        {
129            return new CacheEvent<>();
130        }
131        final String diskLocation = getEventLoggingExtraInfo();
132        return cacheEventLogger.createICacheEvent( getAuxiliaryCacheAttributes().getName(), regionName, eventName,
133                                                   diskLocation, key );
134
135    }
136
137    /**
138     * Logs an event if an event logger is configured.
139     * <p>
140     * @param cacheEvent
141     */
142    protected <T> void logICacheEvent( final ICacheEvent<T> cacheEvent )
143    {
144        if ( cacheEventLogger != null )
145        {
146            cacheEventLogger.logICacheEvent( cacheEvent );
147        }
148    }
149
150    /**
151     * Logs an event if an event logger is configured.
152     * <p>
153     * @param source
154     * @param eventName
155     * @param optionalDetails
156     */
157    protected void logApplicationEvent( final String source, final String eventName, final String optionalDetails )
158    {
159        if ( cacheEventLogger != null )
160        {
161            cacheEventLogger.logApplicationEvent( source, eventName, optionalDetails );
162        }
163    }
164
165    /**
166     * Logs an event if an event logger is configured.
167     * <p>
168     * @param source
169     * @param eventName
170     * @param errorMessage
171     */
172    protected void logError( final String source, final String eventName, final String errorMessage )
173    {
174        if ( cacheEventLogger != null )
175        {
176            cacheEventLogger.logError( source, eventName, errorMessage );
177        }
178    }
179
180    /**
181     * Gets the extra info for the event log.
182     * <p>
183     * @return IP, or disk location, etc.
184     */
185    public abstract String getEventLoggingExtraInfo();
186
187    /**
188     * Allows it to be injected.
189     * <p>
190     * @param cacheEventLogger
191     */
192    @Override
193    public void setCacheEventLogger( final ICacheEventLogger cacheEventLogger )
194    {
195        this.cacheEventLogger = cacheEventLogger;
196    }
197
198    /**
199     * Allows it to be injected.
200     * <p>
201     * @return cacheEventLogger
202     */
203    public ICacheEventLogger getCacheEventLogger()
204    {
205        return this.cacheEventLogger;
206    }
207
208    /**
209     * Allows you to inject a custom serializer. A good example would be a compressing standard
210     * serializer.
211     * <p>
212     * Does not allow you to set it to null.
213     * <p>
214     * @param elementSerializer
215     */
216    @Override
217    public void setElementSerializer( final IElementSerializer elementSerializer )
218    {
219        if ( elementSerializer != null )
220        {
221            this.elementSerializer = elementSerializer;
222        }
223    }
224
225    /**
226     * Allows it to be injected.
227     * <p>
228     * @return elementSerializer
229     */
230    public IElementSerializer getElementSerializer()
231    {
232        return this.elementSerializer;
233    }
234
235    /**
236     * Sets the key matcher used by get matching.
237     * <p>
238     * @param keyMatcher
239     */
240    @Override
241    public void setKeyMatcher( final IKeyMatcher<K> keyMatcher )
242    {
243        if ( keyMatcher != null )
244        {
245            this.keyMatcher = keyMatcher;
246        }
247    }
248
249    /**
250     * Returns the key matcher used by get matching.
251     * <p>
252     * @return keyMatcher
253     */
254    public IKeyMatcher<K> getKeyMatcher()
255    {
256        return this.keyMatcher;
257    }
258}