001package org.apache.commons.jcs3.access;
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.Set;
024import java.util.stream.Collectors;
025
026import org.apache.commons.jcs3.access.behavior.IGroupCacheAccess;
027import org.apache.commons.jcs3.access.exception.CacheException;
028import org.apache.commons.jcs3.access.exception.InvalidArgumentException;
029import org.apache.commons.jcs3.engine.CacheElement;
030import org.apache.commons.jcs3.engine.behavior.ICacheElement;
031import org.apache.commons.jcs3.engine.behavior.IElementAttributes;
032import org.apache.commons.jcs3.engine.control.CompositeCache;
033import org.apache.commons.jcs3.engine.control.group.GroupAttrName;
034import org.apache.commons.jcs3.engine.control.group.GroupId;
035
036/**
037 * Access for groups.
038 */
039public class GroupCacheAccess<K, V>
040    extends AbstractCacheAccess<GroupAttrName<K>, V>
041    implements IGroupCacheAccess<K, V>
042{
043    /**
044     * Constructor for the GroupCacheAccess object
045     * <p>
046     * @param cacheControl
047     */
048    public GroupCacheAccess( final CompositeCache<GroupAttrName<K>, V> cacheControl )
049    {
050        super(cacheControl);
051    }
052
053    /**
054     * Gets an item out of the cache that is in a specified group.
055     * <p>
056     * @param name
057     *            The key name.
058     * @param group
059     *            The group name.
060     * @return The cached value, null if not found.
061     */
062    @Override
063    public V getFromGroup( final K name, final String group )
064    {
065        final ICacheElement<GroupAttrName<K>, V> element = this.getCacheControl().get( getGroupAttrName( group, name ) );
066        return ( element != null ) ? element.getVal() : null;
067    }
068
069    /**
070     * Internal method used for group functionality.
071     * <p>
072     * @param group
073     * @param name
074     * @return GroupAttrName
075     */
076    private GroupAttrName<K> getGroupAttrName( final String group, final K name )
077    {
078        final GroupId gid = new GroupId( this.getCacheControl().getCacheName(), group );
079        return new GroupAttrName<>( gid, name );
080    }
081
082    /**
083     * Allows the user to put an object into a group within a particular cache
084     * region. This method sets the object's attributes to the default for the
085     * region.
086     * <p>
087     * @param name
088     *            The key name.
089     * @param groupName
090     *            The group name.
091     * @param value
092     *            The object to cache
093     * @throws CacheException
094     */
095    @Override
096    public void putInGroup( final K name, final String groupName, final V value )
097        throws CacheException
098    {
099        putInGroup( name, groupName, value, null );
100    }
101
102    /**
103     * Allows the user to put an object into a group within a particular cache
104     * region. This method allows the object's attributes to be individually
105     * specified.
106     * <p>
107     * @param name
108     *            The key name.
109     * @param groupName
110     *            The group name.
111     * @param value
112     *            The object to cache
113     * @param attr
114     *            The objects attributes.
115     * @throws CacheException
116     */
117    @Override
118    public void putInGroup( final K name, final String groupName, final V value, final IElementAttributes attr )
119        throws CacheException
120    {
121        if ( name == null )
122        {
123            throw new InvalidArgumentException( "Key must not be null" );
124        }
125
126        if ( value == null )
127        {
128            throw new InvalidArgumentException( "Value must not be null" );
129        }
130
131        // Create the element and update. This may throw an IOException which
132        // should be wrapped by cache access.
133        try
134        {
135            final GroupAttrName<K> key = getGroupAttrName( groupName, name );
136            final CacheElement<GroupAttrName<K>, V> ce =
137                new CacheElement<>( this.getCacheControl().getCacheName(), key, value );
138
139            final IElementAttributes attributes = (attr == null) ? this.getCacheControl().getElementAttributes() : attr;
140            ce.setElementAttributes( attributes );
141
142            this.getCacheControl().update( ce );
143        }
144        catch ( final IOException e )
145        {
146            throw new CacheException( e );
147        }
148
149    }
150
151    /**
152     * Removes a single item by name from a group.
153     *
154     * @param name
155     * @param group
156     */
157    @Override
158    public void removeFromGroup( final K name, final String group )
159    {
160        final GroupAttrName<K> key = getGroupAttrName( group, name );
161        this.getCacheControl().remove( key );
162    }
163
164    /**
165     * Gets the set of keys of objects currently in the group.
166     * <p>
167     * @param group
168     * @return A Set of keys.
169     */
170    @Override
171    public Set<K> getGroupKeys( final String group )
172    {
173        final GroupId groupId = new GroupId( this.getCacheControl().getCacheName(), group );
174
175        return this.getCacheControl().getKeySet()
176                .stream()
177                .filter(gan -> gan.groupId.equals(groupId))
178                .map(gan -> gan.attrName)
179                .collect(Collectors.toSet());
180    }
181
182    /**
183     * Gets the set of group names in the cache
184     * <p>
185     * @return A Set of group names.
186     */
187    public Set<String> getGroupNames()
188    {
189        return this.getCacheControl().getKeySet()
190                .stream()
191                .map(gan -> gan.groupId.groupName)
192                .collect(Collectors.toSet());
193    }
194
195    /**
196     * Invalidates a group: remove all the group members
197     * <p>
198     * @param group
199     *            The name of the group to invalidate
200     */
201    @Override
202    public void invalidateGroup( final String group )
203    {
204        this.getCacheControl().remove(getGroupAttrName(group, null));
205    }
206}