Skip to content

Commit

Permalink
Quicklook extraction support
Browse files Browse the repository at this point in the history
  • Loading branch information
aaime committed Mar 16, 2017
1 parent 94ea2c0 commit e66d2ec
Show file tree
Hide file tree
Showing 19 changed files with 462 additions and 103 deletions.
Expand Up @@ -53,6 +53,7 @@
<value>description</value> <value>description</value>
<value>search</value> <value>search</value>
<value>metadata</value> <value>metadata</value>
<value>quicklook</value>
</list> </list>
</constructor-arg> </constructor-arg>
</bean> </bean>
Expand Down Expand Up @@ -89,12 +90,14 @@
<constructor-arg ref="openSearchEoService" /> <constructor-arg ref="openSearchEoService" />
</bean> </bean>
<bean id="oseoMetadataRequestKvpParser" class="org.geoserver.opensearch.eo.kvp.MetadataRequestKvpReader" /> <bean id="oseoMetadataRequestKvpParser" class="org.geoserver.opensearch.eo.kvp.MetadataRequestKvpReader" />
<bean id="oseoQuicklookRequestKvpParser" class="org.geoserver.opensearch.eo.kvp.QuicklookRequestKvpReader" />


<!-- responses --> <!-- responses -->
<bean id="oseoDescriptionResponse" class="org.geoserver.opensearch.eo.response.DescriptionResponse" /> <bean id="oseoDescriptionResponse" class="org.geoserver.opensearch.eo.response.DescriptionResponse" />
<bean id="oseoAtomSearchResponse" class="org.geoserver.opensearch.eo.response.AtomSearchResponse"> <bean id="oseoAtomSearchResponse" class="org.geoserver.opensearch.eo.response.AtomSearchResponse">
<constructor-arg ref="geoServer" /> <constructor-arg ref="geoServer" />
</bean> </bean>
<bean id="oseoMetadataResponse" class="org.geoserver.opensearch.eo.response.MetadataResponse"/> <bean id="oseoMetadataResponse" class="org.geoserver.opensearch.eo.response.MetadataResponse"/>
<bean id="oseoQuicklookResponse" class="org.geoserver.opensearch.eo.response.QuicklookResponse"/>


