/* (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.wcs2_0.kvp; import net.opengis.wcs20.DimensionSliceType; import net.opengis.wcs20.DimensionSubsetType; import net.opengis.wcs20.DimensionTrimType; import net.opengis.wcs20.Wcs20Factory; import org.geoserver.ows.KvpParser; import org.geoserver.platform.OWS20Exception; import org.geoserver.wcs2_0.exception.WCS20Exception.WCS20ExceptionCode; /** * Parses the WCS 2.0 subset key * * @author Andrea Aime - GeoSolutions */ public class SubsetKvpParser extends KvpParser { public SubsetKvpParser() { super("subset", DimensionSubsetType.class); } @Override public Object parse(String value) throws Exception { // SubsetSpec: dimension [ , crs ] ( intervalOrPoint ) // dimension: NCName // crs: anyURI // intervalOrPoint: interval | point // interval: low , high // low: point | * // high: point | * // point: number | " token " // " = ASCII 0x42 // trim just in case value = value.trim(); // first, locate the intervalOrPoint part int openIdx = value.indexOf("("); int closeIdx = value.indexOf(")"); if (openIdx == -1 || closeIdx == -1 || closeIdx < value.length() - 1) { throw new OWS20Exception("Invalid syntax, dimension [ , crs ] ( intervalOrPoint ) is expected", WCS20ExceptionCode.InvalidEncodingSyntax, "subset"); } // parse the first part, dimension[,crs] String dimension = null; String crs = null; String dimensionCrs = value.substring(0, openIdx); String[] dcElements = dimensionCrs.split("\\s*,\\s*"); if (dcElements.length == 1) { dimension = dcElements[0]; crs = null; } else if (dcElements.length == 2) { dimension = dcElements[0]; crs = dcElements[1]; } else { throw new OWS20Exception("Invalid syntax, dimension [ , crs ] ( intervalOrPoint ) is expected", WCS20ExceptionCode.InvalidEncodingSyntax, "subset"); } // parse the second part, intervalOrPoint String valuePoint = value.substring(openIdx + 1, closeIdx); // split on all commas not contained in quotes String[] vpElements = valuePoint.split(",\\s*(?=([^\"]*\"[^\"]*\")*[^\"]*$)"); if (vpElements.length == 1) { // point String point = parsePoint(vpElements[0], false); DimensionSliceType slice = Wcs20Factory.eINSTANCE.createDimensionSliceType(); slice.setDimension(dimension); slice.setCRS(crs); slice.setSlicePoint(point); return slice; } else if (vpElements.length == 2) { String low = parsePoint(vpElements[0], true); String high = parsePoint(vpElements[1], true); DimensionTrimType trim = Wcs20Factory.eINSTANCE.createDimensionTrimType(); trim.setDimension(dimension); trim.setCRS(crs); trim.setTrimLow(low); trim.setTrimHigh(high); return trim; } else { throw new OWS20Exception("Invalid syntax, dimension [ , crs ] ( intervalOrPoint ) " + "where interval or point has either 1 or two elements", WCS20ExceptionCode.InvalidEncodingSyntax, "subset"); } } private String parsePoint(String point, boolean allowStar) { point = point.trim(); if ("*".equals(point)) { if (allowStar) { // "no" limit return null; } else { throw new OWS20Exception( "Invalid usage of *, it can be used only when specifying an interval", WCS20ExceptionCode.InvalidEncodingSyntax, "subset"); } } else if (point.startsWith("\"") && point.endsWith("\"")) { point = point.substring(1, point.length() - 1); } else { try { // check it is a number Double.parseDouble(point); } catch (NumberFormatException e) { throw new OWS20Exception("Invalid point value " + point + ", it is not a number and it's not between double quotes", WCS20ExceptionCode.InvalidEncodingSyntax, "subset"); } } return point; } }