diff --git a/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTPublisher.java b/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTPublisher.java
index 9b703ce..2691b12 100644
--- a/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTPublisher.java
+++ b/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTPublisher.java
@@ -26,6 +26,7 @@ package it.geosolutions.geoserver.rest;
import it.geosolutions.geoserver.rest.decoder.RESTCoverageList;
import it.geosolutions.geoserver.rest.decoder.RESTCoverageStore;
+import it.geosolutions.geoserver.rest.decoder.RESTStructuredCoverageGranulesList;
import it.geosolutions.geoserver.rest.decoder.utils.NameLinkElem;
import it.geosolutions.geoserver.rest.encoder.GSBackupEncoder;
import it.geosolutions.geoserver.rest.encoder.GSLayerEncoder;
@@ -37,9 +38,11 @@ import it.geosolutions.geoserver.rest.encoder.GSResourceEncoder.ProjectionPolicy
import it.geosolutions.geoserver.rest.encoder.GSWorkspaceEncoder;
import it.geosolutions.geoserver.rest.encoder.coverage.GSCoverageEncoder;
import it.geosolutions.geoserver.rest.encoder.feature.GSFeatureTypeEncoder;
+import it.geosolutions.geoserver.rest.manager.GeoServerRESTStructuredCoverageGridReaderManager;
import java.io.File;
import java.io.FileNotFoundException;
+import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
@@ -2537,7 +2540,7 @@ public class GeoServerRESTPublisher {
*
* configured - Only setup or configured feature types are returned. This is the default value. available - Only unconfigured feature types
* (not yet setup) but are available from the specified datastore will be returned. available_with_geom - Same as available but only
- * includes feature types that have a geometry attribute. all - The union of configured and available.
+ * includes feature types that have a geometry granule. all - The union of configured and available.
*
*
* @return true if success
@@ -2647,4 +2650,94 @@ public class GeoServerRESTPublisher {
return URLEncoder.encode(s);
// }
}
+
+ // ==> StructuredCoverageGridReader
+
+ /**
+ * Create a store or harvest the coverage from the provided external path.
+ *
+ * @param workspace the GeoServer workspace
+ * @param coverageStore the GeoServer coverageStore
+ * @param format the format of the file to upload
+ * @param the absolut path to the file to upload
+ *
+ * @return true if the call succeeds or false otherwise.
+ */
+ public boolean createOrHarvestExternal(String workspace, String coverageStore, String format, String path) {
+ try {
+ GeoServerRESTStructuredCoverageGridReaderManager manager =
+ new GeoServerRESTStructuredCoverageGridReaderManager(new URL(restURL), gsuser, gspass);
+ return manager.createOrHarvestExternal(workspace, coverageStore, format, path);
+ } catch (IllegalArgumentException e) {
+ if(LOGGER.isInfoEnabled()){
+ LOGGER.info(e.getLocalizedMessage(),e);
+ }
+ } catch (MalformedURLException e) {
+ if(LOGGER.isInfoEnabled()){
+ LOGGER.info(e.getLocalizedMessage(),e);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Remove a granule from a structured coverage by id.
+ *
+ * @param workspace the GeoServer workspace
+ * @param coverageStore the GeoServer coverageStore
+ * @param coverage the name of the target coverage from which we are going to remove
+ * @param filter the absolute path to the file to upload
+ *
+ * @return null in case the call does not succeed, or an instance of {@link RESTStructuredCoverageGranulesList}.
+ *
+ * @throws MalformedURLException
+ * @throws UnsupportedEncodingException
+ */
+ public boolean removeGranuleById(final String workspace, String coverageStore, String coverage, String granuleId) {
+ try {
+ GeoServerRESTStructuredCoverageGridReaderManager manager =
+ new GeoServerRESTStructuredCoverageGridReaderManager(new URL(restURL), gsuser, gspass);
+ return manager.removeGranuleById(workspace, coverageStore, coverage, granuleId);
+ } catch (IllegalArgumentException e) {
+ if(LOGGER.isInfoEnabled()){
+ LOGGER.info(e.getLocalizedMessage(),e);
+ }
+ } catch (MalformedURLException e) {
+ if(LOGGER.isInfoEnabled()){
+ LOGGER.info(e.getLocalizedMessage(),e);
+ }
+ }
+ return false;
+ }
+ /**
+ * Remove granules from a structured coverage, by providing a CQL filter.
+ *
+ * @param workspace the GeoServer workspace
+ * @param coverageStore the GeoServer coverageStore
+ * @param coverage the name of the target coverage from which we are going to remove
+ * @param filter the absolute path to the file to upload
+ *
+ * @return null in case the call does not succeed, or an instance of {@link RESTStructuredCoverageGranulesList}.
+ *
+ * @throws MalformedURLException
+ * @throws UnsupportedEncodingException
+ */
+ public boolean removeGranulesByCQL(final String workspace, String coverageStore,String coverage, String filter) throws UnsupportedEncodingException{
+ try {
+ GeoServerRESTStructuredCoverageGridReaderManager manager =
+ new GeoServerRESTStructuredCoverageGridReaderManager(new URL(restURL), gsuser, gspass);
+ return manager.removeGranulesByCQL(workspace, coverageStore, coverage, filter);
+ } catch (IllegalArgumentException e) {
+ if(LOGGER.isInfoEnabled()){
+ LOGGER.info(e.getLocalizedMessage(),e);
+ }
+ } catch (MalformedURLException e) {
+ if(LOGGER.isInfoEnabled()){
+ LOGGER.info(e.getLocalizedMessage(),e);
+ }
+ }
+ return false;
+
+ }
+
}
diff --git a/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTReader.java b/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTReader.java
index 0cf9846..95654ba 100644
--- a/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTReader.java
+++ b/src/main/java/it/geosolutions/geoserver/rest/GeoServerRESTReader.java
@@ -39,16 +39,20 @@ import it.geosolutions.geoserver.rest.decoder.RESTLayerList;
import it.geosolutions.geoserver.rest.decoder.RESTNamespace;
import it.geosolutions.geoserver.rest.decoder.RESTNamespaceList;
import it.geosolutions.geoserver.rest.decoder.RESTResource;
+import it.geosolutions.geoserver.rest.decoder.RESTStructuredCoverageGranulesList;
+import it.geosolutions.geoserver.rest.decoder.RESTStructuredCoverageIndexSchema;
import it.geosolutions.geoserver.rest.decoder.RESTStyleList;
import it.geosolutions.geoserver.rest.decoder.RESTWorkspaceList;
+import it.geosolutions.geoserver.rest.manager.GeoServerRESTStructuredCoverageGridReaderManager;
+import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -575,4 +579,101 @@ public class GeoServerRESTReader {
return names;
}
+ /**
+ * Get information about a granule for a structured coverage.
+ *
+ * @param workspace the GeoServer workspace
+ * @param coverageStore the GeoServer coverageStore
+ * @param format the format of the file to upload
+ * @param the absolute path to the file to upload
+ * @param id the ID of the granule to get information for
+ *
+ * @return null in case the call does not succeed, or an instance of {@link RESTStructuredCoverageGranulesList}.
+ *
+ * @throws MalformedURLException
+ * @throws UnsupportedEncodingException
+ */
+ public RESTStructuredCoverageGranulesList getGranuleById(final String workspace,
+ String coverageStore, String coverage, String id) throws MalformedURLException,
+ UnsupportedEncodingException {
+ try {
+ GeoServerRESTStructuredCoverageGridReaderManager manager =
+ new GeoServerRESTStructuredCoverageGridReaderManager(new URL(baseurl), username, password);
+ return manager.getGranuleById(workspace, coverageStore, coverage, id);
+ } catch (IllegalArgumentException e) {
+ if(LOGGER.isInfoEnabled()){
+ LOGGER.info(e.getLocalizedMessage(),e);
+ }
+ } catch (MalformedURLException e) {
+ if(LOGGER.isInfoEnabled()){
+ LOGGER.info(e.getLocalizedMessage(),e);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get information about the schema of the index for a structured coverage.
+ *
+ * @param workspace the GeoServer workspace
+ * @param coverageStore the GeoServer coverageStore
+ * @param format the format of the file to upload
+ *
+ * @return null in case the call does not succeed, or an instance of {@link RESTStructuredCoverageGranulesList}.
+ *
+ * @throws MalformedURLException
+ * @throws UnsupportedEncodingException
+ */
+ @Test
+ public RESTStructuredCoverageIndexSchema getGranuleIndexSchema(final String workspace, String coverageStore, String coverage) throws MalformedURLException {
+ try {
+ GeoServerRESTStructuredCoverageGridReaderManager manager =
+ new GeoServerRESTStructuredCoverageGridReaderManager(new URL(baseurl), username, password);
+ return manager.getGranuleIndexSchema(workspace, coverageStore, coverage);
+ } catch (IllegalArgumentException e) {
+ if(LOGGER.isInfoEnabled()){
+ LOGGER.info(e.getLocalizedMessage(),e);
+ }
+ } catch (MalformedURLException e) {
+ if(LOGGER.isInfoEnabled()){
+ LOGGER.info(e.getLocalizedMessage(),e);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Get information about the granules for a coverage with optional filter and paging.
+ *
+ * @param workspace the GeoServer workspace
+ * @param coverageStore the GeoServer coverageStore
+ * @param coverage the name of the target coverage
+ * @param filter the format of the file to upload, can be null to include all the granules
+ * @param offset the start page, can be null or an integer
+ * @param limit the dimension of the page, can be null or a positive integer
+ *
+ * @return null in case the call does not succeed, or an instance of {@link RESTStructuredCoverageGranulesList}.
+ *
+ * @throws MalformedURLException
+ * @throws UnsupportedEncodingException
+ */
+ @Test
+ public RESTStructuredCoverageGranulesList getGranules(final String workspace, String coverageStore, String coverage, String filter, String offset, String limit)
+ throws MalformedURLException, UnsupportedEncodingException {
+ try {
+ GeoServerRESTStructuredCoverageGridReaderManager manager =
+ new GeoServerRESTStructuredCoverageGridReaderManager(new URL(baseurl), username, password);
+ return manager.getGranules(workspace, coverageStore, coverage, filter, offset, limit);
+ } catch (IllegalArgumentException e) {
+ if(LOGGER.isInfoEnabled()){
+ LOGGER.info(e.getLocalizedMessage(),e);
+ }
+ } catch (MalformedURLException e) {
+ if(LOGGER.isInfoEnabled()){
+ LOGGER.info(e.getLocalizedMessage(),e);
+ }
+ }
+ return null;
+ }
+
}
diff --git a/src/main/java/it/geosolutions/geoserver/rest/HTTPUtils.java b/src/main/java/it/geosolutions/geoserver/rest/HTTPUtils.java
index a08da22..ad8e2d0 100644
--- a/src/main/java/it/geosolutions/geoserver/rest/HTTPUtils.java
+++ b/src/main/java/it/geosolutions/geoserver/rest/HTTPUtils.java
@@ -336,7 +336,7 @@ public class HTTPUtils {
InputStream is = httpMethod.getResponseBodyAsStream();
response = IOUtils.toString(is);
IOUtils.closeQuietly(is);
- if (response.trim().equals("")) { // sometimes gs rest fails
+ if (response.trim().equals("")) {
if (LOGGER.isDebugEnabled())
LOGGER
.debug("ResponseBody is empty (this may be not an error since we just performed a DELETE call)");
@@ -467,14 +467,14 @@ public class HTTPUtils {
/**
* @param str a string array
- * @return create a StringBuffer appending all the passed arguments
+ * @return create a StringBuilder appending all the passed arguments
*/
- public static StringBuffer append(String ... str){
+ public static StringBuilder append(String ... str){
if (str==null){
return null;
}
- StringBuffer buf=new StringBuffer();
+ StringBuilder buf=new StringBuilder();
for (String s: str){
if (s!=null)
buf.append(s);
@@ -488,12 +488,12 @@ public class HTTPUtils {
* @param str strings to append
* @return the base URL with parameters attached
*/
- public static StringBuffer append(URL base, String ... str){
+ public static StringBuilder append(URL base, String ... str){
if (str==null){
return append(base.toString());
}
- StringBuffer buf=new StringBuffer(base.toString());
+ StringBuilder buf=new StringBuilder(base.toString());
for (String s: str){
if (s!=null)
buf.append(s);
diff --git a/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTStructuredCoverageGranulesList.java b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTStructuredCoverageGranulesList.java
new file mode 100644
index 0000000..80d612a
--- /dev/null
+++ b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTStructuredCoverageGranulesList.java
@@ -0,0 +1,230 @@
+/*
+ * GeoServer-Manager - Simple Manager Library for GeoServer
+ *
+ * Copyright (C) 2007,2011 GeoSolutions S.A.S.
+ * http://www.geo-solutions.it
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package it.geosolutions.geoserver.rest.decoder;
+
+import it.geosolutions.geoserver.rest.decoder.utils.JDOMBuilder;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.jdom.Element;
+import org.jdom.Namespace;
+
+/**
+ * This decode turns index format for a GeoServer StructuredGridCoverageReader into something
+ * useful, giving access to the definition of the single attributes.
+ *
+ *
This is the XML REST representation: + *
+ {@code
+
+
+
+
+
+
+ 5.0
+ 45.0
+
+
+ 14.875
+ 50.9375
+
+
+
+
+
+
+
+
+
+ 5.0,45.0 5.0,50.9375 14.875,50.9375 14.875,45.0 5.0,45.0
+
+
+
+
+ ..\\polyphemus\\polyphemus_20130302.nc
+ 672
+ 2013-03-01T23:00:00Z
+ 10.0
+ 2013-03-01T23:00:00Z
+ 2013-04-08T05:40:29.061Z
+
+
+
+
+}
+ * @author Simone Giannecchini, GeoSolutions SAS
+ *
+ */
+public class RESTStructuredCoverageGranulesList implements IterableThis is the XML REST representation: + *
+ {@code
+
+
+
+
+
+
+ 5.0,45.0 5.0,50.9375 14.875,50.9375 14.875,45.0 5.0,45.0
+
+
+
+
+ polyphemus_20130301.nc
+ 672
+ 2013-02-28T23:00:00Z
+ 10.0
+ 2013-02-28T23:00:00Z
+ 2013-04-08T06:18:41.597Z
+
+
+
+ * @author Simone Giannecchini, GeoSolutions SAS
+ *
+ */
+ public static class RESTStructuredCoverageGranule {
+
+ protected final Element granule;
+
+ private final String fid;
+
+ private final List children;
+
+ @SuppressWarnings("unchecked")
+ public RESTStructuredCoverageGranule(Element elem) {
+ if(!elem.getName().equals("featureMember")){
+ throw new IllegalStateException("Root element should be gml:featureMember for a granule");
+ }
+ Element feature = (Element) elem.getChildren().get(0);
+ if(feature==null){
+ throw new IllegalStateException("Unable to find feature element for this granule");
+ }
+ this.granule = feature;
+ this.fid=granule.getAttribute("fid").getValue();
+ this.children=granule.getChildren();
+
+ }
+
+ public String getAttributeByName(String name) {
+ return granule.getChildTextTrim(name,null);
+ }
+
+ public String getAttributeByIndex(int index) {
+ return children.get(index).getValue();
+ }
+
+ @SuppressWarnings("unchecked")
+ public Iterator getAttributesIterator() {
+ return granule.getChildren().iterator();
+ }
+
+ /**
+ * @return the fid
+ */
+ public String getFid() {
+ return fid;
+ }
+ }
+
+}
diff --git a/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTStructuredCoverageIndexSchema.java b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTStructuredCoverageIndexSchema.java
new file mode 100644
index 0000000..b19e0e6
--- /dev/null
+++ b/src/main/java/it/geosolutions/geoserver/rest/decoder/RESTStructuredCoverageIndexSchema.java
@@ -0,0 +1,212 @@
+/*
+ * GeoServer-Manager - Simple Manager Library for GeoServer
+ *
+ * Copyright (C) 2007,2011 GeoSolutions S.A.S.
+ * http://www.geo-solutions.it
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package it.geosolutions.geoserver.rest.decoder;
+
+import it.geosolutions.geoserver.rest.decoder.utils.JDOMBuilder;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.jdom.Element;
+
+/**
+ * This decode turns index format for a GeoServer StructuredGridCoverageReader into something
+ * useful, giving access to the definition of the single attributes.
+ *
+ * This is the XML REST representation:
+ *
+ {@code
+
+
+
+
+ the_geom
+ 0
+ 1
+ true
+ com.vividsolutions.jts.geom.Polygon
+
+
+ location
+ 0
+ 1
+ true
+ java.lang.String
+
+
+ imageindex
+ 0
+ 1
+ true
+ java.lang.Integer
+
+
+ time
+ 0
+ 1
+ true
+ java.sql.Timestamp
+
+
+ elevation
+ 0
+ 1
+ true
+ java.lang.Double
+
+
+ fileDate
+ 0
+ 1
+ true
+ java.sql.Timestamp
+
+
+ updated
+ 0
+ 1
+ true
+ java.sql.Timestamp
+
+
+
+
+}
+ * @author Simone Giannecchini, GeoSolutions SAS
+ *
+ */
+public class RESTStructuredCoverageIndexSchema implements Iterable {
+
+ private final List attributeList;
+
+ /**
+ * @param list
+ */
+ @SuppressWarnings("unchecked")
+ protected RESTStructuredCoverageIndexSchema(Element schema) {
+
+ // check ordering of elements
+ if(!schema.getName().equals("Schema")){
+ throw new IllegalStateException("Root element should be Schema");
+ }
+ Element attributes = schema.getChild("attributes");
+ if(attributes==null){
+ throw new IllegalStateException("Root element should be Schema");
+ }
+
+ List tmpList = new ArrayList();
+ for(Element el : (List)attributes.getChildren()){
+ tmpList.add(new RESTStructuredCoverageIndexAttribute(el));
+ }
+ attributeList = Collections.unmodifiableList(tmpList);
+ }
+
+ public static RESTStructuredCoverageIndexSchema build(String response) {
+ if(response == null)
+ return null;
+
+ Element pb = JDOMBuilder.buildElement(response);
+ if(pb != null){
+ return new RESTStructuredCoverageIndexSchema(pb);
+ } else {
+ return null;
+ }
+ }
+
+ public int size() {
+ return attributeList.size();
+ }
+
+ public boolean isEmpty() {
+ return attributeList.isEmpty();
+ }
+
+ public RESTStructuredCoverageIndexAttribute get(int index) {
+ return attributeList.get(index);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Iterable#iterator()
+ */
+ @Override
+ public Iterator iterator() {
+ return attributeList.iterator();
+ }
+
+ /**
+ * Generic granule of the index.
+ *
+ * This is the XML REST representation:
+ *
+ {@code
+
+ the_geom
+ 0
+ 1
+ true
+ com.vividsolutions.jts.geom.Polygon
+
+ * @author Simone Giannecchini, GeoSolutions SAS
+ *
+ */
+ public static class RESTStructuredCoverageIndexAttribute {
+ protected final Element attribute;
+
+ public RESTStructuredCoverageIndexAttribute(Element elem) {
+ this.attribute = elem;
+ }
+
+ public String getName() {
+ return attribute.getChildTextTrim("name");
+ }
+
+ public String getMinOccurs() {
+ return attribute.getChildTextTrim("minOccurs");
+ }
+
+ public String getMaxOccurs() {
+ return attribute.getChildTextTrim("maxOccurs");
+ }
+
+ public String getNillable() {
+ return attribute.getChildTextTrim("nillable");
+ }
+
+ public String getBinding() {
+ return attribute.getChildTextTrim("binding");
+ }
+
+ @Override
+ public String toString() {
+ return "RESTStructuredCoverageGranule [getName()=" + getName()
+ + ", getMinOccurs()=" + getMinOccurs() + ", getMaxOccurs()=" + getMaxOccurs()
+ + ", getNillable()=" + getNillable() + ", getBinding()=" + getBinding() + "]";
+ }
+
+ }
+
+}
diff --git a/src/main/java/it/geosolutions/geoserver/rest/manager/GeoServerRESTStoreManager.java b/src/main/java/it/geosolutions/geoserver/rest/manager/GeoServerRESTStoreManager.java
index 34dad05..5aad7be 100644
--- a/src/main/java/it/geosolutions/geoserver/rest/manager/GeoServerRESTStoreManager.java
+++ b/src/main/java/it/geosolutions/geoserver/rest/manager/GeoServerRESTStoreManager.java
@@ -107,7 +107,7 @@ public class GeoServerRESTStoreManager extends GeoServerRESTAbstractManager {
// if (workspace.isEmpty() || storename.isEmpty())
// throw new IllegalArgumentException("Arguments may not be empty!");
- final StringBuffer url=HTTPUtils.append(restURL,"/rest/workspaces/",workspace,"/", store.getStoreType().toString(), "/",store.getName());
+ final StringBuilder url=HTTPUtils.append(restURL,"/rest/workspaces/",workspace,"/", store.getStoreType().toString(), "/",store.getName());
if (recurse)
url.append("?recurse=true");
final URL deleteStore = new URL(url.toString());
diff --git a/src/main/java/it/geosolutions/geoserver/rest/manager/GeoServerRESTStructuredCoverageGridReaderManager.java b/src/main/java/it/geosolutions/geoserver/rest/manager/GeoServerRESTStructuredCoverageGridReaderManager.java
new file mode 100644
index 0000000..44b3ccc
--- /dev/null
+++ b/src/main/java/it/geosolutions/geoserver/rest/manager/GeoServerRESTStructuredCoverageGridReaderManager.java
@@ -0,0 +1,354 @@
+/*
+ * GeoServer-Manager - Simple Manager Library for GeoServer
+ *
+ * Copyright (C) 2007,2012 GeoSolutions S.A.S.
+ * http://www.geo-solutions.it
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package it.geosolutions.geoserver.rest.manager;
+
+import it.geosolutions.geoserver.rest.GeoServerRESTPublisher.UploadMethod;
+import it.geosolutions.geoserver.rest.HTTPUtils;
+import it.geosolutions.geoserver.rest.decoder.RESTStructuredCoverageGranulesList;
+import it.geosolutions.geoserver.rest.decoder.RESTStructuredCoverageIndexSchema;
+
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLEncoder;
+
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Manage GeoTools StructuredCoverageGridReader. It allows to create a store from a file or harvest
+ * the coverages contained in a file, to delete granules from an existing coverage and eventually
+ * to get information about the granules insi a StructuredCoverageGridReader.
+ *
+ * @author Simone Giannecchini, GeoSolutions
+ */
+public class GeoServerRESTStructuredCoverageGridReaderManager extends GeoServerRESTAbstractManager {
+
+ /**
+ * Default logger
+ */
+ private final static Logger LOGGER = LoggerFactory.getLogger(GeoServerRESTStructuredCoverageGridReaderManager.class);
+
+ /**
+ * Default constructor.
+ *
+ * @param restURL GeoServer REST API endpoint
+ * @param username GeoServer REST API authorized username
+ * @param password GeoServer REST API password for the former username
+ * @throws IllegalArgumentException
+ */
+ public GeoServerRESTStructuredCoverageGridReaderManager(URL restURL, String username, String password) throws IllegalArgumentException, MalformedURLException{
+ super(restURL, username, password);
+ }
+
+ /**
+ * Create a store or harvest the coverage from the provided external path.
+ *
+ * @param workspace the GeoServer workspace
+ * @param coverageStore the GeoServer coverageStore
+ * @param format the format of the file to upload
+ * @param the absolut path to the file to upload
+ *
+ * @return true if the call succeeds or false otherwise.
+ */
+ public boolean createOrHarvestExternal(String workspace, String coverageStore, String format, String path) {
+ // checks
+ checkString(workspace);
+ checkString(coverageStore);
+ checkString(format);
+ checkString(path);
+
+ // create URL
+ String sUrl = HTTPUtils.append(restURL, "/rest/workspaces/", workspace, "/coveragestores/",coverageStore,"/",UploadMethod.EXTERNAL.toString(),".", format).toString();
+
+ // POST request
+ String result = HTTPUtils.post(sUrl, "file:/"+path, "text/plain", gsuser, gspass);
+ return result != null;
+ }
+
+ /**
+ * Check the provided string for not being null or empty.
+ *
+ *
+ * It throws an exception in case the string is either null or empty.
+ *
+ * @param string the {@link String} to be checked
+ */
+ private static void checkString(String string) {
+ if(string==null){
+ throw new NullPointerException("Provided string is is null!");
+ }
+ if(string.length()<=0){
+ throw new IllegalArgumentException("Provided string is is empty!");
+ }
+
+ }
+
+ /**
+ * Remove granules from a structured coverage, by providing a CQL filter.
+ *
+ * @param workspace the GeoServer workspace
+ * @param coverageStore the GeoServer coverageStore
+ * @param coverage the name of the target coverage from which we are going to remove
+ * @param filter the absolute path to the file to upload
+ *
+ * @return null in case the call does not succeed, or an instance of {@link RESTStructuredCoverageGranulesList}.
+ *
+ * @throws MalformedURLException
+ * @throws UnsupportedEncodingException
+ */
+ public boolean removeGranulesByCQL(final String workspace, String coverageStore,String coverage, String filter) throws UnsupportedEncodingException{
+ // checks
+ checkString(workspace);
+ checkString(coverage);
+ checkString(filter);
+ checkString(coverageStore);
+
+ // does it exist?
+ RESTStructuredCoverageGranulesList granulesList=null;
+ try {
+ granulesList = getGranules(workspace, coverageStore, coverageStore, filter, null, "1");
+ } catch (MalformedURLException e) {
+ if(LOGGER.isTraceEnabled()){
+ LOGGER.trace(e.getMessage(), e);
+ }
+ } catch (UnsupportedEncodingException e) {
+ if(LOGGER.isTraceEnabled()){
+ LOGGER.trace(e.getMessage(), e);
+ }
+ }
+ if (granulesList == null||granulesList.isEmpty()) {
+ if(LOGGER.isTraceEnabled()){
+ LOGGER.trace("Granules for filter: "+filter+ " does not exist for coverage "+coverage);
+ }
+ return true; // nothing to remove
+ }
+
+ // method
+ String sUrl = HTTPUtils.append(restURL, "/rest/workspaces/", workspace, "/coveragestores", "/",coverageStore,"/coverages/",coverage,"/index/granules?filter=",URLEncoder.encode(filter, "UTF-8")).toString();
+ if(!HTTPUtils.delete(sUrl, gsuser, gspass)){
+ return false;
+ }
+
+ // does it exist?
+ granulesList=null;
+ try {
+ granulesList = getGranules(workspace, coverageStore, coverageStore, filter, null, "1");
+ } catch (MalformedURLException e) {
+ if(LOGGER.isTraceEnabled()){
+ LOGGER.trace(e.getMessage(), e);
+ }
+ } catch (UnsupportedEncodingException e) {
+ if(LOGGER.isTraceEnabled()){
+ LOGGER.trace(e.getMessage(), e);
+ }
+ }
+ if (granulesList == null||granulesList.isEmpty()) {
+ return true; // nothing to remove
+ }
+ return false;
+ }
+
+ /**
+ * Remove a granule from a structured coverage by id.
+ *
+ * @param workspace the GeoServer workspace
+ * @param coverageStore the GeoServer coverageStore
+ * @param coverage the name of the target coverage from which we are going to remove
+ * @param filter the absolute path to the file to upload
+ *
+ * @return null in case the call does not succeed, or an instance of {@link RESTStructuredCoverageGranulesList}.
+ *
+ * @throws MalformedURLException
+ * @throws UnsupportedEncodingException
+ */
+ public boolean removeGranuleById(final String workspace, String coverageStore, String coverage, String granuleId) {
+ // checks
+ checkString(workspace);
+ checkString(coverage);
+ checkString(granuleId);
+ checkString(coverageStore);
+
+ // does it exist?
+ RESTStructuredCoverageGranulesList granule=null;
+ try {
+ granule = getGranuleById(workspace, coverageStore, coverage, granuleId);
+ } catch (MalformedURLException e) {
+ if(LOGGER.isTraceEnabled()){
+ LOGGER.trace(e.getMessage(), e);
+ }
+ } catch (UnsupportedEncodingException e) {
+ if(LOGGER.isTraceEnabled()){
+ LOGGER.trace(e.getMessage(), e);
+ }
+ }
+ if (granule == null) {
+ if(LOGGER.isTraceEnabled()){
+ LOGGER.trace("Granule for id: "+granuleId+ " does not exist for coverage "+coverage);
+ }
+ return true; // nothing to remove
+ }
+
+ // delete
+ String sUrl = HTTPUtils.append(restURL, "/rest/workspaces/", workspace, "/coveragestores",
+ "/", coverageStore, "/coverages/", coverage, "/index/granules/", granuleId)
+ .toString();
+ if(!HTTPUtils.delete(sUrl, gsuser, gspass)){
+ return false;
+ }
+
+ // has it been canceled?
+ // does it exist?
+ granule=null;
+ try {
+ granule = getGranuleById(workspace, coverageStore, coverage, granuleId);
+ } catch (MalformedURLException e) {
+ if(LOGGER.isTraceEnabled()){
+ LOGGER.trace(e.getMessage(), e);
+ }
+ } catch (UnsupportedEncodingException e) {
+ if(LOGGER.isTraceEnabled()){
+ LOGGER.trace(e.getMessage(), e);
+ }
+ }
+ if (granule == null) {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Get information about the schema of the index for a structured coverage.
+ *
+ * @param workspace the GeoServer workspace
+ * @param coverageStore the GeoServer coverageStore
+ * @param format the format of the file to upload
+ *
+ * @return null in case the call does not succeed, or an instance of {@link RESTStructuredCoverageGranulesList}.
+ *
+ * @throws MalformedURLException
+ * @throws UnsupportedEncodingException
+ */
+ @Test
+ public RESTStructuredCoverageIndexSchema getGranuleIndexSchema(final String workspace, String coverageStore, String coverage) throws MalformedURLException {
+ // checks
+ checkString(workspace);
+ checkString(coverage);
+ checkString(coverageStore);
+
+ // create URL and then call it
+ String sUrl = HTTPUtils.append(restURL, "/rest/workspaces/", workspace, "/coveragestores/", coverageStore, "/coverages/", coverage, "/index.xml").toString();
+ String result = HTTPUtils.get(sUrl, gsuser, gspass);
+ if (result != null) {
+ return RESTStructuredCoverageIndexSchema.build(result);
+ }
+ return null;
+ }
+
+ /**
+ * Get information about the granules for a coverage with optional filter and paging.
+ *
+ * @param workspace the GeoServer workspace
+ * @param coverageStore the GeoServer coverageStore
+ * @param coverage the name of the target coverage
+ * @param filter the format of the file to upload, can be null to include all the granules
+ * @param offset the start page, can be null or an integer
+ * @param limit the dimension of the page, can be null or a positive integer
+ *
+ * @return null in case the call does not succeed, or an instance of {@link RESTStructuredCoverageGranulesList}.
+ *
+ * @throws MalformedURLException
+ * @throws UnsupportedEncodingException
+ */
+ @Test
+ public RESTStructuredCoverageGranulesList getGranules(final String workspace, String coverageStore, String coverage, String filter, String offset, String limit)
+ throws MalformedURLException, UnsupportedEncodingException {
+ // checks
+ checkString(workspace);
+ checkString(coverage);
+ checkString(coverageStore);
+
+ // method
+ boolean append = false;
+ String sUrl = HTTPUtils.append(restURL, "/rest/workspaces/", workspace, "/coveragestores/", coverageStore, "/coverages/", coverage, "/index/granules.xml").toString();
+ if (filter != null && !filter.isEmpty()) {
+ append = true;
+ sUrl = HTTPUtils.append(sUrl, "?filter=", URLEncoder.encode(filter, "UTF-8")).toString();
+ }
+ if (offset != null && !offset.isEmpty()) {
+ sUrl = HTTPUtils.append(sUrl, append ? "&offset=" : "?offset=", offset).toString();
+ append = true;
+ }
+ if (limit != null && !limit.isEmpty()) {
+ sUrl = HTTPUtils.append(sUrl, append ? "&limit=" : "?limit=", limit).toString();
+ append = true;
+ }
+ String result = HTTPUtils.get(sUrl, gsuser, gspass);
+ if (result != null) {
+ return RESTStructuredCoverageGranulesList.build(result);
+ }
+ return null;
+ }
+
+ /**
+ * Get information about a granule for a structured coverage.
+ *
+ * @param workspace the GeoServer workspace
+ * @param coverageStore the GeoServer coverageStore
+ * @param format the format of the file to upload
+ * @param the absolute path to the file to upload
+ * @param id the ID of the granule to get information for
+ *
+ * @return null in case the call does not succeed, or an instance of {@link RESTStructuredCoverageGranulesList}.
+ *
+ * @throws MalformedURLException
+ * @throws UnsupportedEncodingException
+ */
+ @Test
+ public RESTStructuredCoverageGranulesList getGranuleById(final String workspace,
+ String coverageStore, String coverage, String id) throws MalformedURLException,
+ UnsupportedEncodingException {
+ // checks
+ checkString(workspace);
+ checkString(coverage);
+ checkString(coverageStore);
+ checkString(id);
+ try{
+ Integer.parseInt(id);
+ }catch (NumberFormatException e) {
+ throw new IllegalArgumentException(e);
+ }
+
+ // method
+ String sUrl = HTTPUtils.append(restURL, "/rest/workspaces/", workspace, "/coveragestores/", coverageStore, "/coverages/", coverage, "/index/granules/", id, ".xml").toString();
+ String result = HTTPUtils.get(sUrl, gsuser, gspass);
+ if (result != null) {
+ return RESTStructuredCoverageGranulesList.build(result);
+ }
+ return null;
+ }
+}
diff --git a/src/test/java/it/geosolutions/geoserver/rest/manager/GeoServerRESTStructuredCoverageGridReaderManagerTest.java b/src/test/java/it/geosolutions/geoserver/rest/manager/GeoServerRESTStructuredCoverageGridReaderManagerTest.java
new file mode 100644
index 0000000..e71f2f8
--- /dev/null
+++ b/src/test/java/it/geosolutions/geoserver/rest/manager/GeoServerRESTStructuredCoverageGridReaderManagerTest.java
@@ -0,0 +1,136 @@
+/*
+ * GeoTools - The Open Source Java GIS Toolkit
+ * http://geotools.org
+ *
+ * (C) 2002-2011, Open Source Geospatial Foundation (OSGeo)
+ *
+ * This library 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;
+ * version 2.1 of the License.
+ *
+ * This library 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.
+ */
+package it.geosolutions.geoserver.rest.manager;
+
+import it.geosolutions.geoserver.rest.datastore.StoreIntegrationTest;
+import it.geosolutions.geoserver.rest.decoder.RESTStructuredCoverageGranulesList;
+import it.geosolutions.geoserver.rest.decoder.RESTStructuredCoverageGranulesList.RESTStructuredCoverageGranule;
+import it.geosolutions.geoserver.rest.decoder.RESTStructuredCoverageIndexSchema;
+import it.geosolutions.geoserver.rest.decoder.RESTStructuredCoverageIndexSchema.RESTStructuredCoverageIndexAttribute;
+import it.geosolutions.geoserver.rest.encoder.GSAbstractStoreEncoder;
+
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Iterator;
+
+import junit.framework.Assert;
+
+import org.junit.Test;
+
+/**
+ * @author Simone Giannecchini, simone.giannecchini@geo-solutions.it
+ *
+ */
+public class GeoServerRESTStructuredCoverageGridReaderManagerTest extends StoreIntegrationTest {
+
+ /**
+ * @param ignore
+ * @throws IllegalArgumentException
+ * @throws MalformedURLException
+ */
+ public GeoServerRESTStructuredCoverageGridReaderManagerTest()
+ throws IllegalArgumentException, MalformedURLException {
+ super(true);
+ }
+
+ @Override
+ public GSAbstractStoreEncoder getStoreEncoderTest() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Test
+ public void createAndDelete() throws IllegalArgumentException, MalformedURLException, UnsupportedEncodingException{
+ GeoServerRESTStructuredCoverageGridReaderManager manager =
+ new GeoServerRESTStructuredCoverageGridReaderManager(new URL("http://localhost:8080/geoserver"), "admin", "geoserver");
+// boolean result=manager.createOrHarvestExternal("it.geosolutions", "polyphemus", "imagemosaic", "D:\\DLR\\Geoserver-MD\\polyphemus\\polyphemus_20130301.nc");
+// Assert.assertTrue(result);
+
+ // check index format
+ RESTStructuredCoverageIndexSchema indexFormat = manager.getGranuleIndexSchema("it.geosolutions", "polyphemus","V");
+ assertNotNull(indexFormat);
+ assertFalse(indexFormat.isEmpty());
+ assertEquals(7, indexFormat.size());
+ Iterator iterator = indexFormat.iterator();
+ while(iterator.hasNext()){
+ final RESTStructuredCoverageIndexAttribute element = iterator.next();
+ if(element.getName().equals("location")){
+ assertEquals("0", element.getMinOccurs());
+ assertEquals("1", element.getMaxOccurs());
+ assertEquals("true", element.getNillable());
+ assertEquals("java.lang.String", element.getBinding());
+ break;
+ }
+ }
+
+ // get some granules by id
+ RESTStructuredCoverageGranulesList granulesList = manager.getGranuleById("it.geosolutions", "polyphemus","V","348");
+ assertNotNull(granulesList);
+ assertSame(1, granulesList.size());
+ assertFalse(granulesList.isEmpty());
+ RESTStructuredCoverageGranule granule = granulesList.get(0);
+ assertNotNull(granule);
+ assertEquals(granule.getAttributeByIndex(4), "1250.0");
+ assertEquals(granule.getAttributeByName("elevation"), "1250.0");
+
+
+ // get with paging
+ granulesList = manager.getGranules("it.geosolutions", "polyphemus","V",null,"0","10");
+ assertNotNull(granulesList);
+ assertEquals(10, granulesList.size());
+ assertFalse(granulesList.isEmpty());
+ granule = granulesList.get(0);
+ assertNotNull(granule);
+
+ granulesList = manager.getGranules("it.geosolutions", "polyphemus","V",null,null,"10");
+ assertNotNull(granulesList);
+ assertEquals(10, granulesList.size());
+ assertFalse(granulesList.isEmpty());
+ granule = granulesList.get(0);
+ assertNotNull(granule);
+
+ granulesList = manager.getGranules("it.geosolutions", "polyphemus","V",null,null,null);
+ assertNotNull(granulesList);
+ assertEquals(1007, granulesList.size());
+ assertFalse(granulesList.isEmpty());
+ granule = granulesList.get(0);
+ assertNotNull(granule);
+
+ granulesList = manager.getGranules("it.geosolutions", "polyphemus","V","elevation = 10",null,null);
+ assertNotNull(granulesList);
+ assertEquals(72, granulesList.size());
+ assertFalse(granulesList.isEmpty());
+ granule = granulesList.get(0);
+ assertNotNull(granule);
+
+ granulesList = manager.getGranules("it.geosolutions", "polyphemus","V","elevation = 10","0","10");
+ assertNotNull(granulesList);
+ assertEquals(10, granulesList.size());
+ assertFalse(granulesList.isEmpty());
+ granule = granulesList.get(0);
+ assertNotNull(granule);
+
+ // remove by id
+ boolean result = manager.removeGranuleById("it.geosolutions", "polyphemus","V", "349");
+ assertTrue(result);
+
+ // remove by filter
+ result = manager.removeGranulesByCQL("it.geosolutions", "polyphemus","V", "location = 'polyphemus_20130301.nc'");
+ Assert.assertTrue(result);
+ }
+}