</beans> </beans>
@@ -0,0 +1,61 @@
/* (c) 2017 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.opensearch.eo;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

/**
* A generic request by collection and product id
*
* @author Andrea Aime - GeoSolutions
*/
public class AbstractProductRequest {

String parentId;

String id;

String httpAccept;

transient String baseUrl;

public String getBaseUrl() {
return baseUrl;
}

public void setBaseUrl(String baseUrl) {
this.baseUrl = baseUrl;
}

public String getParentId() {
return parentId;
}

public void setParentId(String parentId) {
this.parentId = parentId;
}

public String getHttpAccept() {
return httpAccept;
}

public void setHttpAccept(String httpAccept) {
this.httpAccept = httpAccept;
}

public String getId() {
return id;
}

public void setId(String id) {
this.id = id;
}

@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
}
Expand Up @@ -51,6 +51,13 @@ public class DefaultOpenSearchEoService implements OpenSearchEoService {


static final FilterFactory2 FF = CommonFactoryFinder.getFilterFactory2(); static final FilterFactory2 FF = CommonFactoryFinder.getFilterFactory2();


/* Some mime types for quicklooks */
private static String JPEG_MIME = "image/jpeg";

private static String PNG_MIME = "image/png";

private static String BINARY_MIME = "application/octet-stream ";

GeoServer geoServer; GeoServer geoServer;


public DefaultOpenSearchEoService(GeoServer geoServer) { public DefaultOpenSearchEoService(GeoServer geoServer) {
Expand Down Expand Up @@ -253,13 +260,9 @@ public MetadataResults metadata(MetadataRequest request) throws IOException {
OpenSearchAccess access = getOpenSearchAccess(); OpenSearchAccess access = getOpenSearchAccess();


// build the query // build the query
Query query = new Query(); Query query = queryByIdentifier(request.getId());
PropertyName idProperty = FF
.property(new NameImpl(OpenSearchAccess.EO_NAMESPACE, "identifier"));
query.setProperties(Arrays.asList(FF.property(OpenSearchAccess.METADATA_PROPERTY_NAME))); query.setProperties(Arrays.asList(FF.property(OpenSearchAccess.METADATA_PROPERTY_NAME)));
final PropertyIsEqualTo idFilter = FF.equal(idProperty, FF.literal(request.getId()), true);
query.setFilter(idFilter);

// run it // run it
FeatureSource<FeatureType, Feature> source; FeatureSource<FeatureType, Feature> source;
if (request.getParentId() == null) { if (request.getParentId() == null) {
Expand All @@ -269,18 +272,89 @@ public MetadataResults metadata(MetadataRequest request) throws IOException {
source = access.getProductSource(); source = access.getProductSource();
} }
FeatureCollection<FeatureType, Feature> features = source.getFeatures(query); FeatureCollection<FeatureType, Feature> features = source.getFeatures(query);

// get the metadata from the feature // get the metadata from the feature
Feature feature = DataUtilities.first(features); String metadata = (String) getPropertyFromFirstFeature(features,
Property property; OpenSearchAccess.METADATA_PROPERTY_NAME);
String metadata; if (metadata == null) {
if (feature == null || //
((property = feature.getProperty(OpenSearchAccess.METADATA_PROPERTY_NAME)) == null) || //
((metadata = (String) property.getValue()) == null)) {
throw new OWS20Exception("Could not locate the requested metadata for uid = " throw new OWS20Exception("Could not locate the requested metadata for uid = "
+ request.getId() + " and parentId = " + request.getParentId()); + request.getId() + " and parentId = " + request.getParentId());
} }


return new MetadataResults(request, metadata); return new MetadataResults(request, metadata);
} }

@Override
public QuicklookResults quicklook(QuicklookRequest request) throws IOException {
OpenSearchAccess access = getOpenSearchAccess();

// build the query
Query query = queryByIdentifier(request.getId());
query.setProperties(Arrays.asList(FF.property(OpenSearchAccess.QUICKLOOK_PROPERTY_NAME)));

// run it
FeatureSource<FeatureType, Feature> source;
if (request.getParentId() == null) {
// collection request
source = access.getCollectionSource();
} else {
source = access.getProductSource();
}
FeatureCollection<FeatureType, Feature> features = source.getFeatures(query);

byte[] payload = (byte[]) getPropertyFromFirstFeature(features,
OpenSearchAccess.QUICKLOOK_PROPERTY_NAME);
if (payload == null) {
throw new OWS20Exception("Could not locate the quicklook for uid = " + request.getId()
+ " and parentId = " + request.getParentId());
}

return new QuicklookResults(request, payload, guessImageMimeType(payload));
}

private String guessImageMimeType(byte[] payload) {
// guesses jpeg and png by the magic number
if (payload.length >= 4 && //
(payload[0] == (byte) 0xFF) && //
(payload[1] == (byte) 0xD8) && //
(payload[2] == (byte) 0xFF) && //
(payload[3] == (byte) 0xE0)) {
return JPEG_MIME;
} else if (payload.length >= 8 && //
(payload[0] == (byte) 0x89) && //
(payload[1] == (byte) 0x50) && //
(payload[2] == (byte) 0x4E) && //
(payload[3] == (byte) 0x47) && //
(payload[4] == (byte) 0x0D) && //
(payload[5] == (byte) 0x0A) && //
(payload[6] == (byte) 0x1A) && //
(payload[7] == (byte) 0x0A)) {
return PNG_MIME;
} else {
return BINARY_MIME;
}
}

private Object getPropertyFromFirstFeature(FeatureCollection<FeatureType, Feature> features,
Name propertyName) {
Feature feature = DataUtilities.first(features);
Property property;
Object value;
if (feature == null || //
((property = feature.getProperty(propertyName)) == null) || //
((value = property.getValue()) == null)) {
return null;
}

return value;
}

private Query queryByIdentifier(String identifier) {
Query query = new Query();
PropertyName idProperty = FF
.property(new NameImpl(OpenSearchAccess.EO_NAMESPACE, "identifier"));
final PropertyIsEqualTo idFilter = FF.equal(idProperty, FF.literal(identifier), true);
query.setFilter(idFilter);
return query;
}
} }
Expand Up @@ -4,62 +4,15 @@
*/ */
package org.geoserver.opensearch.eo; package org.geoserver.opensearch.eo;


import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

/** /**
* A OpenSearch EO query for metadata of a specific product or collection * A OpenSearch EO query for metadata of a specific product or collection
* *
* @author Andrea Aime - GeoSolutions * @author Andrea Aime - GeoSolutions
*/ */
public class MetadataRequest { public class MetadataRequest extends AbstractProductRequest {

public static String ISO_METADATA = "application/vnd.iso.19139+xml";

public static String OM_METADATA = "application/gml+xml";

String parentId;

String id;

String httpAccept;

transient String baseUrl;

public String getBaseUrl() {
return baseUrl;
}


public void setBaseUrl(String baseUrl) { public static String ISO_METADATA = "application/vnd.iso.19139+xml";
this.baseUrl = baseUrl;
}

public String getParentId() {
return parentId;
}

public void setParentId(String parentId) {
this.parentId = parentId;
}

public String getHttpAccept() {
return httpAccept;
}

public void setHttpAccept(String httpAccept) {
this.httpAccept = httpAccept;
}

public String getId() {
return id;
}


public void setId(String id) { public static String OM_METADATA = "application/gml+xml";
this.id = id;
}


@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}
} }
Expand Up @@ -25,16 +25,16 @@ public interface OpenSearchEoService {
* *
* @param request * @param request
* @return * @return
* @throws IOException * @throws IOException
*/ */
public SearchResults search(SearchRequest request) throws IOException; public SearchResults search(SearchRequest request) throws IOException;

/** /**
* Retrieves a product/collection metadata in a particular format * Retrieves a product/collection metadata in a particular format
* *
* @param request * @param request
* @return * @return
* @throws IOException * @throws IOException
*/ */
public MetadataResults metadata(MetadataRequest request) throws IOException; public MetadataResults metadata(MetadataRequest request) throws IOException;


Expand All @@ -56,4 +56,10 @@ public interface OpenSearchEoService {
* @throws IOException * @throws IOException
*/ */
Collection<Parameter<?>> getProductSearchParameters(String parentId) throws IOException; Collection<Parameter<?>> getProductSearchParameters(String parentId) throws IOException;

/**
* Returns the quicklook of a product (a PNG or JPEG image normally)
*/
QuicklookResults quicklook(QuicklookRequest request) throws IOException;

} }
@@ -0,0 +1,15 @@
/* (c) 2017 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.opensearch.eo;

/**
* A request to retrieve the quicklook of a particular product
*
* @author Andrea Aime - GeoSolutions
*/
public class QuicklookRequest extends AbstractProductRequest {


}
@@ -0,0 +1,47 @@
/* (c) 2017 Open Source Geospatial Foundation - all rights reserved
* This code is licensed under the GPL 2.0 license, available at the root
* application directory.
*/
package org.geoserver.opensearch.eo;

import org.apache.commons.lang.builder.ToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;

/**
* Represents the result of a quicklook search
*
* @author Andrea Aime - GeoSolutions
*/
public class QuicklookResults {

QuicklookRequest request;

byte[] payload;

String mimeType;

public QuicklookResults(QuicklookRequest request, byte[] payload, String mimeType) {
super();
this.request = request;
this.payload = payload;
this.mimeType = mimeType;
}

public QuicklookRequest getRequest() {
return request;
}

public byte[] getPayload() {
return payload;
}

public String getMimeType() {
return mimeType;
}

@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
}

}

0 comments on commit e66d2ec

Please sign in to comment.