/*
* Copyright (C) 2007 - 2012 GeoSolutions S.A.S.
* http://www.geo-solutions.it
*
* GPLv3 + Classpath exception
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package it.geosolutions.geostore.util;
import com.googlecode.genericdao.search.Filter;
import com.googlecode.genericdao.search.Search;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
import java.util.EnumMap;
import java.util.Map;
import it.geosolutions.geostore.core.model.Resource;
import it.geosolutions.geostore.services.dto.search.AndFilter;
import it.geosolutions.geostore.services.dto.search.AttributeFilter;
import it.geosolutions.geostore.services.dto.search.CategoryFilter;
import it.geosolutions.geostore.services.dto.search.FieldFilter;
import it.geosolutions.geostore.services.dto.search.FilterVisitor;
import it.geosolutions.geostore.services.dto.search.NotFilter;
import it.geosolutions.geostore.services.dto.search.OrFilter;
import it.geosolutions.geostore.services.dto.search.SearchFilter;
import it.geosolutions.geostore.services.dto.search.SearchOperator;
import it.geosolutions.geostore.services.exception.BadRequestServiceEx;
import it.geosolutions.geostore.services.exception.InternalErrorServiceEx;
import org.apache.log4j.Logger;
/**
* Class SearchConverter.
*
* @author ETj (etj at geo-solutions.it)
* @author Tobia di Pisa (tobia.dipisa at geo-solutions.it)
*/
public class SearchConverter implements FilterVisitor {
private static final Map<SearchOperator, Integer> ops_rest_trg;
private static final Logger LOGGER = Logger.getLogger(SearchConverter.class);
static {
Map<SearchOperator, Integer> ops = new EnumMap<SearchOperator, Integer>(
SearchOperator.class);
ops.put(SearchOperator.EQUAL_TO, Filter.OP_EQUAL);
ops.put(SearchOperator.GREATER_THAN_OR_EQUAL_TO, Filter.OP_GREATER_OR_EQUAL);
ops.put(SearchOperator.GREATER_THAN, Filter.OP_GREATER_THAN);
ops.put(SearchOperator.IS_NOT_NULL, Filter.OP_NOT_NULL);
ops.put(SearchOperator.IS_NULL, Filter.OP_NULL);
ops.put(SearchOperator.LESS_THAN, Filter.OP_LESS_THAN);
ops.put(SearchOperator.LESS_THAN_OR_EQUAL_TO, Filter.OP_LESS_OR_EQUAL);
ops.put(SearchOperator.LIKE, Filter.OP_LIKE);
ops.put(SearchOperator.ILIKE, Filter.OP_ILIKE);
ops_rest_trg = Collections.unmodifiableMap(ops);
}
/**
* @param filter
* @return Search
* @throws BadRequestServiceEx
* @throws InternalErrorServiceEx
*/
public static Search convert(SearchFilter filter) throws BadRequestServiceEx,
InternalErrorServiceEx {
SearchConverter sc = new SearchConverter();
filter.accept(sc);
Search trgSearch = new Search(Resource.class);
trgSearch.addFilter(sc.trgFilter);
if (LOGGER.isDebugEnabled()) {
LOGGER.debug("TRG Search --> " + trgSearch);
}
return trgSearch;
}
private Filter trgFilter;
private SearchConverter() {
}
/*
* (non-Javadoc) @see it.geosolutions.geostore.services.dto.search.FilterVisitor#visit(it.geosolutions.geostore.services.dto.search.AndFilter)
*/
@Override
public void visit(AndFilter filter) throws BadRequestServiceEx, InternalErrorServiceEx {
trgFilter = Filter.and();
for (SearchFilter searchFilter : filter.getFilters()) {
SearchConverter sc = new SearchConverter();
searchFilter.accept(sc);
trgFilter.add(sc.trgFilter);
}
}
/**
* This is a leaf filter.
*
* @throws BadRequestServiceEx
* @throws InternalErrorServiceEx
*/
@Override
public void visit(AttributeFilter filter) throws BadRequestServiceEx, InternalErrorServiceEx {
if ((filter.getType() != null) && (filter.getName() != null)
&& (filter.getOperator() != null) && (filter.getValue() != null)) {
Integer trg_op = ops_rest_trg.get(filter.getOperator());
if (trg_op == null) {
throw new IllegalStateException("Unknown op " + filter.getOperator());
}
String fieldValueName;
Object value = null;
switch (filter.getType()) {
case DATE:
fieldValueName = "dateValue";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
try {
value = sdf.parse(filter.getValue());
} catch (ParseException e) {
throw new InternalErrorServiceEx("Error parsing attribute date value");
}
break;
case NUMBER:
fieldValueName = "numberValue";
try {
value = Double.valueOf(filter.getValue());
} catch (NumberFormatException ex) {
throw new InternalErrorServiceEx("Error parsing attribute number value");
}
break;
case STRING:
fieldValueName = "textValue";
value = filter.getValue();
break;
default:
throw new IllegalStateException("Unknown type " + filter.getType());
}
trgFilter = Filter.some("attribute", Filter.and(Filter.equal("name", filter.getName()),
new Filter(fieldValueName, value, trg_op)));
} else {
throw new BadRequestServiceEx("Bad payload. One or more field are missing");
}
}
/**
* This is a leaf filter.
*
* @throws InternalErrorServiceEx
*/
@SuppressWarnings("rawtypes")
@Override
public void visit(FieldFilter filter) throws InternalErrorServiceEx {
String property = filter.getField().getFieldName();
String value = filter.getValue();
Class type = filter.getField().getType();
Filter f = new Filter();
Integer op = ops_rest_trg.get(filter.getOperator());
if (op == null) {
throw new IllegalStateException("Unknown op " + filter.getOperator());
}
f.setProperty(property);
f.setOperator(op);
if (type == Date.class) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
try {
f.setValue(sdf.parse(value));
} catch (ParseException e) {
throw new InternalErrorServiceEx("Error parsing attribute date value");
}
} else if (type == Long.class) {
try {
f.setValue(Long.parseLong(value));
} catch (NumberFormatException e) {
throw new InternalErrorServiceEx("Error parsing attribute long value");
}
} else {
f.setValue(value);
}
trgFilter = f;
}
/**
* This is a leaf filter.
*
* @throws InternalErrorServiceEx
*/
@Override
public void visit(CategoryFilter filter) throws InternalErrorServiceEx {
CategoryFilter.checkOperator(filter.getOperator());
Integer op = ops_rest_trg.get(filter.getOperator());
if (op == null) {
throw new IllegalStateException("Unknown op " + filter.getOperator());
}
Filter f = new Filter();
f.setOperator(op);
f.setProperty("category.name");
f.setValue(filter.getName());
trgFilter = f;
}
/*
* (non-Javadoc) @see it.geosolutions.geostore.services.dto.search.FilterVisitor#visit(it.geosolutions.geostore.services.dto.search.NotFilter)
*/
@Override
public void visit(NotFilter filter) throws BadRequestServiceEx, InternalErrorServiceEx {
SearchFilter notFilter = filter.getFilter();
SearchConverter sc = new SearchConverter();
notFilter.accept(sc);
trgFilter = Filter.not(sc.trgFilter);
}
/*
* (non-Javadoc) @see it.geosolutions.geostore.services.dto.search.FilterVisitor#visit(it.geosolutions.geostore.services.dto.search.OrFilter)
*/
@Override
public void visit(OrFilter filter) throws BadRequestServiceEx, InternalErrorServiceEx {
trgFilter = Filter.or();
for (SearchFilter searchFilter : filter.getFilters()) {
SearchConverter sc = new SearchConverter();
searchFilter.accept(sc);
trgFilter.add(sc.trgFilter);
}
}
}