summaryrefslogtreecommitdiffstats
path: root/petascope/src/petascope/wcs/server/core
diff options
context:
space:
mode:
Diffstat (limited to 'petascope/src/petascope/wcs/server/core')
-rw-r--r--petascope/src/petascope/wcs/server/core/TimeString.java223
-rw-r--r--petascope/src/petascope/wcs/server/core/convertGetCoverage.java498
-rw-r--r--petascope/src/petascope/wcs/server/core/executeDescribeCoverage.java275
-rw-r--r--petascope/src/petascope/wcs/server/core/executeGetCapabilities.java295
4 files changed, 1291 insertions, 0 deletions
diff --git a/petascope/src/petascope/wcs/server/core/TimeString.java b/petascope/src/petascope/wcs/server/core/TimeString.java
new file mode 100644
index 0000000..668614e
--- /dev/null
+++ b/petascope/src/petascope/wcs/server/core/TimeString.java
@@ -0,0 +1,223 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope 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, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcs.server.core;
+
+//~--- non-JDK imports --------------------------------------------------------
+import org.joda.time.DateTime;
+import org.joda.time.format.DateTimeFormat;
+import org.joda.time.format.DateTimeFormatter;
+
+import org.joda.time.format.ISODateTimeFormat;
+
+/**
+ * Represents a Time object, according to ISO 8601, and utility methods.
+ *
+ * @author Gulius Caesar
+ */
+public class TimeString {
+
+ private static DateTimeFormatter DTF = ISODateTimeFormat.dateTime();
+ private DateTime dateTime;
+ private long milliseconds;
+ private String strTime;
+
+ /* Default constructor */
+ public TimeString(String timeStr) throws IllegalArgumentException {
+ strTime = timeStr;
+ dateTime = parse(strTime);
+ milliseconds = parseMillis(strTime);
+ }
+
+ public DateTime getDateTime() {
+ return dateTime;
+ }
+
+ public long getMilliseconds() {
+ return milliseconds;
+ }
+
+ public long subtract(String newString) throws IllegalArgumentException {
+ long newD = parseMillis(newString);
+ long res = milliseconds - newD;
+
+ return res;
+ }
+
+ public double divide(String newString) throws IllegalArgumentException {
+ long newD = parseMillis(newString);
+ double result = milliseconds * new Double(1.0) / newD;
+
+ return result;
+ }
+
+ /** ******************** Static methods ***************** */
+
+ /*
+ * Subtraction Method, calculates the difference in milliseconds between two dates
+ */
+ public static long difference(String bigDate, String smallDate) throws IllegalArgumentException {
+ long smallD = parseMillis(smallDate);
+ long bigD = parseMillis(bigDate);
+ long result = bigD - smallD;
+
+ return result;
+ }
+
+ /**
+ * Division of one Date by the other.
+ */
+ public static double division(String IAmDivided, String IDivide) throws IllegalArgumentException {
+ long iad = parseMillis(IAmDivided);
+ long id = parseMillis(IDivide);
+ double result = iad * new Double(1.0) / id;
+
+ return result;
+ }
+
+ /*
+ * Division of a millisecond-Date-respresentation by a number.
+ */
+ public static double division(String InputDate, long Divisor) throws IllegalArgumentException {
+ long ID = parseMillis(InputDate);
+
+ double result = ID * new Double(1.0) / Divisor;
+
+ return result;
+
+ }
+
+ /**
+ * Date to millisecond parser. Accepts the standard ISO 8601 + shorter codes.
+ * @return long number of miliseconds
+ */
+ public static long parseMillis(String TString) throws IllegalArgumentException {
+ long Millis;
+ int NumberOfSymbols = TString.length();
+
+ switch (NumberOfSymbols) {
+ case 24:
+ DTF = ISODateTimeFormat.dateTime();
+ Millis = DTF.parseMillis(TString);
+
+ break;
+ case 22:
+ DTF = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SS");
+ Millis = DTF.parseMillis(TString);
+
+ break;
+ case 19:
+ DTF = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss");
+ Millis = DTF.parseMillis(TString);
+
+ break;
+ case 16:
+ DTF = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm");
+ Millis = DTF.parseMillis(TString);
+
+ break;
+ case 13:
+ DTF = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH");
+ Millis = DTF.parseMillis(TString);
+
+ break;
+ case 10:
+ DTF = DateTimeFormat.forPattern("yyyy-MM-dd");
+ Millis = DTF.parseMillis(TString);
+
+ break;
+ case 7:
+ DTF = DateTimeFormat.forPattern("yyyy-MM");
+ Millis = DTF.parseMillis(TString);
+
+ break;
+ case 4:
+ DTF = DateTimeFormat.forPattern("yyyy");
+ Millis = DTF.parseMillis(TString);
+
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown DateTime format.");
+ }
+
+ return Millis;
+ }
+
+ /**
+ *
+ * @param TString string containing date
+ * @return joda DateTime corresponding to the input string
+ * @throws IllegalArgumentException
+ */
+ public static DateTime parse(String str) throws IllegalArgumentException {
+ DateTime date;
+ int NumberOfSymbols = str.length();
+
+ System.out.println("Parsing date '" + str + "', with length " + str.length());
+
+ switch (NumberOfSymbols) {
+ case 24:
+ DTF = ISODateTimeFormat.dateTime();
+ date = DTF.parseDateTime(str);
+
+ break;
+ case 22:
+ DTF = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SS");
+ date = DTF.parseDateTime(str);
+
+ break;
+ case 19:
+ DTF = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss");
+ date = DTF.parseDateTime(str);
+
+ break;
+ case 16:
+ DTF = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm");
+ date = DTF.parseDateTime(str);
+
+ break;
+ case 13:
+ DTF = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH");
+ date = DTF.parseDateTime(str);
+
+ break;
+ case 10:
+ DTF = DateTimeFormat.forPattern("yyyy-MM-dd");
+ date = DTF.parseDateTime(str);
+
+ break;
+ case 7:
+ DTF = DateTimeFormat.forPattern("yyyy-MM");
+ date = DTF.parseDateTime(str);
+
+ break;
+ case 4:
+ DTF = DateTimeFormat.forPattern("yyyy");
+ date = DTF.parseDateTime(str);
+
+ break;
+ default:
+ throw new IllegalArgumentException("Unknown DateTime format.");
+ }
+
+ return date;
+ }
+}
diff --git a/petascope/src/petascope/wcs/server/core/convertGetCoverage.java b/petascope/src/petascope/wcs/server/core/convertGetCoverage.java
new file mode 100644
index 0000000..7d4a951
--- /dev/null
+++ b/petascope/src/petascope/wcs/server/core/convertGetCoverage.java
@@ -0,0 +1,498 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope 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, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcs.server.core;
+
+//~--- non-JDK imports --------------------------------------------------------
+import petascope.wcs.server.exceptions.WCSException;
+import net.opengis.gml.v_3_1_1.TimePositionType;
+import net.opengis.ows.v_1_0_0.BoundingBoxType;
+import net.opengis.wcs.v_1_1_0.DomainSubsetType;
+import net.opengis.wcs.v_1_1_0.GetCoverage;
+import net.opengis.wcs.v_1_1_0.GridCrsType;
+import net.opengis.wcs.v_1_1_0.RangeSubsetType;
+import net.opengis.wcs.v_1_1_0.TimePeriodType;
+
+import petascope.wcps.server.core.DbMetadataSource;
+import petascope.wcps.server.core.ProcessCoveragesRequest;
+import petascope.wcps.server.exceptions.WCPSException;
+import petascope.wcps.server.core.DomainElement;
+
+import petascope.ConfigManager;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import org.antlr.runtime.RecognitionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import petascope.wcps.server.core.Metadata;
+import petascope.wcs.server.exceptions.InvalidParameterValueException;
+import petascope.wcs.server.exceptions.InvalidTemporalMetadataException;
+import petascope.wcs.server.exceptions.MissingParameterValueException;
+import petascope.wcs.server.exceptions.NoApplicableCodeException;
+
+/**
+ * This class takes a WCS GetCoverage XML request and converts this request into
+ * a WCPS ProcessCoverages XML request. It is the user's responsibility to pass
+ * the WCPS request to a WCPS server in order to view to result.
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class convertGetCoverage {
+
+ private static Logger LOG = LoggerFactory.getLogger(convertGetCoverage.class);
+ // Trimming
+ private boolean xAxisTrim = false;
+ private boolean yAxisTrim = false;
+ // Time Trimming
+ private boolean timeTrim = false;
+ // Time Slicing
+ private boolean timeSlice = false;
+
+ /* WCPS requests */
+ private String abstractRequest;
+ // Range Composition (field combination)
+ private boolean combineFields;
+
+ /* Value variables, used for building the WCPS abstract syntax query */
+ private String coverageName;
+ private List<String> fields;
+ private boolean finished;
+ // Output
+ private String format;
+
+ /* The Configuration Manager */
+ private DbMetadataSource meta;
+ private boolean store;
+ private String time1, time2;
+ private String timePos;
+ private GetCoverage wcs;
+ private long px0, px1, py0, py1; // Bounding box subsetting
+ private String crsName; // for bounding box
+ private String xmlRequest;
+ private Metadata covMeta;
+
+ /**
+ * Default constructor
+ * @param cov GetCoverage object, the input WCS request for retrieving a coverage
+ * @param path Path to the "settings.properties" file
+ */
+ public convertGetCoverage(GetCoverage cov, DbMetadataSource source)
+ throws WCSException, WCPSException {
+ /* Init Config Manager and global */
+ ConfigManager globals = ConfigManager.getInstance();
+ /* Setup objects */
+ wcs = cov;
+ finished = false;
+
+ meta = source;
+ }
+
+ /**
+ * * Retrieves the WCPS request object that is
+ * equivalent to the WCS request. If it is not yet converted, it will
+ * perform the conversion.
+ *
+ * @return a WCPS abstract syntax query as a string
+ * @throws wcs.server.core.WCSException
+ */
+ public String get() throws WCSException {
+ try {
+ if (!finished) {
+ process();
+ }
+
+ /* Convert the abstract syntax query to a ProcessCoveragesRequest */
+ LOG.debug("Converting WCPS abstract query '{}' to xml", abstractRequest);
+ xmlRequest = ProcessCoveragesRequest.abstractQueryToXmlQuery(abstractRequest);
+ LOG.debug("Resulting XML query is: \n{}", xmlRequest);
+ } catch (RecognitionException re) {
+ throw new NoApplicableCodeException("Internal error: Generated abstract syntax query was not valid.", re);
+ }
+
+ return xmlRequest;
+ }
+
+ /**
+ * Converts WCS node 1 (Coverage Identifier) to WCPS info
+ * @throws wcs_web_service.WCSException
+ */
+ private void readField1() throws WCSException {
+ coverageName = wcs.getIdentifier().getValue();
+ }
+
+ /**
+ * Converts WCS node 2 (Domain subsetting) to WCPS info
+ * @throws wcs_web_service.WCSException
+ */
+ private void readField2() throws WCSException {
+ if (!wcs.isSetDomainSubset()) {
+ throw new MissingParameterValueException("DomainSubset");
+ }
+ if (!wcs.getDomainSubset().isSetBoundingBox()) {
+ throw new MissingParameterValueException("BoundingBox");
+ }
+
+ DomainSubsetType domain = wcs.getDomainSubset();
+
+ // DomainSubset->BoundingBox
+ if (domain.isSetBoundingBox()) {
+ BoundingBoxType bbox = (BoundingBoxType) domain.getBoundingBox().getValue();
+
+ /* We only understand two CRSs: WGS84 and IMAGE_CRS */
+ /* TODO: Implement CRS transformations */
+ crsName = bbox.getCrs();
+ if (crsName != null) {
+ if (crsName.equals(DomainElement.IMAGE_CRS)) {
+ LOG.trace("CRS: NATIVE_IMAGE_CRS");
+ } else if (crsName.equals(DomainElement.WGS84_CRS)) {
+ LOG.trace("CRS: WGS84");
+ } else {
+ throw new InvalidParameterValueException("BoundingBox.crs. Explanation: "
+ + "CRS '" + crsName + "' not available on this server.");
+ }
+ } else {
+ LOG.debug("CRS: None specified for bounding box");
+ LOG.debug("CRS: Using default IMAGE_CRS");
+ crsName = DomainElement.IMAGE_CRS;
+ }
+
+ /* BBox declarations */
+ if (bbox.getLowerCorner().size() != 2) {
+ throw new InvalidParameterValueException("LowerCorner. Explanation: "
+ + "BoundingBox -> LowerCorner should have exactly two "
+ + "values, not " + bbox.getLowerCorner().size());
+ }
+ if (bbox.getUpperCorner().size() != 2) {
+ throw new InvalidParameterValueException("UpperCorner. Explanation: "
+ + "BoundingBox -> UpperCorner should have exactly two "
+ + "values, not " + bbox.getUpperCorner().size());
+ }
+
+ xAxisTrim = true;
+ int u2 = bbox.getLowerCorner().get(0).intValue();
+ int u3 = bbox.getUpperCorner().get(0).intValue();
+ LOG.trace("Added X-axis trimming ! (DomainSubset->BoundingBox): " + u2 + " ... "
+ + u3);
+
+ yAxisTrim = true;
+ int v2 = bbox.getLowerCorner().get(1).intValue();
+ int v3 = bbox.getUpperCorner().get(1).intValue();
+ LOG.trace("Added Y-axis trimming ! (DomainSubset->BoundingBox): " + v2 + " ... "
+ + v3);
+
+ /* Use bounding-box values as they are given */
+ px0 = u2;
+ py0 = v2;
+ px1 = u3;
+ py1 = v3;
+
+ if (crsName.equals(DomainElement.IMAGE_CRS) == false
+ && crsName.equals(DomainElement.WGS84_CRS) == false) {
+ throw new NoApplicableCodeException("Unknown CRS: " + crsName);
+ }
+ }
+
+ // DomainSubset->TemporalSubset
+ if (domain.isSetTemporalSubset()) {
+ // TemporalSubset is of type TimeSequenceType = choice(gml:TimePosition, wcs:TimePeriodType)
+ Object one = domain.getTemporalSubset().getTimePositionOrTimePeriod().get(0);
+
+ LOG.trace("Inside TemporalSubset there is " + one.getClass());
+ if (one instanceof net.opengis.gml.v_3_1_1.TimePositionType) {
+ // TemporalSubset = gml:TimePosition
+ // use WCPS:slice
+ timeSlice = true;
+
+ TimePositionType pos = (TimePositionType) one;
+
+
+ /* Default syntax is ISO 8601.
+ However, we also accept direct time-axis coordinates, as a fail-back solution. */
+ timePos = parseTimePosition(pos);
+ LOG.trace("Added time-axis slicing ! ( DomainSubset->TemporalSubset->gml:TimePositionType): position "
+ + timePos);
+ } else if (one instanceof net.opengis.wcs.v_1_1_0.TimePeriodType) {
+ // TemporalSubset = wcs:TimePeriodType
+ timeTrim = true;
+
+ TimePeriodType period = (TimePeriodType) one;
+
+ TimePositionType pos1 = period.getBeginPosition();
+ TimePositionType pos2 = period.getEndPosition();
+
+ /* Default syntax is ISO 8601.
+ However, we also accept direct time-axis coordinates, as a fail-back solution. */
+ time1 = parseTimePosition(pos1);
+ time2 = parseTimePosition(pos2);
+
+ LOG.trace("Added time-axis trimming ! ( DomainSubset->TemporalSubset->wcs:TimePeriodType): "
+ + time1 + " ... " + time2);
+ }
+ }
+ }
+
+ /**
+ * Converts WCS node 3 (Range subsetting) to WCPS info
+ */
+ private void readField3() throws WCSException {
+ if (wcs.isSetRangeSubset()) {
+ RangeSubsetType range = wcs.getRangeSubset();
+
+ combineFields = true;
+ fields = new ArrayList<String>();
+
+ Iterator<RangeSubsetType.FieldSubset> it = range.getFieldSubset().iterator();
+
+ while (it.hasNext()) {
+ RangeSubsetType.FieldSubset field = it.next();
+
+ fields.add(field.getIdentifier().getValue());
+ LOG.trace("RangeSubsetType->FieldSubset->Identifier is "
+ + field.getIdentifier().getValue());
+ LOG.trace("RangeSubsetType->FieldSubset->Interpolation is "
+ + field.getInterpolationType());
+ /* NOTE: We ignore interpolation instructions (optional) */
+ /* NOTE: We ignore axis subset lists (optional) */
+ }
+
+ }
+ }
+
+ /**
+ * Converts WCS node 4 (Output) to WCPS info
+ * @throws wcs_web_service.WCSException
+ */
+ private void readField4() throws WCSException {
+ if (!wcs.isSetOutput()) {
+ throw new MissingParameterValueException("Output");
+ }
+ LOG.trace("Format: " + wcs.getOutput().getFormat());
+
+ if (wcs.getOutput().isSetGridCRS()) {
+ GridCrsType crs = wcs.getOutput().getGridCRS();
+
+ throw new NoApplicableCodeException("Currently, the Output->GridCRS node is not supported !");
+ }
+
+ String wcsMimeFormat = wcs.getOutput().getFormat();
+
+ format = meta.mimetypeToFormat(wcsMimeFormat);
+ LOG.trace("New format: " + format);
+ if ((format == null) || format.equals("")) {
+ throw new InvalidParameterValueException("Output format");
+ }
+
+ LOG.trace("issetstore = " + wcs.getOutput().isSetStore());
+ LOG.trace("isstore = " + wcs.getOutput().isStore());
+ store = false;
+ if (wcs.getOutput().isSetStore() && wcs.getOutput().isStore()) {
+ store = true;
+ }
+
+ /* WCPS does not support "store=true" */
+ if (store) {
+ throw new InvalidParameterValueException("Output Store. Explanation: "
+ + "Cannot store result image on server.");
+ }
+ }
+
+ /**
+ * Performs the conversion of the WCS request into a WCPS abstract syntax request.
+ * @throws wcs_web_service.WCSException
+ */
+ @SuppressWarnings("static-access")
+ public void process() throws WCSException {
+ /** * Processing starts here ... with the nodes of the WCS * */
+ // Service Description
+ LOG.debug("WCS service: \"" + wcs.SERVICE + "\"");
+ LOG.debug("WCS version: \"" + wcs.VERSION + "\"");
+ if (!wcs.SERVICE.equalsIgnoreCase("WCS")) {
+ throw new InvalidParameterValueException("Service. Explanation: "
+ + "Only the WCS service is supported.");
+ }
+ if (!wcs.VERSION.equals("1.1.0")) {
+ throw new InvalidParameterValueException("Version. Explanation: "
+ + "Only WCS Version 1.1.0 is currently supported.");
+ }
+
+ // First of all, error checking: is the coverage offered by the server?
+ if (!wcs.isSetIdentifier()) {
+ throw new MissingParameterValueException("Identifier");
+ }
+ try {
+ if (!meta.existsCoverageName(wcs.getIdentifier().getValue())) {
+ throw new InvalidParameterValueException("Identifier. Explanation: "
+ + "Coverage " + wcs.getIdentifier().getValue()
+ + " is not served by this server.");
+ }
+ covMeta = meta.read(wcs.getIdentifier().getValue());
+ } catch (WCPSException e) {
+ throw new InvalidParameterValueException("Identifier. Explanation: "
+ + "Coverage " + wcs.getIdentifier().getValue()
+ + " is not served by this server.");
+ }
+
+
+ // Convert all the child nodes of WCS GetCoverage XML node
+ LOG.trace("*** Reading WCS node 1 ... ");
+ readField1();
+ LOG.trace("*** Reading WCS node 2 ...");
+ readField2();
+ LOG.trace("*** Reading WCS node 3 ...");
+ readField3();
+ LOG.trace("*** Reading WCS node 4 ...");
+ readField4();
+ LOG.trace("*** Assembling WCPS abstract syntax query ...");
+ assembleFinalWcpsQuery();
+
+ /* Done building WCPS abstract query. */
+ finished = true;
+ LOG.trace("Done Converting WCS GetCoverage into WCPS ProcessCoverage.");
+ }
+
+ /**
+ * Constructs the WCPS abstract syntax query from the information gathered
+ * by <code>readField*()</code> functions.
+ */
+ private void assembleFinalWcpsQuery() {
+ // Bind variable "c" to the coverage name
+ String forClause = "for c in (" + coverageName + ") ";
+ // Base processing is done on the coverage variable
+ String processing = "c";
+
+ if (xAxisTrim && yAxisTrim) {
+ // Bounding box subsetting
+ String xAxis = "x:\"" + crsName + "\" (" + px0 + ":" + px1 + ")";
+ String yAxis = "y:\"" + crsName + "\" (" + py0 + ":" + py1 + ")";
+ String tAxis = "t(" + time1 + ":" + time2 + ")";
+
+ if (timeTrim) {
+ processing = "trim( " + processing + ", {" + xAxis + ", " + yAxis + ", " + tAxis
+ + "} )";
+ } else {
+ processing = "trim( " + processing + ", {" + xAxis + ", " + yAxis + "} )";
+ }
+ }
+ if (timeSlice) {
+ // Time slicing
+ String tAxis = "t(" + timePos + ")";
+
+ processing = "slice( " + processing + ", {" + tAxis + "} )";
+ }
+ if (combineFields) {
+ // Only one field means we have a "field select" statement
+ if (fields.size() == 1) {
+ String field = fields.get(0);
+
+ processing = "(" + processing + ")." + field;
+ } else // Multiple fields translate into a "range constructor" statement
+ {
+ String newProc = "";
+ Iterator<String> it = fields.iterator();
+
+ while (it.hasNext()) {
+ String field = it.next();
+
+ if (newProc.length() > 0) {
+ newProc += "; ";
+ }
+ newProc += field + ":" + processing;
+ }
+ processing = "struct { " + newProc + " }";
+ }
+ }
+ // Set the output format
+ processing = "encode(" + processing + ", \"" + format + "\")";
+
+ // Build the final query
+ String returnClause = "return " + processing;
+
+ abstractRequest = forClause + returnClause;
+ }
+
+ /** Convert a time-position JAXB object into a numerical index we can use for the
+ * time subsetting.
+ * @param pos TimePositionType object
+ * @return String representation of integer time
+ * @throws WCSException if the contents of the time position is not an integer or an ISO8601 string
+ */
+ private String parseTimePosition(TimePositionType pos) throws WCSException {
+ String result;
+
+ LOG.trace("TimePosition has length " + pos.getValue().size());
+ if (pos.getValue().size() != 1) {
+ throw new InvalidParameterValueException("TimePosition. Explanation: "
+ + "The TimePosition element should have exactly one item, and not "
+ + pos.getValue().size());
+ }
+ String timeStr = pos.getValue().get(0);
+
+ LOG.debug("Parsing time position: " + timeStr);
+ try {
+ // ISO 8601 parsing
+ TimeString ts = new TimeString(timeStr);
+ LOG.debug("Found time position (ISO 8601): " + timeStr);
+ if (ts.subtract(covMeta.getTimePeriodBeginning()) < 0
+ || TimeString.difference(covMeta.getTimePeriodEnd(), timeStr) < 0) {
+ throw new InvalidParameterValueException("TimePosition: value " + timeStr
+ + " is outside this coverage's time range.");
+ }
+ String begin = covMeta.getTimePeriodBeginning();
+ if (begin == null) {
+ throw new InvalidTemporalMetadataException("Coverage '" + covMeta.getCoverageName()
+ + "' has no time axis beginning or end in table PS_Domain.");
+ }
+ long diff1 = ts.subtract(begin);
+ LOG.trace("Selected time span (ISO 8601, in ms) : " + diff1);
+ long diff2 = covMeta.getTimeSpan();
+ if (diff2 == -1) {
+ throw new InvalidTemporalMetadataException("Coverage '" + covMeta.getCoverageName()
+ + "' has no time axis beginning or end in table PS_Domain.");
+ }
+ LOG.trace("Coverage " + covMeta.getCoverageName() + " has time span (ISO 8601, in ms) : " + diff2);
+ LOG.trace("Coverage " + covMeta.getCoverageName() + " has time indexes span : " + covMeta.getTimeIndexesSpan());
+ Double dIndex = covMeta.getTimeIndexesSpan() * diff1 * new Double(1.0) / diff2;
+ if (dIndex == -1) {
+ throw new InvalidTemporalMetadataException("Coverage '" + covMeta.getCoverageName()
+ + "' has no time axis.");
+ }
+ LOG.trace("Computed time axis index: " + dIndex);
+ long timeIndex = dIndex.longValue();
+
+ result = String.valueOf(timeIndex);
+ } catch (IllegalArgumentException e) {
+ LOG.warn("Time position '" + timeStr + "' was not in ISO 8601 format. Trying to parse integer...");
+ try {
+ Integer tPos = Integer.parseInt(timeStr);
+ LOG.debug("Found time position in integer coordinates: " + tPos);
+ result = tPos.toString();
+ } catch (NumberFormatException e2) {
+ throw new InvalidParameterValueException("TimePosition: " + timeStr, e2);
+ }
+ }
+
+ return result;
+ }
+}
diff --git a/petascope/src/petascope/wcs/server/core/executeDescribeCoverage.java b/petascope/src/petascope/wcs/server/core/executeDescribeCoverage.java
new file mode 100644
index 0000000..6df74a8
--- /dev/null
+++ b/petascope/src/petascope/wcs/server/core/executeDescribeCoverage.java
@@ -0,0 +1,275 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope 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, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcs.server.core;
+
+//~--- non-JDK imports --------------------------------------------------------
+import petascope.wcs.server.exceptions.WCSException;
+import net.opengis.ows.v_1_0_0.BoundingBoxType;
+import net.opengis.wcs.ows.v_1_1_0.DomainMetadataType;
+import net.opengis.wcs.ows.v_1_1_0.InterpolationMethodType;
+import net.opengis.wcs.ows.v_1_1_0.InterpolationMethods;
+import net.opengis.wcs.ows.v_1_1_0.UnNamedDomainType;
+import net.opengis.wcs.v_1_1_0.CoverageDescriptionType;
+import net.opengis.wcs.v_1_1_0.CoverageDescriptions;
+import net.opengis.wcs.v_1_1_0.CoverageDomainType;
+import net.opengis.wcs.v_1_1_0.DescribeCoverage;
+import net.opengis.wcs.v_1_1_0.FieldType;
+import net.opengis.wcs.v_1_1_0.RangeType;
+import net.opengis.wcs.v_1_1_0.SpatialDomainType;
+
+import petascope.wcps.server.core.*;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.util.Iterator;
+
+import javax.xml.XMLConstants;
+import javax.xml.bind.JAXBElement;
+import javax.xml.namespace.QName;
+import net.opengis.ows.v_1_0_0.KeywordsType;
+import net.opengis.wcs.ows.v_1_1_0.AnyValue;
+import net.opengis.wcs.v_1_1_0.TimeSequenceType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import petascope.wcs.server.exceptions.InvalidParameterValueException;
+import petascope.wcs.server.exceptions.NoApplicableCodeException;
+
+/**
+ * This class takes a WCS DescribeCoverage XML request and executes request,
+ * building the corresponding XML respose.
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class executeDescribeCoverage {
+
+ private static Logger LOG = LoggerFactory.getLogger(executeDescribeCoverage.class);
+ private boolean finished;
+ private DescribeCoverage input;
+ private DbMetadataSource meta;
+ private CoverageDescriptions output;
+
+ /**
+ * Default constructor
+ * @param cap DescribeCoverage object, a WCS (or WCPS) request
+ * @param metadataDbPath Path to the "dbparams.properties" file
+ */
+ public executeDescribeCoverage(DescribeCoverage cap, DbMetadataSource source)
+ throws WCSException {
+ input = cap;
+ output = new CoverageDescriptions();
+ finished = false;
+ meta = source;
+ }
+
+ /**
+ * Main method of this class. Retrieves the response to the DescribeCoverage
+ * request given to the constructor. If needed, it also calls <b>process()</b>
+ * @return a CoverageDescriptions object.
+ * @throws wcs_web_service.WCSException
+ */
+ public CoverageDescriptions get() throws WCSException {
+ if (finished == false) {
+ process();
+ }
+ if (finished == false) {
+ throw new NoApplicableCodeException("Could not execute the GetCapabilities request! "
+ + "Please see the other errors...");
+ }
+
+ return output;
+ }
+
+ /**
+ * Computes the response to the DescribeCoverage request given to the constructor.
+ */
+ public void process() throws WCSException {
+ String name;
+
+ for (int i = 0; i < input.getIdentifier().size(); i++) {
+ name = input.getIdentifier().get(i);
+ output.getCoverageDescription().add(getCoverageDescription(name));
+ }
+ finished = true;
+ }
+
+ /**
+ * Retrieve details for one coverage.
+ * @param name Name of the coverage
+ * @return CoverageDescriptionType object, that can just be plugged in the respose object
+ */
+ private CoverageDescriptionType getCoverageDescription(String name) throws WCSException {
+ LOG.trace("Building coverage description for coverage '" + name + "' ...");
+ CoverageDescriptionType desc = new CoverageDescriptionType();
+
+ // Error checking: is the coverage available?
+ if (meta.existsCoverageName(name) == false) {
+ throw new InvalidParameterValueException("Identifier. Explanation: Coverage "
+ + name + " is not served by this server !");
+ }
+
+ // Read all coverage metadata
+ Metadata cov = null;
+
+ try {
+ cov = meta.read(name);
+ } catch (Exception e) {
+ throw new NoApplicableCodeException("Metadata for coverage " + name + " is not valid.");
+ }
+
+ desc.setIdentifier(name);
+ desc.setTitle(cov.getTitle());
+ desc.setAbstract(cov.getAbstract());
+
+ KeywordsType keyword = new KeywordsType();
+ Iterator<String> keys = SDU.str2string(cov.getKeywords()).iterator();
+ while (keys.hasNext()) {
+ String k = keys.next();
+ keyword.getKeyword().add(k);
+ }
+ desc.getKeywords().add(keyword);
+
+ // Coverage Domain
+ CoverageDomainType domain = null;
+ Double lo1 = 0.0, lo2 = 0.0, hi1 = 0.0, hi2 = 0.0;
+
+ /* Default Bounding Box (uses IMAGE_CRS): use image size */
+ BoundingBoxType bbox = new BoundingBoxType();
+ CellDomainElement X = cov.getXCellDomain();
+ CellDomainElement Y = cov.getYCellDomain();
+ if (X != null && Y != null) {
+ lo1 = X.getLo().doubleValue();
+ hi1 = X.getHi().doubleValue();
+ lo2 = Y.getLo().doubleValue();
+ hi2 = Y.getHi().doubleValue();
+
+ bbox.setCrs(DomainElement.IMAGE_CRS);
+
+ bbox.getLowerCorner().add(lo1);
+ bbox.getLowerCorner().add(lo2);
+ bbox.getUpperCorner().add(hi1);
+ bbox.getUpperCorner().add(hi2);
+ } else {
+ throw new NoApplicableCodeException("Internal error: Could "
+ + "not find X and Y cell domain extents.");
+ }
+
+ /* Try to use WGS84 bounding box, if available */
+ Wgs84Crs crs = cov.getCrs();
+ BoundingBoxType bbox84 = new BoundingBoxType();
+ bbox84.setCrs(DomainElement.WGS84_CRS);
+ if (crs != null) {
+ lo1 = crs.getLow1().doubleValue();
+ hi1 = crs.getHigh1().doubleValue();
+ lo2 = crs.getLow2().doubleValue();
+ hi2 = crs.getHigh2().doubleValue();
+
+ bbox84.getLowerCorner().add(lo1);
+ bbox84.getLowerCorner().add(lo2);
+ bbox84.getUpperCorner().add(hi1);
+ bbox84.getUpperCorner().add(hi2);
+
+ bbox = bbox84;
+ }
+
+ domain = new CoverageDomainType();
+ SpatialDomainType spatial = new SpatialDomainType();
+ spatial.getBoundingBox().add(new JAXBElement<BoundingBoxType>(
+ new QName("http://www.opengis.net/ows", "BoundingBox", XMLConstants.DEFAULT_NS_PREFIX),
+ BoundingBoxType.class, bbox));
+ domain.setSpatialDomain(spatial);
+
+
+ /* Find a time-axis if exists */
+ CellDomainElement T = cov.getTCellDomain();
+ if (T != null) {
+ LOG.trace("Found time-axis for coverage: [" + T.getLo() + ", " + T.getHi() + "]");
+ TimeSequenceType temporal = new TimeSequenceType();
+ temporal.getTimePositionOrTimePeriod().add(T.getLo().intValue());
+ temporal.getTimePositionOrTimePeriod().add(T.getHi().intValue());
+ domain.setTemporalDomain(temporal);
+ }
+
+ desc.setDomain(domain);
+
+ // The coverage Range
+ RangeType wcsRange = new RangeType();
+ Iterator<RangeElement> rangeIt = cov.getRangeIterator();
+
+ while (rangeIt.hasNext()) {
+ RangeElement range = rangeIt.next();
+ FieldType field = new FieldType();
+
+ field.setIdentifier(range.getName());
+ UnNamedDomainType domtype = new UnNamedDomainType();
+ AnyValue anyVal = new AnyValue();
+ domtype.setAnyValue(anyVal);
+ DomainMetadataType dommeta = new DomainMetadataType();
+
+ dommeta.setValue(range.getType());
+ domtype.setDataType(dommeta);
+ field.setDefinition(domtype);
+
+ InterpolationMethods interp = new InterpolationMethods();
+
+ InterpolationMethodType meth = new InterpolationMethodType();
+
+ meth.setValue(cov.getInterpolationDefault());
+ meth.setNullResistance(cov.getNullResistanceDefault());
+ interp.setDefaultMethod(meth);
+
+ Iterator<InterpolationMethod> interpIt = cov.getInterpolationMethodIterator();
+
+ while (interpIt.hasNext()) {
+ InterpolationMethod wcpsInterp = interpIt.next();
+
+ meth = new InterpolationMethodType();
+ meth.setValue(wcpsInterp.getInterpolationType());
+ meth.setNullResistance(wcpsInterp.getNullResistance());
+ if ((wcpsInterp.getInterpolationType().equals(interp.getDefaultMethod().getValue()) == false) || (wcpsInterp.getNullResistance().equals(interp.getDefaultMethod().getNullResistance()) == false)) {
+ interp.getOtherMethod().add(meth);
+ }
+ }
+
+ field.setInterpolationMethods(interp);
+ wcsRange.getField().add(field);
+ }
+ desc.setRange(wcsRange);
+
+ // Supported formats for GetCoverage: known rasdaman encoders
+ String[] mimetypes = meta.getMimetypesList();
+
+ for (int i = 0; i < mimetypes.length; i++) {
+ String format = mimetypes[i];
+ desc.getSupportedFormat().add(format);
+ }
+
+ // Available CRSs for current coverage
+ desc.getSupportedCRS().add(DomainElement.IMAGE_CRS);
+ if (cov.getCrs() != null) {
+ desc.getSupportedCRS().add(DomainElement.WGS84_CRS);
+ }
+
+ LOG.trace("Done building the Coverage Description for coverage '" + name + "'.");
+
+ return desc;
+ }
+}
diff --git a/petascope/src/petascope/wcs/server/core/executeGetCapabilities.java b/petascope/src/petascope/wcs/server/core/executeGetCapabilities.java
new file mode 100644
index 0000000..aaa84c0
--- /dev/null
+++ b/petascope/src/petascope/wcs/server/core/executeGetCapabilities.java
@@ -0,0 +1,295 @@
+/*
+ * This file is part of PetaScope.
+ *
+ * PetaScope 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, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * PetaScope 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.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with PetaScope. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * For more information please see <http://www.PetaScope.org>
+ * or contact Peter Baumann via <baumann@rasdaman.com>.
+ *
+ * Copyright 2009 Jacobs University Bremen, Peter Baumann.
+ */
+package petascope.wcs.server.core;
+
+import petascope.wcs.server.exceptions.WCSException;
+import java.sql.SQLException;
+import java.util.Iterator;
+import javax.xml.bind.JAXBElement;
+import javax.xml.namespace.QName;
+import net.opengis.ows.v_1_0_0.CodeType;
+import net.opengis.ows.v_1_0_0.ContactType;
+import net.opengis.ows.v_1_0_0.OnlineResourceType;
+import net.opengis.ows.v_1_0_0.ResponsiblePartySubsetType;
+import net.opengis.ows.v_1_0_0.ServiceProvider;
+import net.opengis.wcs.ows.v_1_1_0.AllowedValues;
+import net.opengis.wcs.ows.v_1_1_0.DCP;
+import net.opengis.wcs.ows.v_1_1_0.DomainType;
+import net.opengis.wcs.ows.v_1_1_0.HTTP;
+import net.opengis.wcs.ows.v_1_1_0.Operation;
+import net.opengis.wcs.ows.v_1_1_0.OperationsMetadata;
+import net.opengis.wcs.ows.v_1_1_0.ServiceIdentification;
+import net.opengis.wcs.ows.v_1_1_0.ValueType;
+import net.opengis.wcs.v_1_1_0.Capabilities;
+import net.opengis.wcs.v_1_1_0.Contents;
+import net.opengis.wcs.v_1_1_0.CoverageSummaryType;
+import net.opengis.wcs.v_1_1_0.GetCapabilities;
+import petascope.wcps.server.core.DbMetadataSource;
+import petascope.wcps.server.core.Metadata;
+import petascope.wcps.server.exceptions.ResourceException;
+
+import javax.xml.XMLConstants;
+import net.opengis.ows.v_1_0_0.AddressType;
+import net.opengis.wcs.ows.v_1_1_0.RequestMethodType;
+import petascope.ConfigManager;
+import petascope.wcs.server.exceptions.InternalSqlException;
+import petascope.wcs.server.exceptions.InvalidParameterValueException;
+import petascope.wcs.server.exceptions.NoApplicableCodeException;
+
+/**
+ * This class takes a WCS GetCapabilities XML request and executes request,
+ * building the corresponding XML respose.
+ *
+ * @author Andrei Aiordachioaie
+ */
+public class executeGetCapabilities {
+
+ private GetCapabilities input;
+ private Capabilities output;
+ private boolean finished;
+ private DbMetadataSource meta;
+
+ /**
+ * Default constructor
+ * @param cap GetCapabilities object, a WCS (or WCPS) request
+ * @param metadataDbPath Path to the "dbparams.properties" file
+ */
+ public executeGetCapabilities(GetCapabilities cap, DbMetadataSource source) throws WCSException {
+ input = cap;
+ output = new Capabilities();
+ meta = source;
+ finished = false;
+ }
+
+ /**
+ * Main method of this class. Retrieves the response to the GetCapabilities
+ * request given to the constructor. If needed, it also calls <b>process()</b>
+ * @return a Capabilities object.
+ * @throws wcs_web_service.WCSException
+ */
+ public Capabilities get() throws WCSException {
+ if (finished == false) {
+ process();
+ }
+ if (finished == false) {
+ throw new NoApplicableCodeException("Could not execute the GetCapabilities request! "
+ + "Please see the other errors...");
+ }
+ return output;
+ }
+
+ /**
+ * Computes the response to the GetCapabilities request given to the constructor.
+ * @throws wcs_web_service.WCSException
+ */
+ public void process() throws WCSException {
+ if (!input.SERVICE.equalsIgnoreCase("WCS")) {
+ throw new InvalidParameterValueException("Service");
+ }
+
+ try {
+ buildField1(); // Service Identification
+ buildField2(); // Service Provider
+ buildField3(); // Operations Metadata
+ buildField4(); // Contents
+
+ finishBuild(); // Add the remaining required attributes
+ finished = true;
+ } catch (SQLException se) {
+ finished = false;
+ throw new InternalSqlException(se.getMessage(), se);
+ }
+
+ }
+
+ /**
+ * Builds the output node "Service Identification"
+ */
+ private void buildField1() {
+ ServiceIdentification ident = new ServiceIdentification();
+ ident.setTitle("PetaScope");
+ ident.setAbstract("PetaScope is a suite of OGC web-services comprising of "
+ + "WCS, WCS-T and WCPS. It has been developed at Jacobs University, and "
+ + "is mentained by the Jacobs University. Copyright Peter Baumann");
+ CodeType code = new CodeType();
+ code.setValue("WCS");
+ ident.setServiceType(code);
+ ident.getServiceTypeVersion().add("1.1.0");
+ ident.setFees("NONE");
+
+ output.setServiceIdentification(ident);
+ }
+
+ /**
+ * Builds the output node "Service Provider"
+ */
+ private void buildField2() {
+ ServiceProvider prov = new ServiceProvider();
+ prov.setProviderName("Jacobs University Bremen");
+ OnlineResourceType site = new OnlineResourceType();
+ site.setHref("http://www.petascope.org/");
+ prov.setProviderSite(site);
+ ResponsiblePartySubsetType resp = new ResponsiblePartySubsetType();
+ resp.setIndividualName("Prof. Dr. Peter Baumann");
+ CodeType role = new CodeType();
+ role.setValue("Project Leader");
+ resp.setRole(role);
+ ContactType contact = new ContactType();
+ AddressType addr = new AddressType();
+ addr.getElectronicMailAddress().add("p.baumann@jacobs-university.de");
+ addr.setCountry("Germany");
+ addr.setCity("Bremen");
+ addr.setPostalCode("28717");
+ contact.setAddress(addr);
+ resp.setContactInfo(contact);
+ prov.setServiceContact(resp);
+
+ output.setServiceProvider(prov);
+ }
+
+ /**
+ * Builds the output node "Operations Metadata"
+ * @throws java.sql.SQLException
+ */
+ private void buildField3() throws SQLException {
+ OperationsMetadata opmeta = new OperationsMetadata();
+
+ Operation op1 = new Operation();
+ op1.setName("GetCapabilities");
+ DomainType postE = new DomainType();
+ postE.setName("PostEncoding");
+ AllowedValues val1 = new AllowedValues();
+ ValueType valX = new ValueType();
+ valX.setValue("XML");
+ val1.getValueOrRange().add(valX);
+ postE.setAllowedValues(val1);
+ op1.getConstraint().add(postE);
+
+ DomainType store = new DomainType();
+ store.setName("store");
+ AllowedValues val2 = new AllowedValues();
+ ValueType v = new ValueType();
+ v.setValue("false");
+ val2.getValueOrRange().add(v);
+ store.setAllowedValues(val2);
+ op1.getParameter().add(store);
+ DCP dcp = new DCP();
+ HTTP http = new HTTP();
+ RequestMethodType post = new RequestMethodType();
+ post.setHref(ConfigManager.PETASCOPE_SERVLET_URL);
+ post.setType("simple");
+ http.getGetOrPost().add(new JAXBElement<RequestMethodType>(
+ new QName("http://www.opengis.net/wcs/1.1/ows", "Post",
+ XMLConstants.DEFAULT_NS_PREFIX), RequestMethodType.class, post));
+ dcp.setHTTP(http);
+ op1.getDCP().add(dcp);
+ DomainType paramOnlyXml = new DomainType();
+ paramOnlyXml.setName("Format");
+ AllowedValues vals = new AllowedValues();
+ ValueType val = new ValueType();
+ val.setValue("text/xml");
+ vals.getValueOrRange().add(val);
+ paramOnlyXml.setAllowedValues(vals);
+ op1.getParameter().add(paramOnlyXml);
+ opmeta.getOperation().add(op1);
+
+ Operation op2 = new Operation();
+ op2.setName("GetCoverage");
+ op2.getConstraint().add(postE); // POST Encoding accepts only XML
+ op2.getParameter().add(store); // Store parameter: not implemented
+ op2.getDCP().add(dcp); // HTTP request URL
+ op2.getConstraint().add(paramOnlyXml);
+ opmeta.getOperation().add(op2);
+
+ Operation op3 = new Operation();
+ op3.setName("DescribeCoverage");
+ op3.getConstraint().add(postE); // POST Encoding accepts only XML
+ op3.getParameter().add(store); // Store parameter: not implemented
+ op3.getDCP().add(dcp); // HTTP request URL
+ op3.getConstraint().add(paramOnlyXml);
+ opmeta.getOperation().add(op3);
+
+ Operation op4 = new Operation();
+ op4.setName("ProcessCoverages");
+ op4.getConstraint().add(postE); // POST Encoding accepts only XML
+ op4.getParameter().add(store); // Store parameter: not implemented
+ op4.getDCP().add(dcp); // HTTP request URL
+ op4.getConstraint().add(paramOnlyXml);
+ opmeta.getOperation().add(op4);
+
+ Operation op5 = new Operation();
+ op5.setName("Transaction");
+ op5.getConstraint().add(postE); // POST Encoding accepts only XML
+ op5.getParameter().add(store); // Store parameter: not implemented
+ op5.getDCP().add(dcp); // HTTP request URL
+ op5.getConstraint().add(paramOnlyXml);
+ opmeta.getOperation().add(op5);
+
+ output.setOperationsMetadata(opmeta);
+ }
+
+ /**
+ * Builds the output node "Contents"
+ * @throws java.sql.SQLException
+ */
+ private void buildField4() {
+ Contents cont = new Contents();
+ Iterator<String> coverages = null;
+
+ try {
+ coverages = meta.coverages().iterator();
+ } catch (ResourceException e) {
+ }
+ while (coverages.hasNext()) {
+ Metadata metadata = null;
+ try {
+ metadata = meta.read(coverages.next());
+ } catch (Exception e) {
+ }
+ String covName = metadata.getCoverageName();
+ CoverageSummaryType sum = new CoverageSummaryType();
+ sum.setAbstract(metadata.getAbstract());
+ sum.setTitle(metadata.getTitle());
+
+ // code holds the coverage value
+ CodeType code = new CodeType();
+ code.setValue(covName);
+ // code is encapsulated in JAXBElement "jelem"
+ JAXBElement<String> jelem =
+ new JAXBElement<String>(
+ new QName("http://www.opengis.net/wcs/1.1", "Identifier", XMLConstants.DEFAULT_NS_PREFIX),
+ String.class, covName);
+ // Insert "jelem" into this coveragesummary
+ sum.getRest().add(jelem);
+
+ // Add this CoverageSummary to the list of coverage summaries, to make up the Contents
+ cont.getCoverageSummary().add(sum);
+ }
+
+ output.setContents(cont);
+ }
+
+ private void finishBuild() {
+ /* WCS Standard Version ! */
+ output.setVersion("1.1.0");
+ }
+}