summaryrefslogtreecommitdiffstats
path: root/petascope/src/petascope/wcs2/server/ops/GetCoverage.java
diff options
context:
space:
mode:
Diffstat (limited to 'petascope/src/petascope/wcs2/server/ops/GetCoverage.java')
-rw-r--r--petascope/src/petascope/wcs2/server/ops/GetCoverage.java529
1 files changed, 0 insertions, 529 deletions
diff --git a/petascope/src/petascope/wcs2/server/ops/GetCoverage.java b/petascope/src/petascope/wcs2/server/ops/GetCoverage.java
deleted file mode 100644
index a6ddcff..0000000
--- a/petascope/src/petascope/wcs2/server/ops/GetCoverage.java
+++ /dev/null
@@ -1,529 +0,0 @@
-/*
- * This file is part of rasdaman community.
- *
- * Rasdaman community is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Rasdaman community 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 General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with rasdaman community. If not, see <http://www.gnu.org/licenses/>.
- *
- * Copyright 2003, 2004, 2005, 2006, 2007, 2008, 2009 Peter Baumann /
- rasdaman GmbH.
- *
- * For more information please see <http://www.rasdaman.org>
- * or contact Peter Baumann via <baumann@rasdaman.com>.
- */
-package petascope.wcs2.server.ops;
-
-//~--- non-JDK imports --------------------------------------------------------
-import org.apache.commons.io.IOUtils;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-
-import org.xml.sax.SAXException;
-
-import petascope.ConfigManager;
-
-import petascope.wcps.server.core.DbMetadataSource;
-import petascope.wcps.server.core.Metadata;
-
-import petascope.wcs.server.exceptions.WCSException;
-
-//~--- JDK imports ------------------------------------------------------------
-
-import java.io.IOException;
-
-import java.math.BigInteger;
-import java.util.HashSet;
-import java.util.Iterator;
-
-import java.util.List;
-import java.util.Set;
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.xpath.XPath;
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathExpressionException;
-import javax.xml.xpath.XPathFactory;
-import org.odmg.DBag;
-import org.odmg.Database;
-import org.odmg.Implementation;
-import org.odmg.ODMGException;
-import org.odmg.OQLQuery;
-import org.odmg.QueryException;
-import org.odmg.Transaction;
-import rasj.RasGMArray;
-import rasj.RasImplementation;
-import petascope.wcps.server.core.CellDomainElement;
-import petascope.wcps.server.core.DomainElement;
-import petascope.wcps.server.core.RangeElement;
-import petascope.wcps.server.core.SDU;
-import petascope.wcs.server.exceptions.InputOutputException;
-import petascope.wcs.server.exceptions.InternalComponentException;
-import petascope.wcs.server.exceptions.InvalidParameterValueException;
-import petascope.wcs.server.exceptions.InvalidServiceConfigurationException;
-import petascope.wcs.server.exceptions.NoApplicableCodeException;
-import petascope.wcs.server.exceptions.WcsRuntimeException;
-import petascope.wcs.server.exceptions.XmlNotValidException;
-import petascope.wcs2.server.templates.WcsNamespaceContext;
-
-/**
- * Get Coverage operation for WCS 2.0
- *
- * @author Andrei Aiordachioaie
- */
-public class GetCoverage implements WcsOperation {
-
- private static Logger LOG = LoggerFactory.getLogger(GetCoverage.class);
- private DocumentBuilder builder = null;
- private XPathFactory xpathFactory = XPathFactory.newInstance();
- /* Template XMLs for response types */
- private String GetCoverageResponse;
- private String rangeComponentTemplate;
- /* Xml request */
- private Document doc;
- /* for Metadata */
- private DbMetadataSource meta;
- /* The new coverage domain */
- private String lowPoint, highPoint, newAxesLabels;
-
- public GetCoverage(DbMetadataSource metadata) throws WCSException {
- meta = metadata;
- GetCoverageResponse = ConfigManager.WCS2_GET_COVERAGE_TEMPLATE;
- if (GetCoverageResponse == null) {
- throw new InvalidServiceConfigurationException("Could not find template file.");
- }
-
- /* Find the RangeField template string */
- String starttag = "<gmlwcs:rangeField", endtag = "</gmlwcs:rangeField>";
- int start = GetCoverageResponse.indexOf(starttag);
- int end = GetCoverageResponse.indexOf(endtag);
- rangeComponentTemplate = GetCoverageResponse.substring(start, end + endtag.length());
- String newTemplate = GetCoverageResponse.substring(0, start - 1) + GetCoverageResponse.substring(end + endtag.length());
- GetCoverageResponse = newTemplate;
-
- /* init XML parser */
- DocumentBuilderFactory domFactory = DocumentBuilderFactory.newInstance();
- domFactory.setNamespaceAware(true); // never forget this!
- try {
- builder = domFactory.newDocumentBuilder();
- } catch (Exception e) {
- throw new NoApplicableCodeException("Error initializing XML parser", e);
- }
- }
-
- @Override
- public String execute(String stringXml) throws WCSException {
- String output;
- Metadata cov;
-
- try {
- doc = builder.parse(IOUtils.toInputStream(stringXml));
- cov = readCoverageMetadata();
- } catch (SAXException e) {
- throw new XmlNotValidException("Could not parse input request.", e);
- } catch (IOException e) {
- throw new InputOutputException("Could not read input request", e);
- } catch (XPathExpressionException e) {
- throw new InternalComponentException("Invalid XPath expression", e);
- }
-
- // Analyze input and build trim/slice info structures
- String subsetting = computeRequestSubsettingLimits(cov);
- String coverageName = cov.getCoverageName();
-
- // Evaluate all bands and then perform string processing to get coverage data
- String coverageData = buildCoverageData(cov, subsetting);
-
- // Build response xml document
- output = buildOutputXml(coverageData, cov);
-
- return output;
- }
-
- private NodeList evalXPathList(String query, Object context) throws WCSException {
- try {
- LOG.debug("Evaluating XPath: {}", query);
- XPath xpath = xpathFactory.newXPath();
-
- xpath.setNamespaceContext(new WcsNamespaceContext());
- NodeList result = (NodeList) xpath.evaluate(query, context, XPathConstants.NODESET);
-
- for (int i = 0; i < result.getLength(); i++) {
- LOG.trace("Result {}: {}", i, result.item(i).getNodeValue());
- }
-
- return (NodeList) result;
- } catch (XPathExpressionException e) {
- LOG.error("Could not execute XPath expression '{}'", query);
-
- throw new WcsRuntimeException("Could not execute XPath expression", e);
- }
- }
-
- private String getCoverageName(Document doc) throws WCSException {
- NodeList nodes = evalXPathList("//wcs:id/@gml:id", doc);
-
- if (nodes.getLength() != 1) {
- LOG.error("Could not retrieve coverage name from XML document.");
-
- return null;
- }
-
- return nodes.item(0).getNodeValue();
- }
-
- private Metadata readCoverageMetadata() throws WCSException, XPathExpressionException {
- String coverageId = getCoverageName(doc);
-
- if (meta.existsCoverageName(coverageId)) {
- try {
- Metadata cov = meta.read(coverageId);
-
- return cov;
- } catch (Exception e) {
- e.printStackTrace();
-
- throw new NoApplicableCodeException("Metadata for coverage '"
- + coverageId + "' is not valid.");
- }
- } else {
- throw new InvalidParameterValueException("gml:id");
- }
- }
-
- /** Computes the domain of the new coverage, and returns a string that can be
- * used to do subsetting on the original coverage. Also computes the low, high
- * and the axis labels for the new coverage.
- *
- * @param coverage
- * @return
- * @throws WCSException
- */
- private String computeRequestSubsettingLimits(Metadata coverage) throws WCSException {
- int dims = coverage.getDimension(), i = 0;
- String[] limits = new String[dims];
- BigInteger[] high = new BigInteger[dims];
- BigInteger[] low = new BigInteger[dims];
- String[] axesLabels = new String[dims];
- boolean[] sliced = new boolean[dims];
- boolean[] trimmed = new boolean[dims];
-
- Iterator<CellDomainElement> it = coverage.getCellDomainIterator();
- Iterator<DomainElement> it2 = coverage.getDomainIterator();
- i = 0;
- while (it.hasNext() && it2.hasNext()) {
- CellDomainElement cell = it.next();
- DomainElement dom = it2.next();
- LOG.trace(cell.toString());
- LOG.trace(dom.toString());
- high[i] = cell.getHi();
- low[i] = cell.getLo();
- axesLabels[i] = dom.getName();
- limits[i] = low[i] + ":" + high[i];
- sliced[i] = false;
- trimmed[i] = false;
- i++;
- }
-
- NodeList list = null;
- int axisIndex;
- String axis, root;
- NodeList trims, slices;
-
- trims = evalXPathList("//wcs:trimDimension", doc);
- for (i = 0; i < trims.getLength(); i++) {
- Node trim = trims.item(i);
-
- list = evalXPathList("wcs:dimension/text()", trim);
- axis = list.item(0).getNodeValue();
- axisIndex = coverage.getDomainIndexByName(axis);
- if (axisIndex == -1) {
- throw new InvalidParameterValueException("dimension. Explanation: Unknown axis: " + axis);
- }
- if (trimmed[axisIndex] || sliced[axisIndex]) {
- throw new NoApplicableCodeException("Already performed one subsetting operation on axis: " + axis);
- }
-
- list = evalXPathList("wcs:trimLow/text()", trim);
- if (list.getLength() > 0) {
- try {
- long val = Long.parseLong(list.item(0).getNodeValue());
- low[axisIndex] = BigInteger.valueOf(val);
- } catch (NumberFormatException e) {
- throw new InvalidParameterValueException("trimLow. Explanation: invalid integer number: " + list.item(0).getNodeValue());
- }
- }
- list = evalXPathList("wcs:trimHigh/text()", trim);
- if (list.getLength() > 0) {
- try {
- long val = Long.parseLong(list.item(0).getNodeValue());
- high[axisIndex] = BigInteger.valueOf(val);
- } catch (NumberFormatException e) {
- throw new InvalidParameterValueException("trimHigh. Explanation: invalid integer number: " + list.item(0).getNodeValue());
- }
- }
-
- trimmed[axisIndex] = true;
- limits[axisIndex] = low[axisIndex] + ":" + high[axisIndex];
- LOG.debug("New limits for axis {}: {}", axis, limits[axisIndex]);
- }
-
- slices = evalXPathList("//wcs:sliceDimension", doc);
- for (i = 0; i < slices.getLength(); i++) {
- Node slice = slices.item(i);
-
- list = evalXPathList("wcs:dimension/text()", slice);
- axis = list.item(0).getNodeValue();
- axisIndex = coverage.getDomainIndexByName(axis);
- if (axisIndex == -1) {
- throw new InvalidParameterValueException("dimension. Explanation: Unknown axis name: " + axis);
- }
- if (trimmed[axisIndex] || sliced[axisIndex]) {
- throw new NoApplicableCodeException("Already performed one subsetting operation on axis: " + axis);
- }
-
- list = evalXPathList("wcs:slicePoint/text()", slice);
- if (list.getLength() > 0) {
- try {
- long point = Long.parseLong(list.item(0).getNodeValue());
- low[axisIndex] = BigInteger.valueOf(point);
- } catch (NumberFormatException e) {
- throw new InvalidParameterValueException("slicePoint. Explanation: invalid integer number: " + list.item(0).getNodeValue());
- }
- high[axisIndex] = low[axisIndex];
- limits[axisIndex] = list.item(0).getNodeValue();
- }
-
- sliced[axisIndex] = true;
- LOG.debug("New limits for axis {}: {}", axis, limits[axisIndex]);
- }
-
- // Compute the lowest, highest point and the labels
- lowPoint = "";
- highPoint = "";
- newAxesLabels = "";
- int first = 0;
- for (i = 0; i < dims; i++) {
- if (sliced[i] == false) {
- if (first == 0) {
- lowPoint = low[i].toString();
- highPoint = high[i].toString();
- newAxesLabels = axesLabels[i];
- first++;
- } else {
- lowPoint += " " + low[i];
- highPoint += " " + high[i];
- newAxesLabels += " " + axesLabels[i];
- }
- }
- }
-
- // Concatenate all limits into a single string
- String result = limits[0];
-
- for (i = 1; i < dims; i++) {
- result += ", " + limits[i];
- }
-
- return result;
- }
-
- public String executeRasqlQuery(String query) throws WCSException {
- byte[] result = null;
-
- Implementation impl = new RasImplementation(ConfigManager.RASDAMAN_URL);
- Database db = impl.newDatabase();
-
- try {
- db.open(ConfigManager.RASDAMAN_DATABASE, Database.OPEN_READ_ONLY);
- } catch (ODMGException odmge) {
- try {
- db.close();
- } catch (ODMGException e) {
- }
-
- throw new InternalComponentException("Could not connect to rasdaman server at " + ConfigManager.RASDAMAN_URL + ", database " + ConfigManager.RASDAMAN_DATABASE, odmge);
- }
-
- Transaction tr = impl.newTransaction();
-
- tr.begin();
- OQLQuery q = impl.newOQLQuery();
- DBag resultSet;
-
- try {
- q.create(query);
- resultSet = (DBag) q.execute();
-
- if (resultSet != null) {
- Iterator resultIterator = resultSet.iterator();
-
- if (resultIterator.hasNext()) {
- Object current = resultIterator.next();
-
- try {
- RasGMArray resultArray = (RasGMArray) current;
- result = resultArray.getArray();
- } catch (ClassCastException e) {
- LOG.error("result=" + current.toString());
- result = current.toString().getBytes();
- }
- }
- }
- } catch (QueryException qe) {
- tr.commit();
-
- try {
- db.close();
- } catch (ODMGException odmge) {
- }
-
- throw new InternalComponentException("Could not evaluate rasdaman query: '" + query + "'. Cause: " + qe.getMessage(), qe);
- }
-
- tr.commit();
-
- try {
- db.close();
- } catch (ODMGException odmge) {
- }
-
- return new String(result);
- }
-
- /** Creates a string with the contents of the GetCoverage response XML */
- private String buildOutputXml(String coverageData, Metadata coverage) {
- String xml = GetCoverageResponse;
- xml = xml.replaceAll("\\{coverageId\\}", coverage.getCoverageName() + Math.random());
- xml = xml.replaceAll("\\{gridDimension\\}", String.valueOf(coverage.getDimension()));
- xml = xml.replaceAll("\\{gridId\\}", "grid-" + coverage.getCoverageName());
- // low
- xml = xml.replaceAll("\\{low\\}", lowPoint);
- // high
- xml = xml.replaceAll("\\{high\\}", highPoint);
- // axisLabels
- xml = xml.replaceAll("\\{axisLabels\\}", newAxesLabels);
- // coverageData
- xml = xml.replaceAll("\\{coverageData\\}", coverageData);
-
-
-
- // Build the range structure
- Iterator<RangeElement> it3 = coverage.getRangeIterator();
- int i = -1;
- String rangeComponents = "";
- while (it3.hasNext()) {
- String component = rangeComponentTemplate;
- RangeElement range = it3.next();
- i++;
- String rangeId = "range-" + coverage.getCoverageId() + "-" + range.getName();
- LOG.trace(range.toString());
-
- component = component.replaceAll("\\{rangeFieldId\\}", rangeId);
- component = component.replaceAll("\\{fieldName\\}", range.getName());
- component = component.replaceAll("\\{datatype\\}", DescribeCoverage.DATATYPE_URN_PREFIX + range.getType());
-
- // Compute the null values for this range field
- Set<String> nullVals = new HashSet<String>();
- Iterator<String> it = coverage.getNullSetIterator();
- while (it.hasNext()) {
- List<String> nilVal = SDU.str2string(it.next());
- nullVals.add(nilVal.get(i));
- }
- StringBuffer nullValsString = new StringBuffer();
- it = nullVals.iterator();
- while (it.hasNext()) {
- nullValsString.append(" " + it.next());
- }
- component = component.replaceAll("\\{nilValues\\}", nullValsString.toString().substring(1));
-
- // And add this range field to the range structure
- rangeComponents += component;
- }
-
- xml = xml.replaceAll("\\{rangeFields\\}", rangeComponents);
- xml = xml.replaceAll("\\{rangeStructureId\\}", "rangeStructure-" + coverage.getCoverageId());
-
- xml = xml.replaceAll("\\{wcsSchemaUrl\\}", ConfigManager.WCS2_SCHEMA_URL);
-
- return xml;
- }
-
- /**
- * Retrieve the coverage data for a multi-band coverage,
- * with particular subsetting parameters.
- * @param coverage metadata for the coverage we want
- * @param subsetting subsetting string, to be used in the RasQL query
- * @return a string of space-separated values, where various bands of one
- * pixel are comma-separated. For example, the string "1,2 3,4 5,6" can
- * be the coverage data of a 1-by-3 coverage, with two bands
- */
- private String buildCoverageData(Metadata coverage, String subsetting) throws WCSException {
- String coverageName = coverage.getCoverageName();
- Iterator<RangeElement> it = coverage.getRangeIterator();
- int bandcount = 0;
- while (it.hasNext()) {
- it.next();
- bandcount++;
- }
- LOG.debug("Coverage {} has {} bands", coverageName, bandcount);
- String[][] pixels = new String[bandcount][];
- String currentBand = "";
- /* For all bands of the coverage, execute a rasql query */
- for (int band = 0; band < bandcount; band++) {
- LOG.trace("Processing band {}", band);
- // Construct rasql query
- currentBand = "." + band;
- // If this is a one-band image, then band-subsetting would result in an error
- if (bandcount == 1) {
- currentBand = "";
- }
- String rasqlQuery = "select csv(cov[" + subsetting + "]" + currentBand + ") "
- + "from " + coverageName + " as cov";
-
- // Execute RasQl query => coverage data
- LOG.trace("Executing query {}", rasqlQuery);
- String output = executeRasqlQuery(rasqlQuery);
-
- // Remove the curly braces from the rasql output
- LOG.trace("Removing curly braces...");
- output = output.replaceAll("\\{", "");
- output = output.replaceAll("\\}", "");
-
- // Tokenize the input to get the pixel values of the current band
- LOG.trace("Splitting values with comma...");
- pixels[band] = output.split(",");
-
- LOG.trace("Done processing band {}.", band);
- }
-
- /* Combine all bands into one single string */
- int pixelcount = pixels[0].length;
- StringBuilder data = new StringBuilder(pixelcount * bandcount);
- LOG.debug("Going to combine {} pixels with {} bands...", pixelcount, bandcount);
- for (int pix = 0; pix < pixelcount; pix++) {
- if (pixelcount > 20 && pix % (pixelcount / 20) == 0) {
- LOG.debug("Processing Pixel {} of " + pixelcount + " - {}%", pix, pix * 100 / (pixelcount - 1));
- }
- for (int b = 0; b < bandcount - 1; b++) {
- data.append(pixels[b][pix] + ",");
- }
- data.append(pixels[bandcount - 1][pix]);
- data.append(" ");
- }
- return data.substring(0, data.length() - 2);
- }
-}