/* See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* Esri Inc. licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.esri.gpt.catalog.lucene;
import com.esri.gpt.catalog.discovery.Discoverable;
import com.esri.gpt.catalog.discovery.DiscoveryException;
import com.esri.gpt.catalog.discovery.LogicalClause;
import com.esri.gpt.catalog.discovery.SpatialClause;
import com.esri.gpt.framework.collection.StringAttributeMap;
import com.esri.gpt.framework.context.RequestContext;
import com.esri.gpt.framework.geometry.Envelope;
import com.esri.gpt.framework.util.Val;
import java.util.logging.Logger;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.NumericRangeQuery;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.function.ValueSourceQuery;
/**
* Adapts a catalog discovery SpatialClause to the Lucene model.
*/
public class SpatialClauseAdapter extends DiscoveryClauseAdapter {
/** class variables ========================================================= */
/** The Logger. */
private static Logger LOGGER = Logger.getLogger(SpatialClauseAdapter.class.getName());
/** instance variables ====================================================== */
/** The input envelope. */
private Envelope envelope;
/** The field names. */
private String docMinX = "envelope.minx";
private String docMinY = "envelope.miny";
private String docMaxX = "envelope.maxx";
private String docMaxY = "envelope.maxy";
private String docMinXLeft = "envelope.minx";
private String docMaxXRight = "envelope.maxx";
private String docXDL = "envelope.xdl";
/** The query values */
private boolean qryCrossedDateline = false;
private double qryMinX;
private double qryMinY;
private double qryMaxX;
private double qryMaxY;
/** constructors ============================================================ */
/**
* Constructs with an associated query adapter.
* @param queryAdapter the query adapter
*/
protected SpatialClauseAdapter(LuceneQueryAdapter queryAdapter) {
super(queryAdapter);
}
/** methods ================================================================= */
/**
* Adapts a catalog discovery SpatialClause to the Lucene model.
* @param activeBooleanQuery the active Lucene boolean query
* @param activeLogicalClause the active discovery logical clause
* @param spatialClause the spatial clause to adapt
* @throws DiscoveryException if an invalid clause is encountered
*/
protected void adaptSpatialClause(BooleanQuery activeBooleanQuery,
LogicalClause activeLogicalClause,
SpatialClause spatialClause)
throws DiscoveryException {
LOGGER.finer("Adapting SpatialClause...\n"+spatialClause);
// determine the discoverable target, set names
String sErr;
Discoverable discoverable = spatialClause.getTarget();
if (discoverable == null) {
sErr = "The SpatialClause.target is null.";
throw new DiscoveryException(sErr);
}
if (discoverable.getStorable() == null) {
sErr = "The SpatialClause.target.storeable is null.";
throw new DiscoveryException(sErr);
} else {
Storeable storeable = (Storeable)discoverable.getStorable();
if (!(storeable instanceof GeometryProperty)) {
sErr = "The SpatialClause.target.storeable is not a GeometryProperty.";
throw new DiscoveryException(sErr);
}
}
// check the envelope
envelope = spatialClause.getBoundingEnvelope();
if ((envelope == null) || envelope.isEmpty()) {
sErr = "The SpatialClause.boundingEnvelope is empty.";
throw new DiscoveryException(sErr);
}
// initialize the values of the input query envelope
qryMinX = envelope.getMinX();
qryMinY = envelope.getMinY();
qryMaxX = envelope.getMaxX();
qryMaxY = envelope.getMaxY();
if (qryMinX > qryMaxX) {
qryCrossedDateline = true;
}
// determine spatialRelevance parameters
// (original defaults were queryPower=2.0, targetPower=0.5)
RequestContext rc = this.getQueryAdapter().getIndexAdapter().getRequestContext();
StringAttributeMap params = rc.getCatalogConfiguration().getParameters();
double queryPower = Val.chkDbl(params.getValue("spatialRelevance.queryPower"),1.0);
double targetPower = Val.chkDbl(params.getValue("spatialRelevance.targetPower"),1.0);
String rankingOption = Val.chkStr(params.getValue("spatialRelevance.ranking.enabled"));
int rankingMaxDoc = Val.chkInt(params.getValue("spatialRelevance.ranking.maxDoc"),50000);
boolean bUseSpatialRanking = false;
if (rankingOption.equalsIgnoreCase("true")) {
bUseSpatialRanking = true;
} else if (rankingOption.equalsIgnoreCase("false")) {
bUseSpatialRanking = false;
} else {
// default spatialRelevance.ranking.enabled option is "auto"
if (this.getQueryAdapter() != null) {
int maxDoc = this.getQueryAdapter().getMaxDoc();
if ((maxDoc > 0) && (maxDoc <= rankingMaxDoc)) {
bUseSpatialRanking = true;
}
}
}
// Handle each operation - Beyond, Crosses, DWithin and Touches are not implemented
if (bUseSpatialRanking) {
Query spatialQuery = null;
if (spatialClause instanceof SpatialClause.GeometryBBOXIntersects) {
spatialQuery = this.makeIntersects();
} else if (spatialClause instanceof SpatialClause.GeometryContains) {
spatialQuery = this.makeContains();
} else if (spatialClause instanceof SpatialClause.GeometryIntersects) {
spatialQuery = this.makeIntersects();
} else if (spatialClause instanceof SpatialClause.GeometryIsDisjointTo) {
bUseSpatialRanking = false;
} else if (spatialClause instanceof SpatialClause.GeometryIsEqualTo) {
bUseSpatialRanking = false;
} else if (spatialClause instanceof SpatialClause.GeometryIsWithin) {
spatialQuery = this.makeWithin();
} else if (spatialClause instanceof SpatialClause.GeometryOverlaps) {
spatialQuery = this.makeIntersects();
} else {
sErr = "Unrecognized spatial clause type: ";
throw new DiscoveryException(sErr+spatialClause.getClass().getName());
}
if (bUseSpatialRanking) {
SpatialRankingValueSource srvs = new SpatialRankingValueSource(envelope,queryPower,targetPower);
Query spatialRankingQuery = new ValueSourceQuery(srvs);
BooleanQuery bq = new BooleanQuery();
bq.add(spatialQuery,BooleanClause.Occur.MUST);
bq.add(spatialRankingQuery,BooleanClause.Occur.MUST);
appendQuery(activeBooleanQuery,activeLogicalClause,bq);
this.getQueryAdapter().setHasScoredExpression(true);
}
}
if (!bUseSpatialRanking) {
if (spatialClause instanceof SpatialClause.GeometryBBOXIntersects) {
appendQuery(activeBooleanQuery,activeLogicalClause,makeIntersects());
} else if (spatialClause instanceof SpatialClause.GeometryContains) {
appendQuery(activeBooleanQuery,activeLogicalClause,makeContains());
} else if (spatialClause instanceof SpatialClause.GeometryIntersects) {
appendQuery(activeBooleanQuery,activeLogicalClause,makeIntersects());
} else if (spatialClause instanceof SpatialClause.GeometryIsDisjointTo) {
appendQuery(activeBooleanQuery,activeLogicalClause,makeDisjoint());
} else if (spatialClause instanceof SpatialClause.GeometryIsEqualTo) {
appendQuery(activeBooleanQuery,activeLogicalClause,makeEquals());
} else if (spatialClause instanceof SpatialClause.GeometryIsWithin) {
appendQuery(activeBooleanQuery,activeLogicalClause,makeWithin());
} else if (spatialClause instanceof SpatialClause.GeometryOverlaps) {
appendQuery(activeBooleanQuery,activeLogicalClause,makeIntersects());
} else {
sErr = "Unrecognized spatial clause type: ";
throw new DiscoveryException(sErr+spatialClause.getClass().getName());
}
}
}
/**
* Constructs a query to retrieve documents that fully contain the input envelope.
* @return the spatial query
*/
private Query makeContains() {
/*
// the original contains query does not work for envelopes that cross the date line
// docMinX <= qryMinX, docMinY <= qryMinY, docMaxX >= qryMaxX, docMaxY >= qryMaxY
Query qMinX = NumericRangeQuery.newDoubleRange(docMinX,null,qryMinX,false,true);
Query qMinY = NumericRangeQuery.newDoubleRange(docMinY,null,qryMinY,false,true);
Query qMaxX = NumericRangeQuery.newDoubleRange(docMaxX,qryMaxX,null,true,false);
Query qMaxY = NumericRangeQuery.newDoubleRange(docMaxY,qryMaxY,null,true,false);
BooleanQuery bq = new BooleanQuery();
bq.add(qMinX,BooleanClause.Occur.MUST);
bq.add(qMinY,BooleanClause.Occur.MUST);
bq.add(qMaxX,BooleanClause.Occur.MUST);
bq.add(qMaxY,BooleanClause.Occur.MUST);
return bq;
*/
// general case
// docMinX <= qryMinX AND docMinY <= qryMinY AND docMaxX >= qryMaxX AND docMaxY >= qryMaxY
// Y conditions
// docMinY <= qryMinY AND docMaxY >= qryMaxY
Query qMinY = NumericRangeQuery.newDoubleRange(docMinY,null,qryMinY,false,true);
Query qMaxY = NumericRangeQuery.newDoubleRange(docMaxY,qryMaxY,null,true,false);
Query yConditions = this.makeQuery(new Query[]{qMinY,qMaxY},BooleanClause.Occur.MUST);
// X conditions
Query xConditions = null;
// queries that do not cross the date line
if (!qryCrossedDateline) {
// X Conditions for documents that do not cross the date line,
// documents that contain the min X and max X of the query envelope,
// docMinX <= qryMinX AND docMaxX >= qryMaxX
Query qMinX = NumericRangeQuery.newDoubleRange(docMinX,null,qryMinX,false,true);
Query qMaxX = NumericRangeQuery.newDoubleRange(docMaxX,qryMaxX,null,true,false);
Query qMinMax = this.makeQuery(new Query[]{qMinX,qMaxX},BooleanClause.Occur.MUST);
Query qNonXDL = this.makeXDL(false,qMinMax);
// X Conditions for documents that cross the date line,
// the left portion of the document contains the min X of the query
// OR the right portion of the document contains the max X of the query,
// docMinXLeft <= qryMinX OR docMaxXRight >= qryMaxX
Query qXDLLeft = NumericRangeQuery.newDoubleRange(docMinXLeft,null,qryMinX,false,true);
Query qXDLRight = NumericRangeQuery.newDoubleRange(docMaxXRight,qryMaxX,null,true,false);
Query qXDLLeftRight = this.makeQuery(new Query[]{qXDLLeft,qXDLRight},BooleanClause.Occur.SHOULD);
Query qXDL = this.makeXDL(true,qXDLLeftRight);
// apply the non-XDL and XDL conditions
xConditions = this.makeQuery(new Query[]{qNonXDL,qXDL},BooleanClause.Occur.SHOULD);
// queries that cross the date line
} else {
// No need to search for documents that do not cross the date line
// X Conditions for documents that cross the date line,
// the left portion of the document contains the min X of the query
// AND the right portion of the document contains the max X of the query,
// docMinXLeft <= qryMinX AND docMaxXRight >= qryMaxX
Query qXDLLeft = NumericRangeQuery.newDoubleRange(docMinXLeft,null,qryMinX,false,true);
Query qXDLRight = NumericRangeQuery.newDoubleRange(docMaxXRight,qryMaxX,null,true,false);
Query qXDLLeftRight = this.makeQuery(new Query[]{qXDLLeft,qXDLRight},BooleanClause.Occur.MUST);
Query qXDL = this.makeXDL(true,qXDLLeftRight);
xConditions = qXDL;
}
// both X and Y conditions must occur
Query xyConditions = this.makeQuery(new Query[]{xConditions,yConditions},BooleanClause.Occur.MUST);
return xyConditions;
}
/**
* Constructs a query to retrieve documents that are disjoint to the input envelope.
* @return the spatial query
*/
private Query makeDisjoint() {
/*
// the original disjoint query does not work for envelopes that cross the date line
// docMinX > qryMaxX OR docMaxX < qryMinX OR docMinY > qryMaxY OR docMaxY < qryMinY
Query qMinX = NumericRangeQuery.newDoubleRange(docMinX,qryMaxX,null,false,false);
Query qMaxX = NumericRangeQuery.newDoubleRange(docMaxX,null,qryMinX,false,false);
Query qMinY = NumericRangeQuery.newDoubleRange(docMinY,qryMaxY,null,false,false);
Query qMaxY = NumericRangeQuery.newDoubleRange(docMaxY,null,qryMinY,false,false);
BooleanQuery bq = new BooleanQuery();
bq.add(qMinX,BooleanClause.Occur.SHOULD);
bq.add(qMinY,BooleanClause.Occur.SHOULD);
bq.add(qMaxX,BooleanClause.Occur.SHOULD);
bq.add(qMaxY,BooleanClause.Occur.SHOULD);
*/
// general case
// docMinX > qryMaxX OR docMaxX < qryMinX OR docMinY > qryMaxY OR docMaxY < qryMinY
// Y conditions
// docMinY > qryMaxY OR docMaxY < qryMinY
Query qMinY = NumericRangeQuery.newDoubleRange(docMinY,qryMaxY,null,false,false);
Query qMaxY = NumericRangeQuery.newDoubleRange(docMaxY,null,qryMinY,false,false);
Query yConditions = this.makeQuery(new Query[]{qMinY,qMaxY},BooleanClause.Occur.SHOULD);
// X conditions
Query xConditions = null;
// queries that do not cross the date line
if (!qryCrossedDateline) {
// X Conditions for documents that do not cross the date line,
// docMinX > qryMaxX OR docMaxX < qryMinX
Query qMinX = NumericRangeQuery.newDoubleRange(docMinX,qryMaxX,null,false,false);
Query qMaxX = NumericRangeQuery.newDoubleRange(docMaxX,null,qryMinX,false,false);
Query qMinMax = this.makeQuery(new Query[]{qMinX,qMaxX},BooleanClause.Occur.SHOULD);
Query qNonXDL = this.makeXDL(false,qMinMax);
// X Conditions for documents that cross the date line,
// both the left and right portions of the document must be disjoint to the query
// (docMinXLeft > qryMaxX OR docMaxXLeft < qryMinX) AND
// (docMinXRight > qryMaxX OR docMaxXRight < qryMinX)
// where: docMaxXLeft = 180.0, docMinXRight = -180.0
// (docMaxXLeft < qryMinX) equates to (180.0 < qryMinX) and is ignored
// (docMinXRight > qryMaxX) equates to (-180.0 > qryMaxX) and is ignored
Query qMinXLeft = NumericRangeQuery.newDoubleRange(docMinXLeft,qryMaxX,null,false,false);
Query qMaxXRight = NumericRangeQuery.newDoubleRange(docMaxXRight,null,qryMinX,false,false);
Query qLeftRight = this.makeQuery(new Query[]{qMinXLeft,qMaxXRight},BooleanClause.Occur.MUST);
Query qXDL = this.makeXDL(true,qLeftRight);
// apply the non-XDL and XDL conditions
xConditions = this.makeQuery(new Query[]{qNonXDL,qXDL},BooleanClause.Occur.SHOULD);
// queries that cross the date line
} else {
// X Conditions for documents that do not cross the date line,
// the document must be disjoint to both the left and right query portions
// (docMinX > qryMaxXLeft OR docMaxX < qryMinX) AND (docMinX > qryMaxX OR docMaxX < qryMinXLeft)
// where: qryMaxXLeft = 180.0, qryMinXLeft = -180.0
Query qMinXLeft = NumericRangeQuery.newDoubleRange(docMinX,180.0,null,false,false);
Query qMaxXLeft = NumericRangeQuery.newDoubleRange(docMaxX,null,qryMinX,false,false);
Query qMinXRight = NumericRangeQuery.newDoubleRange(docMinX,qryMaxX,null,false,false);
Query qMaxXRight = NumericRangeQuery.newDoubleRange(docMaxX,null,-180.0,false,false);
Query qLeft = this.makeQuery(new Query[]{qMinXLeft,qMaxXLeft},BooleanClause.Occur.SHOULD);
Query qRight = this.makeQuery(new Query[]{qMinXRight,qMaxXRight},BooleanClause.Occur.SHOULD);
Query qLeftRight = this.makeQuery(new Query[]{qLeft,qRight},BooleanClause.Occur.MUST);
Query qNonXDL = this.makeXDL(false,qLeftRight);
// No need to search for documents that do not cross the date line
xConditions = qNonXDL;
}
// either X or Y conditions should occur
Query xyConditions = this.makeQuery(new Query[]{xConditions,yConditions},BooleanClause.Occur.SHOULD);
return xyConditions;
}
/**
* Constructs a query to retrieve documents that equal the input envelope.
* @return the spatial query
*/
private Query makeEquals() {
// docMinX = qryMinX AND docMinY = qryMinY AND docMaxX = qryMaxX AND docMaxY = qryMaxY
Query qMinX = NumericRangeQuery.newDoubleRange(docMinX,qryMinX,qryMinX,true,true);
Query qMinY = NumericRangeQuery.newDoubleRange(docMinY,qryMinY,qryMinY,true,true);
Query qMaxX = NumericRangeQuery.newDoubleRange(docMaxX,qryMaxX,qryMaxX,true,true);
Query qMaxY = NumericRangeQuery.newDoubleRange(docMaxY,qryMaxY,qryMaxY,true,true);
BooleanQuery bq = new BooleanQuery();
bq.add(qMinX,BooleanClause.Occur.MUST);
bq.add(qMinY,BooleanClause.Occur.MUST);
bq.add(qMaxX,BooleanClause.Occur.MUST);
bq.add(qMaxY,BooleanClause.Occur.MUST);
return bq;
}
/**
* Constructs a query to retrieve documents that intersect the input envelope.
* @return the spatial query
*/
private Query makeIntersects() {
// the original intersects query does not work for envelopes that cross the date line,
// switch to a NOT Disjoint query
// MUST_NOT causes a problem when it's the only clause type within a BooleanQuery,
// to get round it we add all documents as a SHOULD
// there must be an envelope, it must not be disjoint
Query qDisjoint = makeDisjoint();
Query qIsNonXDL = this.makeXDL(false);
Query qIsXDL = this.makeXDL(true);
Query qHasEnv = this.makeQuery(new Query[]{qIsNonXDL,qIsXDL},BooleanClause.Occur.SHOULD);
BooleanQuery qNotDisjoint = new BooleanQuery();
qNotDisjoint.add(qHasEnv,BooleanClause.Occur.MUST);
qNotDisjoint.add(qDisjoint,BooleanClause.Occur.MUST_NOT);
//Query qDisjoint = makeDisjoint();
//BooleanQuery qNotDisjoint = new BooleanQuery();
//qNotDisjoint.add(new MatchAllDocsQuery(),BooleanClause.Occur.SHOULD);
//qNotDisjoint.add(qDisjoint,BooleanClause.Occur.MUST_NOT);
return qNotDisjoint;
}
/**
* Makes a boolean query based upon a collection of queries and a logical operator.
* @param queries the query collection
* @param occur the logical operator
* @return the query
*/
private BooleanQuery makeQuery(Query[] queries, BooleanClause.Occur occur) {
BooleanQuery bq = new BooleanQuery();
for (Query query: queries) {
bq.add(query,occur);
}
return bq;
}
/**
* Constructs a query to retrieve documents are fully within the input envelope.
* @return the spatial query
*/
private Query makeWithin() {
/*
// the original within query does not work for envelopes that cross the date line
// docMinX >= qryMinX AND docMinY >= qryMinY AND docMaxX <= qryMaxX AND docMaxY <= qryMaxY
Query qMinX = NumericRangeQuery.newDoubleRange(docMinX,qryMinX,null,true,false);
Query qMinY = NumericRangeQuery.newDoubleRange(docMinY,qryMinY,null,true,false);
Query qMaxX = NumericRangeQuery.newDoubleRange(docMaxX,null,qryMaxX,false,true);
Query qMaxY = NumericRangeQuery.newDoubleRange(docMaxY,null,qryMaxY,false,true);
BooleanQuery bq = new BooleanQuery();
bq.add(qMinX,BooleanClause.Occur.MUST);
bq.add(qMinY,BooleanClause.Occur.MUST);
bq.add(qMaxX,BooleanClause.Occur.MUST);
bq.add(qMaxY,BooleanClause.Occur.MUST);
return bq;
*/
// general case
// docMinX >= qryMinX AND docMinY >= qryMinY AND docMaxX <= qryMaxX AND docMaxY <= qryMaxY
// Y conditions
// docMinY >= qryMinY AND docMaxY <= qryMaxY
Query qMinY = NumericRangeQuery.newDoubleRange(docMinY,qryMinY,null,true,false);
Query qMaxY = NumericRangeQuery.newDoubleRange(docMaxY,null,qryMaxY,false,true);
Query yConditions = this.makeQuery(new Query[]{qMinY,qMaxY},BooleanClause.Occur.MUST);
// X conditions
Query xConditions = null;
// X Conditions for documents that cross the date line,
// the left portion of the document must be within the left portion of the query,
// AND the right portion of the document must be within the right portion of the query
// docMinXLeft >= qryMinX AND docMaxXLeft <= 180.0
// AND docMinXRight >= -180.0 AND docMaxXRight <= qryMaxX
Query qXDLLeft = NumericRangeQuery.newDoubleRange(docMinXLeft,qryMinX,null,true,false);
Query qXDLRight = NumericRangeQuery.newDoubleRange(docMaxXRight,null,qryMaxX,false,true);
Query qXDLLeftRight = this.makeQuery(new Query[]{qXDLLeft,qXDLRight},BooleanClause.Occur.MUST);
Query qXDL = this.makeXDL(true,qXDLLeftRight);
// queries that do not cross the date line
if (!qryCrossedDateline) {
// X Conditions for documents that do not cross the date line,
// docMinX >= qryMinX AND docMaxX <= qryMaxX
Query qMinX = NumericRangeQuery.newDoubleRange(docMinX,qryMinX,null,true,false);
Query qMaxX = NumericRangeQuery.newDoubleRange(docMaxX,null,qryMaxX,false,true);
Query qMinMax = this.makeQuery(new Query[]{qMinX,qMaxX},BooleanClause.Occur.MUST);
Query qNonXDL = this.makeXDL(false,qMinMax);
// apply the non-XDL or XDL X conditions
if ((qryMinX <= -180.0) && qryMaxX >= 180.0) {
xConditions = this.makeQuery(new Query[]{qNonXDL,qXDL},BooleanClause.Occur.SHOULD);
} else {
xConditions = qNonXDL;
}
// queries that cross the date line
} else {
// X Conditions for documents that do not cross the date line
// the document should be within the left portion of the query
// docMinX >= qryMinX AND docMaxX <= 180.0
Query qMinXLeft = NumericRangeQuery.newDoubleRange(docMinX,qryMinX,null,true,false);
Query qMaxXLeft = NumericRangeQuery.newDoubleRange(docMaxX,null,180.0,false,true);
Query qLeft = this.makeQuery(new Query[]{qMinXLeft,qMaxXLeft},BooleanClause.Occur.MUST);
// the document should be within the right portion of the query
// docMinX >= -180.0 AND docMaxX <= qryMaxX
Query qMinXRight = NumericRangeQuery.newDoubleRange(docMinX,-180.0,null,true,false);
Query qMaxXRight = NumericRangeQuery.newDoubleRange(docMaxX,null,qryMaxX,false,true);
Query qRight = this.makeQuery(new Query[]{qMinXRight,qMaxXRight},BooleanClause.Occur.MUST);
// either left or right conditions should occur,
// apply the left and right conditions to documents that do not cross the date line
Query qLeftRight = this.makeQuery(new Query[]{qLeft,qRight},BooleanClause.Occur.SHOULD);
Query qNonXDL = this.makeXDL(false,qLeftRight);
// apply the non-XDL and XDL conditions
xConditions = this.makeQuery(new Query[]{qNonXDL,qXDL},BooleanClause.Occur.SHOULD);
}
// both X and Y conditions must occur
Query xyConditions = this.makeQuery(new Query[]{xConditions,yConditions},BooleanClause.Occur.MUST);
return xyConditions;
}
/**
* Constructs a query to retrieve documents that do or do not cross the date line.
* @param crossedDateLine <code>true</true> for documents that cross the date line
* @return the query
*/
private Query makeXDL(boolean crossedDateLine) {
return new TermQuery(new Term(docXDL,""+crossedDateLine));
}
/**
* Constructs a query to retrieve documents that do or do not cross the date line
* and match the supplied spatial query.
* @param crossedDateLine <code>true</true> for documents that cross the date line
* @param query the spatial query
* @return the query
*/
private Query makeXDL(boolean crossedDateLine, Query query) {
BooleanQuery bq = new BooleanQuery();
bq.add(this.makeXDL(crossedDateLine),BooleanClause.Occur.MUST);
bq.add(query,BooleanClause.Occur.MUST);
return bq;
}
}