Skip to content

Commit

Permalink
Harvester / CSW / Bbox filter. (geonetwork#4076)
Browse files Browse the repository at this point in the history
* Harvester / CSW / Bbox filter.

* Harvester / CSW / Bbox filter / Add map.
  • Loading branch information
fxprunayre authored and julsbreakdown committed Feb 7, 2020
1 parent 9e65324 commit 74b260c
Show file tree
Hide file tree
Showing 7 changed files with 263 additions and 191 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,16 @@

import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;

import com.google.common.collect.ImmutableSet;
import org.apache.commons.lang.StringUtils;
import org.fao.geonet.GeonetContext;
import org.fao.geonet.Logger;
import org.fao.geonet.constants.Geonet;
Expand All @@ -58,60 +61,39 @@
import org.fao.geonet.utils.GeonetHttpRequestFactory;
import org.fao.geonet.utils.Xml;
import org.fao.geonet.utils.XmlRequest;
import org.jdom.Content;
import org.jdom.Element;

import jeeves.server.context.ServiceContext;

//=============================================================================
import org.jdom.Namespace;

class Harvester implements IHarvester<HarvestResult> {
//---------------------------------------------------------------------------
//---
//--- Variables
//---
//---------------------------------------------------------------------------
// FIXME : Currently switch from POST to GET for testing mainly.
public static final String PREFERRED_HTTP_METHOD = AbstractHttpRequest.Method.GET.toString();
//--------------------------------------------------------------------------
//---
//--- Constructor
//---
//--------------------------------------------------------------------------

private final static String ATTRIB_SEARCHRESULT_MATCHED = "numberOfRecordsMatched";

//---------------------------------------------------------------------------
//---
//--- API methods
//---
//---------------------------------------------------------------------------
private final static String ATTRIB_SEARCHRESULT_RETURNED = "numberOfRecordsReturned";

//---------------------------------------------------------------------------
private final static String ATTRIB_SEARCHRESULT_NEXT = "nextRecord";

//---------------------------------------------------------------------------
private static int GETRECORDS_REQUEST_MAXRECORDS = 20;

//---------------------------------------------------------------------------
private static String CONSTRAINT_LANGUAGE_VERSION = "1.1.0";

//---------------------------------------------------------------------------
//FIXME version should be parametrized
private static String GETCAPABILITIES_PARAMETERS = "SERVICE=CSW&REQUEST=GetCapabilities&VERSION=2.0.2";
private final AtomicBoolean cancelMonitor;

//---------------------------------------------------------------------------
private Logger log;
private CswParams params;
private ServiceContext context;

//---------------------------------------------------------------------------
/**
* Contains a list of accumulated errors during the executing of this harvest.
*/
private List<HarvestError> errors = new LinkedList<HarvestError>();

//---------------------------------------------------------------------------

public Harvester(AtomicBoolean cancelMonitor, Logger log, ServiceContext context, CswParams params) {
this.cancelMonitor = cancelMonitor;
Expand Down Expand Up @@ -174,7 +156,6 @@ public HarvestResult harvest(Logger log) throws Exception {

return result;
}
//---------------------------------------------------------------------------

/**
* Does CSW GetCapabilities request and check that operations needed for harvesting (ie.
Expand Down Expand Up @@ -223,8 +204,6 @@ private CswServer retrieveCapabilities(Logger log) throws Exception {
return server;
}

//---------------------------------------------------------------------------

private boolean checkOperation(Logger log, CswServer server, String name) {
CswOperation oper = server.getOperation(name);

Expand All @@ -243,11 +222,11 @@ private boolean checkOperation(Logger log, CswServer server, String name) {

/**
* Does CSW GetRecordsRequest.
* @param aligner
* @param errors2
* @param aligner
* @param errors2
*/
private void searchAndAlign(CswServer server, Search s, Set<String> uuids,
Aligner aligner, List<HarvestError> harvesterErrors) throws Exception {
private void searchAndAlign(CswServer server, Search s, Set<String> uuids,
Aligner aligner, List<HarvestError> harvesterErrors) throws Exception {
int start = 1;

GetRecordsRequest request = new GetRecordsRequest(context);
Expand Down Expand Up @@ -406,11 +385,6 @@ private void searchAndAlign(CswServer server, Search s, Set<String> uuids,
return;
}

//---------------------------------------------------------------------------

/**
* TODO Javadoc.
*/
private void setUpRequest(GetRecordsRequest request, CswOperation oper, CswServer server, Search s, URL url,
ConstraintLanguage constraintLanguage, String constraint, AbstractHttpRequest.Method method) {

Expand Down Expand Up @@ -476,22 +450,35 @@ private void configRequest(final GetRecordsRequest request, final CswOperation o
}
}

public static ImmutableSet<String> bboxParameters;
static {
bboxParameters = ImmutableSet.<String>builder()
.add("bbox-xmin")
.add("bbox-ymin")
.add("bbox-xmax")
.add("bbox-ymax")
.build();
}
private String getFilterConstraint(final Search s) {
//--- collect queriables

ArrayList<Element> queriables = new ArrayList<Element>();
Map<String, Double> bboxCoordinates = new HashMap<String, Double>();

if (!s.attributesMap.isEmpty()) {
for (Map.Entry<String, String> entry : s.attributesMap.entrySet()) {
if (entry.getValue() != null) {
// If the queriable has the namespace, use it
String queryableName = entry.getKey();
if (queryableName.contains("__")) {
if (bboxParameters.contains(queryableName)
&& StringUtils.isNotEmpty(entry.getValue())) {
bboxCoordinates.put(queryableName, Double.valueOf(entry.getValue()));
} else if (queryableName.contains("__")) {
queryableName = queryableName.replace("__", ":");
buildFilterQueryable(queriables, queryableName, entry.getValue());
} else if (!queryableName.contains(":")) {
queryableName = "csw:" + queryableName;
buildFilterQueryable(queriables, queryableName, entry.getValue());
}
buildFilterQueryable(queriables, queryableName, entry.getValue());
}
}
} else {
Expand All @@ -507,21 +494,58 @@ private String getFilterConstraint(final Search s) {

Element filter = new Element("Filter", Csw.NAMESPACE_OGC);

if (queriables.size() == 1)
if (queriables.size() == 1 && bboxCoordinates.size() == 0)
filter.addContent(queriables.get(0));
else {
Element and = new Element("And", Csw.NAMESPACE_OGC);

for (Element prop : queriables)
and.addContent(prop);

if (bboxCoordinates.size() > 0) {
and.addContent(buildBboxFilter(bboxCoordinates));
}
filter.addContent(and);
}

return Xml.getString(filter);
}

//---------------------------------------------------------------------------

/*
Build an ogc:BBOX element from bbox coordinates.
<ogc:Filter>
<ogc:And>
<ogc:PropertyIsEqualTo>
<ogc:PropertyName>csw:AnyText</ogc:PropertyName>
<ogc:Literal>roads</ogc:Literal>
</ogc:PropertyIsEqualTo>
<ogc:BBOX>
<ogc:PropertyName>ows:BoundingBox</ogc:PropertyName>
<gml:Envelope>
<gml:lowerCorner>47 -5</gml:lowerCorner>
<gml:upperCorner>55 20</gml:upperCorner>
</gml:Envelope>
</ogc:BBOX>*/
private Content buildBboxFilter(Map<String, Double> bboxCoordinates) {
Namespace gml = Namespace.getNamespace("http://www.opengis.net/gml");

Element bbox = new Element("BBOX", Csw.NAMESPACE_OGC);
Element bboxProperty = new Element("PropertyName", Csw.NAMESPACE_OGC);
bboxProperty.setText("ows:BoundingBox");
bbox.addContent(bboxProperty);
Element envelope = new Element("Envelope", gml);
Element lowerCorner = new Element("lowerCorner", gml);
lowerCorner.setText(bboxCoordinates.get("bbox-xmin") + " " + bboxCoordinates.get("bbox-ymin"));
Element upperCorner = new Element("upperCorner", gml);
upperCorner.setText(bboxCoordinates.get("bbox-xmax") + " " + bboxCoordinates.get("bbox-ymax"));
envelope.addContent(lowerCorner);
envelope.addContent(upperCorner);
bbox.addContent(envelope);
return bbox;
}

private void buildFilterQueryable(List<Element> queryables, String name, String value) {
if (value.contains("%")) {
buildFilterQueryable(queryables, name, value, "PropertyIsLike");
Expand Down Expand Up @@ -559,41 +583,44 @@ private void buildFilterQueryable(List<Element> queryables, String name, String
}

private String getCqlConstraint(Search s) {
//--- collect queriables

ArrayList<String> queryables = new ArrayList<String>();
Map<String, Double> bboxCoordinates = new HashMap<String, Double>();

if (!s.attributesMap.isEmpty()) {
for (Map.Entry<String, String> entry : s.attributesMap.entrySet()) {
if (entry.getValue() != null) {
if (bboxParameters.contains(entry.getKey())
&& StringUtils.isNotEmpty(entry.getValue())) {
bboxCoordinates.put(entry.getKey(), Double.valueOf(entry.getValue()));
} else if (entry.getValue() != null) {
buildCqlQueryable(queryables, "csw:" + entry.getKey(), entry.getValue());
}
}
} else {
log.debug("no search criterion specified, harvesting all ... ");
}

/*
buildCqlQueryable(queryables, "csw:AnyText", s.freeText);
buildCqlQueryable(queryables, "dc:title", s.title);
buildCqlQueryable(queryables, "dct:abstract", s.abstrac);
buildCqlQueryable(queryables, "dc:subject", s.subject);
buildCqlQueryable(queryables, "dct:denominator", s.minscale, ">=");
buildCqlQueryable(queryables, "dct:denominator", s.maxscale, "<=");
*/

//--- build CQL query

StringBuffer sb = new StringBuffer();

for (int i = 0; i < queryables.size(); i++) {
sb.append(queryables.get(i));

if (i < queryables.size() - 1)
if (i < queryables.size() - 1) {
sb.append(" AND ");
}
}

if (bboxCoordinates.size() > 0) {
if (queryables.size() > 0) {
sb.append(" AND ");
}
//BBOX(the_geom, -90, 40, -60, 45)
sb.append(String.format("BBOX(the_geom, %s, %s, %s, %s)",
bboxCoordinates.get("bbox-xmin"), bboxCoordinates.get("bbox-ymin"),
bboxCoordinates.get("bbox-xmax"), bboxCoordinates.get("bbox-ymax")
));
}

return (queryables.size() == 0) ? null : sb.toString();
return (queryables.size() == 0 && bboxCoordinates.size() == 0) ? null : sb.toString();
}

/**
Expand Down Expand Up @@ -703,7 +730,3 @@ public List<HarvestError> getErrors() {
return errors;
}
}

//=============================================================================


Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
description: '@',
dcRef: '@',
extentXml: '=?',
extent: '=?',
lang: '=',
schema: '@',
location: '@'
Expand Down Expand Up @@ -131,17 +132,12 @@

// Format extent values with at least 2 decimals
if (scope.extent.md) {
scope.extent.md[0] = scope.extent.md[0].toFixed(
Math.max(2, getPrecision(scope.extent.md[0])));

scope.extent.md[1] = scope.extent.md[1].toFixed(
Math.max(2, getPrecision(scope.extent.md[1])));

scope.extent.md[2] = scope.extent.md[2].toFixed(
Math.max(2, getPrecision(scope.extent.md[2])));

scope.extent.md[3] = scope.extent.md[3].toFixed(
Math.max(2, getPrecision(scope.extent.md[3])));
scope.extent.md.forEach(function (v, i) {
if (v != null) {
scope.extent.md[i] = v.toFixed(
Math.max(2, getPrecision(v)));
}
});
}

xmlExtentFn(scope.extent.md, scope.location);
Expand Down Expand Up @@ -177,7 +173,7 @@
formLabel: gnMap.getMapConfig().projectionList[0].label
};

scope.extent = {
scope.extent = scope.extent || {
md: null,
map: [],
form: []
Expand Down
Loading

0 comments on commit 74b260c

Please sign in to comment.