/*
* GeoTools - The Open Source Java GIS Toolkit
* http://geotools.org
*
* (C) 2017, Open Source Geospatial Foundation (OSGeo)
*
* This library 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;
* version 2.1 of the License.
*
* This library 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
* Lesser General Public License for more details.
*/
package org.geotools.mbstyle;
import org.geotools.mbstyle.layer.MBLayer;
import org.geotools.mbstyle.parse.MBFormatException;
import org.geotools.mbstyle.parse.MBStyleParser;
import org.geotools.styling.FeatureTypeStyle;
import org.geotools.styling.NamedLayer;
import org.geotools.styling.StyledLayer;
import org.geotools.styling.StyledLayerDescriptor;
import org.json.simple.parser.ParseException;
import org.opengis.style.Style;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
* MapBox Style facade offering utility methods for quickly working with JSON and converting to
* {@link StyledLayerDescriptor}.
*
* @author Jody Garnett (Boundless)
*/
public class MapBoxStyle {
/**
* Read in the provided JSON as a {@link StyledLayerDescriptor}.
*
* @param reader
* @return generated style
*/
public static StyledLayerDescriptor parse(Reader reader) throws IOException, ParseException {
MBStyleParser parser = new MBStyleParser();
MBStyle style = parser.parse(reader);
StyledLayerDescriptor sld = style.transform();
return sld;
}
/**
* Read in the provided JSON as a {@link StyledLayerDescriptor}.
*
* @param stream
* @return generated style
*/
public static StyledLayerDescriptor parse(InputStream stream) throws IOException, ParseException {
MBStyleParser parser = new MBStyleParser();
MBStyle style = parser.parse(stream);
StyledLayerDescriptor sld = style.transform();
return sld;
}
/**
* Validate ability to read json, and parse each layer.
* @param reader Reader for reading the style
* @return List of parse exceptions found. If this list is empty, the style is valid.
*/
public static List<Exception> validate(Reader reader) {
List<Exception> problems = new ArrayList<Exception>();
MBStyleParser parser = new MBStyleParser();
MBStyle style;
try {
style = parser.parse(reader);
} catch (Exception invalid) {
problems.add( invalid );
return problems;
}
List<MBLayer> layers = Collections.emptyList();
try {
layers = style.layers();
if (layers.isEmpty()) {
problems.add( new MBFormatException("No layers defined"));
}
}
catch (MBFormatException layersUnavailable){
problems.add( layersUnavailable );
}
boolean hasVisibleLayer = false;
for (MBLayer layer : layers) {
if (!layer.visibility()) {
continue;
}
try {
List<FeatureTypeStyle> featureTypeStyle = layer.transform(style);
if (featureTypeStyle != null) {
hasVisibleLayer = true;
}
} catch (Exception invalid) {
problems.add((MBFormatException) new MBFormatException(
"Layer " + layer.getId() + ":" + invalid.getMessage()).initCause(invalid));
return problems;
}
}
if (!hasVisibleLayer) {
problems.add( new MBFormatException("No layers were visible"));
}
else {
try {
StyledLayerDescriptor sld = style.transform();
// quick sanity check on results sld files
// if we get any problems downstream in rendering add additional checks here
if( sld.getStyledLayers().length == 0 ){
problems.add(new MBFormatException("Generated sld for "+sld.getName()+" is empty."));
}
else {
for( StyledLayer layer : sld.getStyledLayers()){
if( layer instanceof NamedLayer ){
NamedLayer named = (NamedLayer) layer;
if( named.styles().isEmpty() ){
problems.add(new MBFormatException("Generated named layer for "+named.getName()+" is empty."));
}
else {
for( Style layerStyle : named.styles()){
if( layerStyle instanceof FeatureTypeStyle){
FeatureTypeStyle fts = (FeatureTypeStyle) layerStyle;
if( fts.rules().isEmpty()){
problems.add(new MBFormatException("Generated feature type style "+fts.getName()+" is empty."));
}
}
}
}
}
}
}
} catch (MBFormatException invalid) {
// we could not parse out an sld due to a well-known problem
problems.add(invalid);
} catch (Exception problem) {
// we could not parse out sld due to an unexpected problem
problems.add((MBFormatException) new MBFormatException(
"Style " + style.getName() + ":" + problem.getMessage()).initCause(problem));
}
}
return problems;
}
}