org.geowebcache.storage.BlobStore.java Source code

Java tutorial

Introduction

Here is the source code for org.geowebcache.storage.BlobStore.java

Source

/**
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * @author Arne Kepp / The Open Planning Project 2009
 *  
 */
package org.geowebcache.storage;

import java.io.UncheckedIOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.geowebcache.filter.parameters.ParameterFilter;
import org.geowebcache.filter.parameters.ParametersUtils;
import org.geowebcache.layer.TileLayer;

/**
 * Manages the persistence of the actual data contained in cacheable objects (tiles, WFS responses).
 * <p>
 * Blobstores may assume that the StorageObjects passed to them are completely filled in except for
 * the blob fields.
 * </p>
 */
public interface BlobStore {
    static Log log = LogFactory.getLog(BlobStore.class);

    /**
     * Delete the cache for the named layer
     * 
     * @param layerName the name of the layer to delete
     * @return {@literal true} if successful, {@literal false} otherwise
     */
    public boolean delete(String layerName) throws StorageException;

    /**
     * Delete the cache for the named gridset and layer
     * 
     * @param layerName
     * @param gridSetId
     * @return {@literal true} if successful, {@literal false} otherwise
     * @throws StorageException
     */
    public boolean deleteByGridsetId(final String layerName, final String gridSetId) throws StorageException;

    /**
     * Delete the cache for the named layer and parameters.
     * 
     * @param layerName
     * @param parameters Complete filtered parameters to generate the ID
     * @return {@literal true} if successful, {@literal false} otherwise
     * @throws StorageException
     */
    public default boolean deleteByParameters(final String layerName, final Map<String, String> parameters)
            throws StorageException {
        return deleteByParametersId(layerName, ParametersUtils.getId(parameters));
    }

    /**
     * Delete the cache for the named layer and parameters id.
     * 
     * @param layerName
     * @param parameters
     * @return {@literal true} if successful, {@literal false} otherwise
     * @throws StorageException
     */
    public boolean deleteByParametersId(final String layerName, String parametersId) throws StorageException;

    /**
     * Delete the cached blob associated with the specified TileObject.
     * The passed in object itself will not be modified.
     * 
     * @param obj
     * @return {@literal true} if successful, {@literal false} otherwise
     * @throws StorageException
     */
    public boolean delete(TileObject obj) throws StorageException;

    /**
     * Delete the cached blob associated with the tiles in the given range.
     * 
     * @param obj the range of tiles.
     * @return {@literal true} if successful, {@literal false} otherwise
     * @throws StorageException
     */
    public boolean delete(TileRange obj) throws StorageException;

    /**
     * Retrieves a tile from the storage, filling its metadata too
     * @param obj
     * @return {@literal true} if successful, {@literal false} otherwise
     * @throws StorageException
     */
    public boolean get(TileObject obj) throws StorageException;

    /**
     * Store blob. Calls getBlob() on passed object, does not modify the object.
     * 
     * @param key
     * @param blog
     * @throws StorageException
     */
    public void put(TileObject obj) throws StorageException;

    /**
     * Wipes the entire storage. Should only be invoked during testing.
     * 
     * @throws StorageException
     */
    @Deprecated
    public void clear() throws StorageException;

    /**
     * Destroy method for Spring
     */
    public void destroy();

    /**
     * Add an event listener 
     * @param listener
     * @see BlobStoreListener
     */
    public void addListener(BlobStoreListener listener);

    /**
     * Remove an event listener
     * @param listener
     * @return {@literal true} if successful, {@literal false} otherwise
     * @see BlobStoreListener
     */
    public boolean removeListener(BlobStoreListener listener);

    /**
     * Get the cached parameter maps for a layer
     * @param layerName
     * @return
     */
    public default Set<Map<String, String>> getParameters(String layerName) throws StorageException {
        return getParametersMapping(layerName).values().stream().filter(Optional::isPresent).map(Optional::get)
                .collect(Collectors.toSet());
    }

    /**
     * Get the IDs of the cached parameter maps for a layer. 
     * 
     * <p>Stores that predate 1.12 should implement this to provide any parameters for which maps
     * are not available.  Stores not using {@link ParametersUtils.getId} or which have more 
     * efficient ways to provide it should also implement it.
     * @param layerName
     * @return
     */
    public default Set<String> getParameterIds(String layerName) throws StorageException {
        return getParametersMapping(layerName).keySet();
    }

    /**
     * Rename a stored layer
     * @param oldLayerName the old name of the layer
     * @param newLayerName the new name
     * @return {@literal true} if successful or the layer didn't exist, {@literal false} otherwise
     * @throws StorageException if {@code newLayerName} already exists or the rename can't be accomplished for other reason
     */
    public boolean rename(String oldLayerName, String newLayerName) throws StorageException;

    /**
     * @return the value of the stored metadata for the given layer and key, or {@code null} if no
     *         such value exists
     */
    public String getLayerMetadata(String layerName, String key);

    /**
     * Stores a metadata key/value pair for the given layer
     */
    public void putLayerMetadata(String layerName, String key, String value);

    /**
     * @return {@code true} if the blobstore has a layer named {@code layerName}
     *         in use, {@code false} otherwise
     */
    public boolean layerExists(String layerName);

    /**
     * Gets the mapping from parameter IDs to parameter maps.  For cache parameter IDs that lack 
     * reverse mappings (as produced by GWC before 1.12) the ID will map to an empty 
     * {@link Optional}.
     * @param layerName The layer to look up.
     * @return A map from parameter IDs to {@link Optional}s containing parameter maps, or empty 
     *          {@link Optional}s.
     * @since 1.12
     */
    Map<String, Optional<Map<String, String>>> getParametersMapping(String layerName);

    /**
     * If the given layer is cached, remove 
     * @param layer
     * @throws StorageException
     */
    public default boolean purgeOrphans(TileLayer layer) throws StorageException {
        // TODO maybe do purging based on gridset and format
        try {
            final List<ParameterFilter> parameterFilters = layer.getParameterFilters();

            // Given known parameter mapping, figures out if the parameters need to be purged
            final Function<Map<String, String>, Boolean> parametersNeedPurge = parameters -> {
                return parameters.size() != parameterFilters.size() || // Should have the same number of parameters as the layer has filters
                parameterFilters.stream().allMatch(pfilter -> { // Do all the parameter filters on the layer consider their parameter legal
                    final String key = pfilter.getKey();
                    final String value = parameters.get(key);
                    if (Objects.isNull(value)) {
                        return true; // No parameter for this filter so purge
                    }
                    return !pfilter.isFilteredValue(value); // purge if it's not a filtered value
                });
            };

            return getParametersMapping(layer.getName()).entrySet().stream().filter(parameterMapping -> {
                return parameterMapping.getValue().map(parametersNeedPurge).orElse(true); // Don't have the original values so purge
            }).map(Map.Entry::getKey) // The parameter id
                    .map(id -> {
                        try {
                            return this.deleteByParametersId(layer.getName(), id);
                        } catch (StorageException e) {
                            throw new UncheckedIOException(e);
                        }
                    }).reduce((x, y) -> x || y) // OR results without short circuiting
                    .orElse(false);
        } catch (UncheckedIOException ex) {
            if (ex.getCause() instanceof StorageException) {
                throw (StorageException) ex.getCause();
            } else {
                throw ex;
            }
        }
    }

    // /**
    // * Test to see whether the blobstore is ready or not
    // */
    // public boolean isReady();
}