package org.gcube.portlets.user.geoportaldataviewer.server.gis; import org.gcube.application.geoportalcommon.shared.gis.BoundsMap; import org.gcube.application.geoportalcommon.util.URLParserUtil; import org.gcube.portlets.user.geoportaldataviewer.server.gis.MapServerRecognize.SERVERTYPE; import org.gcube.portlets.user.geoportaldataviewer.shared.gis.LayerItem; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * The Class URLMakers. * * @author Francesco Mangiacrapa at ISTI-CNR (francesco.mangiacrapa@isti.cnr.it) * * Oct 29, 2020 */ public class GisMakers { public static final String CQL_FILTER_PARAMETER = "CQL_FILTER"; // MAP SERVER PIVOT public static final String WXS = "wxs"; // GEOSERVER PIVOT public static final String WMS = "/wms"; // OUTPUT FORMAT public static final String CSV = "csv"; public static final String JSON = "json"; private static String[][] a = { { "\\?", "%3F" }, { "&", "%26" }, }; private static final Logger LOG = LoggerFactory.getLogger(GisMakers.class); /** * The Enum COORDINATE_FORMAT. * * @author Francesco Mangiacrapa at ISTI-CNR (francesco.mangiacrapa@isti.cnr.it) * * Oct 29, 2020 */ public static enum COORDINATE_FORMAT { XY, YX }; /** * Builds the WFS feature query. * * @param layerItem the layer item * @param mapSrsName the map srs name * @param mapBBOX the map BBOX * @param maxFeatures the max features * @param outputFormat the output format * @return the string */ public static String buildWFSFeatureQuery(LayerItem layerItem, String mapSrsName, BoundsMap mapBBOX, int maxFeatures, String outputFormat) { String link = layerItem.getMapServerHost(); LOG.debug("Map server host URL: " + link); LOG.debug("CQL filter is: " + layerItem.getCqlFilter()); LOG.debug("MAX FEATURES: " + maxFeatures); String outputformat = null; String boundingBox = ""; // CASE MAP SERVER SERVERTYPE mapserverType = MapServerRecognize.recongnize(layerItem); LOG.debug("Recongnized SERVERTYPE: " + mapserverType); if (mapserverType != null) { if (mapserverType.equals(SERVERTYPE.MAPSERVER)) { LOG.debug("wms url contains wxs is a map server? no appending /wfs "); outputformat = MapServerRecognize.outputFormatRecognize(SERVERTYPE.MAPSERVER, outputFormat); boundingBox = BBOX_FORMAT(COORDINATE_FORMAT.YX, ",",mapBBOX.getLowerLeftX(),mapBBOX.getLowerLeftY(),mapBBOX.getUpperRightX(),mapBBOX.getUpperRightY()); // USE AXIS XY // TODO DEBUG LOG.debug("SERVERTYPE.MAPSERVER outputformat: " + outputformat); LOG.debug("SERVERTYPE.MAPSERVER srsName: " + mapSrsName); LOG.debug("SERVERTYPE.MAPSERVER boundingBox: " + boundingBox); } else { LOG.debug("is geoserver appending suffix /wfs if is not present"); link += link.endsWith("wfs") ? "" : "/wfs"; outputformat = MapServerRecognize.outputFormatRecognize(SERVERTYPE.GEOSEVER, outputFormat); mapSrsName = "urn:x-ogc:def:crs:"+mapSrsName; boundingBox = BBOX_FORMAT(COORDINATE_FORMAT.YX, ",",mapBBOX.getLowerLeftX(),mapBBOX.getLowerLeftY(),mapBBOX.getUpperRightX(),mapBBOX.getUpperRightY()); // USE AXIS XY // TODO DEBUG LOG.debug("SERVERTYPE.GEOSEVER outputformat: " + outputformat); LOG.debug("SERVERTYPE.GEOSEVER srsName: " + mapSrsName); } } // // link += "?service=wfs&version=1.1.0" + "&REQUEST=GetFeature" + "&srsName=" + srsName + "&TYPENAME=" // + layerItem.getName() + (limit == 0 ? "" : "&MAXFEATURES=" + limit) // + (outputformat == null ? "" : "&OUTPUTFORMAT=" + outputformat); // link += "?"+ URLParserUtil.addParameterToQueryString(WFSGetFeature.SERVICE.getParameter(), WFSGetFeature.SERVICE.getValue(), false, true)+ URLParserUtil.addParameterToQueryString(WFSGetFeature.VERSION.getParameter(), WFSGetFeature.VERSION.getValue(), false, true)+ URLParserUtil.addParameterToQueryString(WFSGetFeature.REQUEST.getParameter(), WFSGetFeature.REQUEST.getValue(), false, true)+ URLParserUtil.addParameterToQueryString(WFSGetFeature.SRSNAME.getParameter(), mapSrsName, false, true)+ URLParserUtil.addParameterToQueryString(WFSGetFeature.TYPENAME.getParameter(), layerItem.getName(), false, true)+ (maxFeatures == 0 ? "" : URLParserUtil.addParameterToQueryString(WFSGetFeature.MAXFEATURES.getParameter(), maxFeatures+"", false, true))+ (outputformat == null ? "" : URLParserUtil.addParameterToQueryString(WFSGetFeature.OUTPUTFORMAT.getParameter(), outputformat, false, false)); if (layerItem.getCqlFilter() != null && !layerItem.getCqlFilter().isEmpty()) { if (layerItem.getCqlFilter().contains("BBOX(the_geom")) { // THE BBOX IS ALREADY USED INTO CQL FILTERING, SO USING IT DIRECTLY link += "&" + CQL_FILTER_PARAMETER + "=" + layerItem.getCqlFilter(); } else { // I NEED TO ENCODE THE BBOX INTO CQL FILTERING, String cqlFilterValue = "BBOX(the_geom," + boundingBox + ")" + " AND " + layerItem.getCqlFilter(); link += "&" + CQL_FILTER_PARAMETER + "=" + cqlFilterValue; } } else { // NO CQL FILTERING APPLIED link += (boundingBox == null ? "" : "&BBOX=" + boundingBox); } LOG.info("WFS: " + link); return link; } /** * Encode url. * * @param url the url * @return the string */ public static String encodeUrl(String url) { String urlNew = url; for (String[] s : a) { urlNew = urlNew.replaceAll(s[0], s[1]); } return urlNew; } /** * Decode url. * * @param url the url * @return the string */ public static String decodeUrl(String url) { String urlNew = url; for (String[] s : a) { urlNew = urlNew.replaceAll(s[1], s[0]); } return urlNew; } /** * Removes the last char. * * @param string the string * @return the string */ public static String removeLastChar(String string) { if (string == null) return null; if (string.length() > 0) return string.substring(0, string.length() - 1); return string; } /** * Format. * * @param format the format * @param separator the separator * @return the string */ public static String BBOX_FORMAT(COORDINATE_FORMAT format, String separator, double lowerLeftX, double lowerLeftY, double upperRightX, double upperRightY) { if(format==null) format = COORDINATE_FORMAT.XY; if(separator==null) separator = ","; switch (format) { case XY: return String.format("%s%s%s%s%s%s%s", String.valueOf(lowerLeftX), separator, String.valueOf(lowerLeftY), separator, String.valueOf(upperRightX), separator, String.valueOf(upperRightY) ); case YX: return String.format("%s%s%s%s%s%s%s", String.valueOf(lowerLeftY), separator, String.valueOf(lowerLeftX), separator, String.valueOf(upperRightY), separator, String.valueOf(upperRightX) ); } return null; } }