// At this point, all search attributes are ready
List<SourceSearchAttribute> sources = new ArrayList<>();
boolean hasEmptySearchFields = false;
DistanceSearchAttribute distanceSearch = null;
GeoCodingResult coords = null;
Double dist = null;
// check for optional-only queries
// (some query types seem to allow no MUST occurs)
for (Iterator<SearchAttribute> it = rootGroup.getSearchAttributes().iterator(); it.hasNext();) {
SearchAttribute attr = it.next();
if (attr instanceof SearchAttributeGroup) {
// fixme: this needs to be done recursively, but how?
for (final Iterator<SearchAttribute> groupIterator = ((SearchAttributeGroup)attr).getSearchAttributes().iterator(); groupIterator.hasNext();) {
final SearchAttribute item = groupIterator.next();
if (item instanceof SourceSearchAttribute) {
sources.add((SourceSearchAttribute)item);
// remove attribute from filter list
groupIterator.remove();
hasGraphSources = true;
}
if (item instanceof EmptySearchAttribute) {
hasEmptySearchFields = true;
}
}
}
// check for distance search and initialize
if (attr instanceof DistanceSearchAttribute) {
distanceSearch = (DistanceSearchAttribute) attr;
coords = GeoHelper.geocode(distanceSearch);
dist = distanceSearch.getValue();
// remove attribute from filter list
it.remove();
hasSpatialSource = true;
}
// store source attributes for later use
if (attr instanceof SourceSearchAttribute) {
sources.add((SourceSearchAttribute)attr);
// remove attribute from filter list
it.remove();
hasGraphSources = true;
}
if (attr instanceof EmptySearchAttribute) {
hasEmptySearchFields = true;
}
}
Result intermediateResult;
// only do "normal" query if no other sources are present
// use filters to filter sources otherwise
if (distanceSearch == null && !sources.isEmpty()) {
intermediateResult = new Result(new ArrayList<AbstractNode>(), null, false, false);
} else {
BooleanQuery query = new BooleanQuery();
boolean allExactMatch = true;
// build query
for (SearchAttribute attr : rootGroup.getSearchAttributes()) {
Query queryElement = attr.getQuery();
if (queryElement != null) {
query.add(queryElement, attr.getOccur());
}
allExactMatch &= attr.isExactMatch();
}
QueryContext queryContext = new QueryContext(query);
IndexHits hits = null;
if (sortKey != null) {
Integer sortType = sortKey.getSortType();
if (sortType != null) {
queryContext.sort(new Sort(new SortField(sortKey.dbName(), sortType, sortDescending)));
} else {
queryContext.sort(new Sort(new SortField(sortKey.dbName(), Locale.getDefault(), sortDescending)));
}
}
if (distanceSearch != null) {
if (coords != null) {
Map<String, Object> params = new HashMap<>();
params.put(LayerNodeIndex.POINT_PARAMETER, coords.toArray());
params.put(LayerNodeIndex.DISTANCE_IN_KM_PARAMETER, dist);
LayerNodeIndex spatialIndex = this.getSpatialIndex();
if (spatialIndex != null) {