/*
* 3D City Database Web Feature Service
* http://www.3dcitydb.org/
*
* Copyright 2014 - 2016
* virtualcitySYSTEMS GmbH
* Tauentzienstrasse 7b/c
* 10789 Berlin, Germany
* http://www.virtualcitysystems.de/
*
* Licensed 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 vcs.citydb.wfs.operation.getfeature;
import java.util.ArrayList;
import java.util.List;
import org.citydb.modules.common.filter.feature.FeatureClassFilter;
import org.citydb.modules.common.filter.feature.GmlIdFilter;
import org.citydb.util.Util;
import org.citygml4j.model.citygml.CityGMLClass;
import vcs.citydb.wfs.exception.WFSException;
public class QueryBuilder {
// TODO: rewrite query builder using a dynamic sql generator such as squiggle
private String optimizerHint;
public String buildQuery(List<QueryExpression> queryExpressions) throws WFSException {
optimizerHint = "";
StringBuilder query = new StringBuilder();
int nrOfQueries = queryExpressions.size();
boolean isMultipleQueryRequest = nrOfQueries > 1;
String queryMatchAlias = null;
if (isMultipleQueryRequest) {
query.append("select id, objectclass_id, count(1) over () match_all, query_no, match_query from (");
queryMatchAlias = "match_query";
} else
queryMatchAlias = "match_all";
for (int i = 0; i < queryExpressions.size(); ++i) {
QueryExpression queryExpression = queryExpressions.get(i);
StringBuilder select = new StringBuilder();
String resourceIdSelection = getResourceIdSelection(queryExpression);
select.append("select ").append(optimizerHint).append(" co.id, co.objectclass_id, count(1) over () as ").append(queryMatchAlias).append(" ");
if (isMultipleQueryRequest)
select.append(", " + i + " as query_no ");
select.append("from cityobject co ")
.append("where ").append(getFeatureTypeSelection(queryExpression));
if (resourceIdSelection != null)
select.append(" and ").append(resourceIdSelection);
if (nrOfQueries == 1)
select.append(" order by co.id");
else if (i < nrOfQueries - 1)
select.append(" union all ");
query.append(select);
}
if (isMultipleQueryRequest)
query.append(") query order by query_no, id");
return query.toString();
}
public String buildHitsQuery(QueryExpression queryExpression) {
optimizerHint = "";
StringBuilder select = new StringBuilder();
String resourceIdSelection = getResourceIdSelection(queryExpression);
select.append("select ").append(optimizerHint).append(" count(co.id) ")
.append("from cityobject co ")
.append("where ").append(getFeatureTypeSelection(queryExpression));
if (resourceIdSelection != null)
select.append(" and ").append(resourceIdSelection);
return select.toString();
}
private String getFeatureTypeSelection(QueryExpression queryExpression) {
FeatureClassFilter filter = queryExpression.getFeatureTypeFilter();
if (filter != null) {
List<Integer> classIds = new ArrayList<Integer>();
for (CityGMLClass cityGMLClass : filter.getNotFilterState())
classIds.add(Util.cityObject2classId(cityGMLClass));
if (!classIds.isEmpty()) {
StringBuilder builder = new StringBuilder();
builder.append(" co.objectclass_id in (").append(Util.collection2string(classIds, ", ")).append(") ");
return builder.toString();
}
}
return null;
}
private String getResourceIdSelection(QueryExpression queryExpression) {
GmlIdFilter filter = queryExpression.getGmlIdFilter();
if (filter != null) {
List<String> ids = filter.getFilterState();
if (ids != null && !ids.isEmpty()) {
StringBuilder builder = new StringBuilder();
if (ids.size() == 1)
builder.append("co.gmlid = ?");
else {
builder.append("co.gmlid in (");
for (int i = 0; i < ids.size(); i++) {
builder.append("?");
if (i < ids.size() - 1)
builder.append(", ");
else
builder.append(")");
}
}
return builder.toString();
}
}
return null;
}
}