/* * Constellation - An open source and standard compliant SDI * http://www.constellation-sdi.org * * Copyright 2014 Geomatys. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.constellation.json.util; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.vividsolutions.jts.geom.Geometry; import com.vividsolutions.jts.geom.LineString; import com.vividsolutions.jts.geom.LinearRing; import com.vividsolutions.jts.geom.MultiLineString; import com.vividsolutions.jts.geom.MultiPoint; import com.vividsolutions.jts.geom.MultiPolygon; import com.vividsolutions.jts.geom.Point; import com.vividsolutions.jts.geom.Polygon; import org.apache.sis.util.Static; import org.apache.sis.util.logging.Logging; import org.constellation.dto.BandDescription; import org.constellation.dto.CoverageDataDescription; import org.constellation.dto.DataDescription; import org.constellation.dto.FeatureDataDescription; import org.constellation.dto.PropertyDescription; import org.constellation.json.binding.ChannelSelection; import org.constellation.json.binding.DynamicRangeSymbolizer; import org.constellation.json.binding.LineSymbolizer; import org.constellation.json.binding.PointSymbolizer; import org.constellation.json.binding.PolygonSymbolizer; import org.constellation.json.binding.RasterSymbolizer; import org.constellation.json.binding.Rule; import org.constellation.json.binding.SelectedChannelType; import org.constellation.json.binding.Style; import org.constellation.json.binding.StyleElement; import org.constellation.json.binding.Symbolizer; import org.geotoolkit.cql.CQL; import org.geotoolkit.cql.CQLException; import org.geotoolkit.filter.visitor.DuplicatingFilterVisitor; import org.opengis.filter.Filter; import org.opengis.filter.expression.Expression; import org.opengis.filter.expression.NilExpression; import java.awt.*; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import static org.constellation.json.util.StyleFactories.FF; /** * @author Fabien Bernard (Geomatys). * @version 0.9 * @since 0.9 */ public final class StyleUtilities extends Static { private static final Logger LOGGER = Logging.getLogger("org.constellation.json.util"); /** * Parse given string as CQL and returns Expression. * @param exp * @return */ public static Expression parseExpression(final String exp) { try{ return CQL.parseExpression(exp); } catch (CQLException ex) { return Expression.NIL; } } /** * Convert expression to String CQL * if exp is NilExpression then returns empty string because NilExpression is not supported by CQL * @param exp {Expression exp} * @return {String} */ public static String toCQL(final Expression exp) { if(exp instanceof NilExpression) { return ""; } else { return CQL.write(exp); } } /** * Convert filter to String CQL. * if the filter contains NilExpression then return null literal because Nil is not supported by CQL * @param f {Filter} * @return {String} */ public static String toCQL(Filter f) { f = (Filter) f.accept(new NoNilFilter(),null); return CQL.write(f); } public static Expression opacity(final double opacity) { return (opacity >= 0 && opacity <= 1.0) ? FF.literal(opacity) : Expression.NIL; } public static Expression literal(final Object value) { return value != null ? FF.literal(value) : Expression.NIL; } public static <T> T type(final StyleElement<T> elt) { return elt != null ? elt.toType() : null; } public static <T> List<T> singletonType(final StyleElement<T> elt) { return elt != null ? Collections.singletonList(elt.toType()) : new ArrayList<T>(0); } public static <T> List<T> listType(final List<? extends StyleElement<T>> elts) { final List<T> list = new ArrayList<T>(); if (elts == null) { return list; } for (final StyleElement<T> elt : elts) { list.add(elt.toType()); } return list; } public static Filter filter(final String filter) { if (filter == null) { return null; } try { return CQL.parseFilter(filter); } catch (CQLException ex) { LOGGER.log(Level.WARNING, "An error occurred during filter parsing.", ex); } return null; } public static String writeJson(final Object object) throws JsonProcessingException { final ObjectMapper mapper = new ObjectMapper(); return mapper.writeValueAsString(object); } public static <T> T readJson(final String json, final Class<T> clazz) throws IOException { final ObjectMapper mapper = new ObjectMapper(); return mapper.readValue(json, clazz); } public static String toHex(final Color color) { String redCode = Integer.toHexString(color.getRed()); String greenCode = Integer.toHexString(color.getGreen()); String blueCode = Integer.toHexString(color.getBlue()); if (redCode.length() == 1) redCode = "0" + redCode; if (greenCode.length() == 1) greenCode = "0" + greenCode; if (blueCode.length() == 1) blueCode = "0" + blueCode; int alpha = color.getAlpha(); if(alpha != 255){ String alphaCode = Integer.toHexString(alpha); if (alphaCode.length() == 1) alphaCode = "0" + alphaCode; return "#" + alphaCode + redCode + greenCode + blueCode; }else{ return "#" + redCode + greenCode + blueCode; } } public static final Symbolizer DEFAULT_POINT_SYMBOLIZER = new PointSymbolizer(); public static final Symbolizer DEFAULT_LINE_SYMBOLIZER = new LineSymbolizer(); public static final Symbolizer DEFAULT_POLYGON_SYMBOLIZER = new PolygonSymbolizer(); public static final RasterSymbolizer DEFAULT_GREY_RASTER_SYMBOLIZER = new RasterSymbolizer(); public static final RasterSymbolizer DEFAULT_RGB_RASTER_SYMBOLIZER = new RasterSymbolizer(); public static final DynamicRangeSymbolizer DEFAULT_RGB_DYNAMICRANGE_SYMBOLIZER = new DynamicRangeSymbolizer(); static { final ChannelSelection rgbSelection = new ChannelSelection(); final SelectedChannelType red = new SelectedChannelType(); final SelectedChannelType green = new SelectedChannelType(); final SelectedChannelType blue = new SelectedChannelType(); red.setName("0"); green.setName("1"); blue.setName("2"); rgbSelection.setRgbChannels(new SelectedChannelType[]{red, green, blue}); DEFAULT_RGB_RASTER_SYMBOLIZER.setChannelSelection(rgbSelection); final ChannelSelection greySelection = new ChannelSelection(); final SelectedChannelType grey = new SelectedChannelType(); grey.setName("0"); greySelection.setGreyChannel(grey); DEFAULT_GREY_RASTER_SYMBOLIZER.setChannelSelection(greySelection); } public static Style createDefaultStyle(final DataDescription dataDescription) { // Create a default rule. final Rule rule = new Rule(); rule.setName("Default"); // Create a default style; final Style style = new Style(); style.getRules().add(rule); // Feature data. if (dataDescription instanceof FeatureDataDescription) { final PropertyDescription geometryProp = ((FeatureDataDescription) dataDescription).getGeometryProperty(); final Symbolizer symbolizer; if (geometryProp != null) { if (isAssignableToPolygon(geometryProp.getType())) { symbolizer = DEFAULT_POLYGON_SYMBOLIZER; } else if (isAssignableToLine(geometryProp.getType())) { symbolizer = DEFAULT_LINE_SYMBOLIZER; } else { symbolizer = DEFAULT_POINT_SYMBOLIZER; } } else { symbolizer = DEFAULT_POINT_SYMBOLIZER; } rule.getSymbolizers().add(symbolizer); } // Coverage data. else if (dataDescription instanceof CoverageDataDescription) { final List<BandDescription> bands = ((CoverageDataDescription) dataDescription).getBands(); final Symbolizer symbolizer; if (bands.size() >= 3) { symbolizer = DEFAULT_RGB_RASTER_SYMBOLIZER; } else { symbolizer = DEFAULT_GREY_RASTER_SYMBOLIZER; } rule.getSymbolizers().add(symbolizer); } // Undefined else { rule.getSymbolizers().add(DEFAULT_GREY_RASTER_SYMBOLIZER); rule.getSymbolizers().add(DEFAULT_POINT_SYMBOLIZER); } // Return generated style. return style; } /** * Determines if the {@link Class} passed in arguments is assignable * to a JTS {@link Geometry}. * * @param clazz the {@link Class} * @return {@code true} if the class is assignable to the expected type */ public static boolean isAssignableToGeometry(final Class<?> clazz) { return Geometry.class.isAssignableFrom(clazz); } /** * Determines if the {@link Class} passed in arguments is assignable * to a JTS polygon {@link Geometry}. * * @param clazz the {@link Class} to test * @return {@code true} if the class is assignable to the expected type */ public static boolean isAssignableToPolygon(final Class<?> clazz) { return Polygon.class.isAssignableFrom(clazz) || MultiPolygon.class.isAssignableFrom(clazz); } /** * Determines if the {@link Class} passed in arguments is assignable * to a JTS line {@link Geometry}. * * @param clazz the {@link Class} * @return {@code true} if the class is assignable to the expected type */ public static boolean isAssignableToLine(final Class<?> clazz) { return LineString.class.isAssignableFrom(clazz) || MultiLineString.class.isAssignableFrom(clazz) || LinearRing.class.isAssignableFrom(clazz); } /** * Determines if the {@link Class} passed in arguments is assignable * to a JTS point {@link Geometry}. * * @param clazz the {@link Class} * @return {@code true} if the class is assignable to the expected type */ public static boolean isAssignableToPoint(final Class<?> clazz) { return Point.class.isAssignableFrom(clazz) || MultiPoint.class.isAssignableFrom(clazz); } private static class NoNilFilter extends DuplicatingFilterVisitor { @Override public Object visit(NilExpression expression, Object extraData) { return ff.literal(null); } } }