/* (c) 2014 Open Source Geospatial Foundation - all rights reserved * (c) 2001 - 2013 OpenPlans * This code is licensed under the GPL 2.0 license, available at the root * application directory. */ package org.geoserver.gwc.layer; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkState; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Set; import java.util.TreeSet; import java.util.logging.Level; import java.util.logging.Logger; import javax.annotation.Nullable; import org.geoserver.catalog.LayerInfo; import org.geoserver.catalog.StyleInfo; import org.geotools.util.logging.Logging; import org.geowebcache.filter.parameters.ParameterException; import org.geowebcache.filter.parameters.ParameterFilter; import com.google.common.base.Preconditions; import com.google.common.collect.Sets; import com.thoughtworks.xstream.annotations.XStreamAlias; /** * ParameterFilter which allows the styles of the back end layer as legal values. Maintains a set * of allowed layers which are intersected with those available on the layer. The default specified * by the layer can be overridden and will be expended to its name rather than left null. * * @author Kevin Smith, OpenGeo * */ @XStreamAlias("styleParameterFilter") public class StyleParameterFilter extends ParameterFilter { private static final Logger LOGGER = Logging.getLogger(GeoServerTileLayerInfoImpl.class); private Set<String> allowedStyles; // The following two fields are omitted from REST private Set<String> availableStyles; private String defaultStyle; /** serialVersionUID */ private static final long serialVersionUID = 1L; /** * Check that setLayer has been called */ protected void checkInitialized(){ checkState(availableStyles!=null, "Current styles of layer not available."); } public StyleParameterFilter(){ super("STYLES"); } @Override public String getDefaultValue() { checkInitialized(); String name = super.getDefaultValue(); if(name.isEmpty()) { // Default is not set so use the default from the layer if(defaultStyle==null) return ""; return defaultStyle; } else { // Default is set so use it return name; } } @Override public boolean applies(String parameterValue) { checkInitialized(); return parameterValue==null || getLegalValues().contains(parameterValue); } @Override public String apply(String str) throws ParameterException { checkInitialized(); if(str == null || str.isEmpty()) { // Use the default return getDefaultValue(); } else { for(String value: getLegalValues()){ // Find a matching style if (value.equalsIgnoreCase(str)) { return value; } } // no match so fail throw new ParameterException(str); } } @Override public void setKey(String key) { checkArgument(key.equalsIgnoreCase("STYLES")); } @Override public void setDefaultValue(String defaultValue) { if(defaultValue==null) defaultValue=""; if(!defaultValue.isEmpty() && availableStyles!=null && !availableStyles.contains(defaultValue)) { LOGGER.log(Level.WARNING, "Selected default style "+defaultValue+" is not in the available styles "+availableStyles+"."); } super.setDefaultValue(defaultValue); } /** * Returns the default style name, or an empty string if set to use the layer specified default * */ public String getRealDefault() { // Bypass the special processing this class normally does on the default value return super.getDefaultValue(); } /** * @see StyleParameterFilter#setDefaultValue() * @param s */ public void setRealDefault(String s) { // Just use the regular set method setDefaultValue(s); } @Override public StyleParameterFilter clone() { StyleParameterFilter clone = new StyleParameterFilter(); clone.setDefaultValue(super.getDefaultValue()); // Want to get the configured value so use super clone.setKey(getKey()); clone.allowedStyles = getStyles(); clone.availableStyles = availableStyles; clone.defaultStyle = defaultStyle; return clone; } /** * Get the names of all the styles supported by the layer * */ public Set<String> getLayerStyles() { checkInitialized(); return availableStyles; } @Override public List<String> getLegalValues() { checkInitialized(); Set<String> layerStyles = getLayerStyles(); if (allowedStyles==null) { // Values is null so allow any of the backing layer's styles return new ArrayList<String>(layerStyles); } else { // Values is set so only allow the intersection of the specified styles and those of the backing layer. return new ArrayList<String>(Sets.intersection(layerStyles, allowedStyles)); } } /** * Set/update the availableStyles and defaultStyle based on the given GeoServer layer. * * @param layer */ public void setLayer(LayerInfo layer) { availableStyles = new TreeSet<String>(); for(StyleInfo style: layer.getStyles()) { availableStyles.add(style.prefixedName()); } if(layer.getDefaultStyle() !=null) { defaultStyle = layer.getDefaultStyle().prefixedName(); } else { defaultStyle = null; } } /** * Get the styles. * @return The set of specified styles, or {@literal null} if all styles are allowed. */ @Nullable public Set<String> getStyles() { if(allowedStyles==null) return null; return Collections.unmodifiableSet(allowedStyles); } /** * Set the allowed styles. {@code null} to allow all styles available on the layer. * @param styles */ public void setStyles(@Nullable Set<String> styles) { if(styles==null) { this.allowedStyles=null; } else { this.allowedStyles = new TreeSet<String>(styles); } } @Override protected ParameterFilter readResolve() { super.readResolve(); Preconditions.checkState(this.getKey().equalsIgnoreCase("STYLES"), "StyleParameterFilter must have a key of \"STYLES\""); return this; } }