/* (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.catalog;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import org.geoserver.platform.GeoServerExtensions;
import org.geotools.factory.CommonFactoryFinder;
import org.geotools.styling.NamedLayer;
import org.geotools.styling.NamedStyle;
import org.geotools.styling.Style;
import org.geotools.styling.StyleFactory;
import org.geotools.styling.StyledLayerDescriptor;
import org.geotools.styling.UserLayer;
import org.geotools.util.Version;
import org.geotools.util.logging.Logging;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
/**
* Provides methods to parse/encode style documents.
*
* @author Justin Deoliveira, OpenGeo
*/
public class Styles {
/** logger */
static Logger LOGGER = Logging.getLogger("org.geoserver.wms");
static StyleFactory styleFactory = CommonFactoryFinder.getStyleFactory(null);
/**
* Encodes the specified SLD as a string.
*
* @param sld The sld to encode.
* @param handler The handler to use to encode.
* @param ver Version of the style to encode, may be <code>null</code>.
* @param pretty Whether to format the style.
*
* @return The encoded style.
*/
public static String string(StyledLayerDescriptor sld, SLDHandler handler, Version ver, boolean pretty)
throws IOException {
ByteArrayOutputStream bout = new ByteArrayOutputStream();
handler.encode(sld, ver, pretty, bout);
return new String(bout.toByteArray());
}
/**
* Convenience method to pull a UserSyle from a StyledLayerDescriptor.
* <p>
* This method will return the first UserStyle it encounters in the StyledLayerDescriptor tree.
* </p>
* @param sld The StyledLayerDescriptor object.
*
* @return The UserStyle, or <code>null</code> if no such style could be found.
*/
public static Style style(StyledLayerDescriptor sld) {
for (int i = 0; i < sld.getStyledLayers().length; i++) {
Style[] styles = null;
if (sld.getStyledLayers()[i] instanceof NamedLayer) {
NamedLayer layer = (NamedLayer) sld.getStyledLayers()[i];
styles = layer.getStyles();
}
else if(sld.getStyledLayers()[i] instanceof UserLayer) {
UserLayer layer = (UserLayer) sld.getStyledLayers()[i];
styles = layer.getUserStyles();
}
if (styles != null) {
for (int j = 0; j < styles.length; j++) {
if (!(styles[j] instanceof NamedStyle)) {
return styles[j];
}
}
}
}
return null;
}
/**
* Convenience method to wrap a UserStyle in a StyledLayerDescriptor object.
* <p>
* This method wraps the UserStyle in a NamedLayer, and wraps the result in a StyledLayerDescriptor.
* </p>
* @param style The UserStyle.
*
* @return The StyledLayerDescriptor.
*/
public static StyledLayerDescriptor sld(Style style) {
StyledLayerDescriptor sld = styleFactory.createStyledLayerDescriptor();
NamedLayer layer = styleFactory.createNamedLayer();
layer.setName(style.getName());
sld.addStyledLayer(layer);
layer.addStyle(style);
return sld;
}
/**
* Looks up a style handler by format, file extension, or mime type.
*
* @param format The format, file extension, or mime type.
*
* @see StyleHandler#getFormat()
* @see StyleHandler#getFileExtension()
* @see StyleHandler#mimeType(org.geotools.util.Version)
*/
public static StyleHandler handler(String format) {
if (format == null) {
throw new IllegalArgumentException("Style format must not be null");
}
List<StyleHandler> allHandlers = handlers();
List<StyleHandler> matches = new ArrayList();
// look by format
for (StyleHandler h : allHandlers) {
if (format.equalsIgnoreCase(h.getFormat())) {
matches.add(h);
}
}
if (matches.isEmpty()) {
// look by mime type
for (StyleHandler h : allHandlers) {
for (Version ver : h.getVersions()) {
if (h.mimeType(ver).equals(format)) {
matches.add(h);
}
}
}
}
if (matches.isEmpty()) {
// look by file extension
for (StyleHandler h : allHandlers) {
if (format.equalsIgnoreCase(h.getFileExtension())) {
matches.add(h);
}
}
}
if (matches.isEmpty()) {
throw new RuntimeException(
"No such style handler: format = " + format);
}
if (matches.size() == 1) {
return matches.get(0);
}
List<String> handlerNames = Lists.transform(matches, new Function<StyleHandler, String>() {
@Nullable
@Override
public String apply(@Nullable StyleHandler styleHandler) {
return styleHandler.getName();
}
});
throw new IllegalArgumentException("Multiple style handlers: " + handlerNames + " found for format: " + format);
}
/**
* Returns all registered style handlers.
*/
public static List<StyleHandler> handlers() {
return GeoServerExtensions.extensions(StyleHandler.class);
}
}