Commit 64e3c84c authored by Matija Obreza's avatar Matija Obreza

Use AppliedFilters instead of ObjectNode/String jsonFilter

parent 367bf5b7
......@@ -19,10 +19,9 @@ package org.genesys2.server.persistence.domain;
import org.genesys2.server.model.genesys.Method;
import org.genesys2.server.model.impl.Country;
import org.genesys2.server.model.impl.FaoInstitute;
import org.genesys2.server.service.impl.FilterHandler.AppliedFilters;
import org.springframework.jdbc.core.RowCallbackHandler;
import com.fasterxml.jackson.databind.node.ObjectNode;
public interface GenesysLowlevelRepository {
void updateCountryRefs();
......@@ -38,20 +37,20 @@ public interface GenesysLowlevelRepository {
void refreshMetadataMethods();
void listAccessions(ObjectNode filter, RowCallbackHandler rowCallbackHandler);
void listAccessions(AppliedFilters filter, RowCallbackHandler rowCallbackHandler);
void listAccessionsGeo(ObjectNode filter, RowCallbackHandler rowCallbackHandler);
void listAccessionsGeo(AppliedFilters filter, RowCallbackHandler rowCallbackHandler);
void listAccessionsColl(ObjectNode filter, RowCallbackHandler rowCallbackHandler);
void listAccessionsColl(AppliedFilters filter, RowCallbackHandler rowCallbackHandler);
void listMetadataAccessions(long id, RowCallbackHandler rowCallbackHandler);
void listAccessionsAlias(ObjectNode filter, RowCallbackHandler rowCallbackHandler);
void listAccessionsAlias(AppliedFilters filter, RowCallbackHandler rowCallbackHandler);
void listAccessionsAccenames(RowCallbackHandler rowCallbackHandler);
void listAccessionsAlias(RowCallbackHandler rowCallbackHandler);
int countAccessions(ObjectNode filter);
int countAccessions(AppliedFilters filter);
}
......@@ -30,6 +30,7 @@ import org.apache.commons.logging.LogFactory;
import org.genesys2.server.model.genesys.Method;
import org.genesys2.server.service.impl.DirectMysqlQuery;
import org.genesys2.server.service.impl.DirectMysqlQuery.MethodResolver;
import org.genesys2.server.service.impl.FilterHandler.AppliedFilters;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.jdbc.core.ArgumentPreparedStatementSetter;
......@@ -40,8 +41,6 @@ import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
import com.fasterxml.jackson.databind.node.ObjectNode;
@Repository
@Transactional(readOnly = true)
public class GenesysLowlevelRepositoryImpl implements GenesysLowlevelRepository {
......@@ -218,7 +217,7 @@ public class GenesysLowlevelRepositoryImpl implements GenesysLowlevelRepository
}
@Override
public int countAccessions(final ObjectNode filter) {
public int countAccessions(final AppliedFilters filter) {
final DirectMysqlQuery directQuery = new DirectMysqlQuery("accession", "a");
directQuery.jsonFilter(filter, new MethodResolver() {
@Override
......@@ -231,7 +230,7 @@ public class GenesysLowlevelRepositoryImpl implements GenesysLowlevelRepository
}
@Override
public void listAccessions(final ObjectNode filter, final RowCallbackHandler rowCallbackHandler) {
public void listAccessions(final AppliedFilters filter, final RowCallbackHandler rowCallbackHandler) {
final DirectMysqlQuery directQuery = new DirectMysqlQuery("accession", "a");
directQuery.outerJoin("taxonomy2", "t", "t.id=a.taxonomyId2");
directQuery.jsonFilter(filter, new MethodResolver() {
......@@ -258,7 +257,7 @@ public class GenesysLowlevelRepositoryImpl implements GenesysLowlevelRepository
}
@Override
public void listAccessionsGeo(final ObjectNode filter, final RowCallbackHandler rowCallbackHandler) {
public void listAccessionsGeo(final AppliedFilters filter, final RowCallbackHandler rowCallbackHandler) {
final DirectMysqlQuery directQuery = new DirectMysqlQuery("accessiongeo", "geo");
directQuery.innerJoin("accession", "a", "a.id=geo.accessionId");
directQuery.jsonFilter(filter, new MethodResolver() {
......@@ -285,7 +284,7 @@ public class GenesysLowlevelRepositoryImpl implements GenesysLowlevelRepository
}
@Override
public void listAccessionsAlias(final ObjectNode filter, final RowCallbackHandler rowCallbackHandler) {
public void listAccessionsAlias(final AppliedFilters filter, final RowCallbackHandler rowCallbackHandler) {
// from n inner join accession a on a.id=n.accessionId
final DirectMysqlQuery directQuery = new DirectMysqlQuery("accessionalias", "n");
directQuery.innerJoin("accession", "a", "a.id=n.accessionId");
......@@ -326,7 +325,7 @@ public class GenesysLowlevelRepositoryImpl implements GenesysLowlevelRepository
}
@Override
public void listAccessionsColl(final ObjectNode filter, final RowCallbackHandler rowCallbackHandler) {
public void listAccessionsColl(final AppliedFilters filter, final RowCallbackHandler rowCallbackHandler) {
// from accessioncollect coll inner join accession a on
// a.id=coll.accessionId
final DirectMysqlQuery directQuery = new DirectMysqlQuery("accessioncollect", "coll");
......
......@@ -19,13 +19,14 @@ package org.genesys2.server.service;
import java.util.Collection;
import org.genesys2.server.model.elastic.AccessionDetails;
import org.genesys2.server.service.impl.FilterHandler.AppliedFilters;
import org.genesys2.server.service.impl.SearchException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
public interface ElasticService {
void reindexByFilter(String jsonFilter, boolean slow);
void reindexByFilter(AppliedFilters filters, boolean slow);
Page<AccessionDetails> search(String query, Pageable pageable) throws SearchException;
......@@ -39,4 +40,5 @@ public interface ElasticService {
Page<AccessionDetails> filter(String jsonFilter, Pageable pageable) throws SearchException;
}
......@@ -55,4 +55,6 @@ public interface FilterConstants {
public static final String TAXONOMY_SPECIES = "taxonomy.species";
public static final String TAXONOMY_GENUS = "taxonomy.genus";
public static final String ID = "id";
}
......@@ -19,21 +19,20 @@ package org.genesys2.server.service;
import java.util.List;
import org.genesys2.server.model.genesys.Accession;
import org.genesys2.server.service.impl.FilterHandler.AppliedFilters;
import org.genesys2.server.service.impl.GenesysFilterServiceImpl.LabelValue;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.jdbc.core.RowCallbackHandler;
import com.fasterxml.jackson.databind.node.ObjectNode;
public interface GenesysFilterService {
Page<Accession> listAccessions(ObjectNode jsonTree, Pageable pageable);
Page<Accession> listAccessions(AppliedFilters filters, Pageable pageable);
List<LabelValue<String>> autocomplete(String filter, String ac,ObjectNode jsonTree);
List<LabelValue<String>> autocomplete(String filter, String ac, AppliedFilters filters);
void listGeo(ObjectNode jsonTree, Integer limit, RowCallbackHandler rowHandler);
void listGeo(AppliedFilters filters, Integer limit, RowCallbackHandler rowHandler);
void listGeoTile(boolean distinct, ObjectNode jsonTree, Integer limit, int zoom, int xtile, int ytile, RowCallbackHandler rowHandler);
void listGeoTile(boolean distinct, AppliedFilters filters, Integer limit, int zoom, int xtile, int ytile, RowCallbackHandler rowHandler);
}
......@@ -42,6 +42,7 @@ import org.genesys2.server.model.impl.Country;
import org.genesys2.server.model.impl.Crop;
import org.genesys2.server.model.impl.FaoInstitute;
import org.genesys2.server.model.impl.Organization;
import org.genesys2.server.service.impl.FilterHandler.AppliedFilters;
import org.genesys2.server.service.impl.NonUniqueAccessionException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
......@@ -149,7 +150,7 @@ public interface GenesysService {
long countDatasets(FaoInstitute faoInstitute);
void writeAccessions(String jsonFilter, OutputStream outputStream) throws IOException;
void writeAccessions(AppliedFilters filters, OutputStream outputStream) throws IOException;
List<AccessionAlias> saveAliases(List<AccessionAlias> aliases);
......@@ -183,7 +184,7 @@ public interface GenesysService {
Set<Long> listAccessions(FaoInstitute holdingInstitute, Set<Long> accessionIds);
int countAccessions(String jsonFilter);
int countAccessions(AppliedFilters filters);
List<AccessionRemark> saveRemarks(List<AccessionRemark> toSaveRemarks);
......
......@@ -18,15 +18,17 @@ package org.genesys2.server.service;
import java.io.IOException;
import org.genesys2.server.service.impl.FilterHandler.AppliedFilters;
public interface MappingService {
void clearCache();
String filteredKml(String jsonFilter);
String filteredKml(AppliedFilters filters);
String filteredGeoJson(String string, Integer limit) throws IOException;
String filteredGeoJson(AppliedFilters filters, Integer limit) throws IOException;
byte[] getTile(String jsonFilter, int zoom, int xtile, int ytile);
byte[] getTile(AppliedFilters filters, int zoom, int xtile, int ytile);
public static class CoordUtil {
public static double tileToLon(int zoom, int xtile) {
......
......@@ -21,6 +21,7 @@ import org.genesys2.server.service.ElasticService;
import org.genesys2.server.service.FilterConstants;
import org.genesys2.server.service.GenesysFilterService;
import org.genesys2.server.service.GenesysService;
import org.genesys2.server.service.impl.FilterHandler.AppliedFilters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
......@@ -256,7 +257,7 @@ public class ElasticsearchSearchServiceImpl implements ElasticService, Initializ
}
@Override
public void reindexByFilter(String jsonFilter, boolean slow) {
public void reindexByFilter(AppliedFilters filters, boolean slow) {
LOG.info("Creating index");
elasticsearchTemplate.createIndex(AccessionDetails.class);
......@@ -265,19 +266,6 @@ public class ElasticsearchSearchServiceImpl implements ElasticService, Initializ
LOG.info("Refreshing");
elasticsearchTemplate.refresh(AccessionDetails.class, true);
ObjectNode jsonTree = null;
try {
if (StringUtils.isNotBlank(jsonFilter))
jsonTree = (ObjectNode) objectMapper.readTree(jsonFilter);
else {
LOG.warn("No filter provided. Quitting.");
return;
}
} catch (IOException e) {
LOG.error(e.getMessage(), e);
return;
}
StopWatch stopWatch = new StopWatch();
stopWatch.setKeepTaskList(false);
......@@ -288,7 +276,7 @@ public class ElasticsearchSearchServiceImpl implements ElasticService, Initializ
queries.clear();
stopWatch.start("Get data by filter");
Page<Accession> accessions = filterService.listAccessions(jsonTree, new PageRequest(page, size));
Page<Accession> accessions = filterService.listAccessions(filters, new PageRequest(page, size));
stopWatch.stop();
LOG.info(stopWatch.getLastTaskName() + " took " + stopWatch.getLastTaskTimeMillis());
......
......@@ -18,6 +18,7 @@ package org.genesys2.server.service.impl;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
......@@ -241,12 +242,23 @@ public class FilterHandler {
}
public static interface FilterValue {
String getType();
}
@JsonSerialize(using = AppliedFilters.Serializer.class)
@JsonDeserialize(using = AppliedFilters.Deserializer.class)
public static class AppliedFilters extends ArrayList<AppliedFilter> {
private static final ObjectMapper objectMapper = new ObjectMapper();
@Override
public String toString() {
try {
return objectMapper.writeValueAsString(this);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
public static class Serializer extends JsonSerializer<AppliedFilters> {
@Override
public void serialize(AppliedFilters filters, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
......@@ -357,6 +369,9 @@ public class FilterHandler {
if (jp.nextToken() != JsonToken.END_OBJECT)
throw new JsonParseException("Expecting }, got " + jp.getCurrentToken(), jp.getCurrentLocation());
} else if (jp.getCurrentToken() == JsonToken.END_ARRAY) {
// Blank array
break;
} else {
throw new JsonParseException("I don't know where I am.", jp.getCurrentLocation());
}
......@@ -377,6 +392,63 @@ public class FilterHandler {
return appliedFilters;
}
}
/**
* Get the first applied filter matching filterName
*
* @param filterName
* @return
*/
public AppliedFilter get(String filterName) {
for (AppliedFilter af : this) {
if (af.getFilterName().equals(filterName))
return af;
}
return null;
}
public Collection<AppliedFilter> methodFilters() {
return CollectionUtils.select(this, new Predicate<AppliedFilter>() {
@Override
public boolean evaluate(AppliedFilter filter) {
return filter.getFilterName().startsWith("gm:");
}
});
}
/**
* Collect filterNames from AppliedFilters in this list
*
* @return
*/
public String[] getFilterNames() {
List<String> filterNames = new ArrayList<String>();
for (AppliedFilter af : this) {
filterNames.add(af.getFilterName());
}
return filterNames.toArray(ArrayUtils.EMPTY_STRING_ARRAY);
}
/**
* Get first literal filter value
*
* @param filterName
* @param class1
* @return
*/
public <T> T getFirstLiteralValue(String filterName, Class<T> clazz) {
AppliedFilter af = get(filterName);
if (af != null) {
for (FilterValue fv : af.getValues()) {
if (fv instanceof LiteralValueFilter) {
Object obj = ((LiteralValueFilter) fv).getValue();
if (clazz.isAssignableFrom(obj.getClass()))
return (T) obj;
}
}
}
return null;
}
}
public static class AppliedFilter {
......@@ -454,6 +526,10 @@ public class FilterHandler {
return false;
return true;
}
public int size() {
return values.size();
}
}
@JsonSerialize(using = LiteralValueFilter.Serializer.class)
......@@ -500,6 +576,11 @@ public class FilterHandler {
return false;
return true;
}
@Override
public String getType() {
return "literal";
}
}
@JsonSerialize(using = ValueRangeFilter.Serializer.class)
......@@ -509,7 +590,7 @@ public class FilterHandler {
@Override
public void serialize(ValueRangeFilter value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeStartObject();
jgen.writeArrayFieldStart("range");
jgen.writeArrayFieldStart(value.getType());
jgen.writeObject(value.getFrom());
jgen.writeObject(value.getTo());
jgen.writeEndArray();
......@@ -538,6 +619,11 @@ public class FilterHandler {
this.to = number1.doubleValue() < number2.doubleValue() ? number2 : number1;
}
@Override
public String getType() {
return "range";
}
public Number getFrom() {
return from;
}
......@@ -584,7 +670,7 @@ public class FilterHandler {
@Override
public void serialize(MaxValueFilter value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeStartObject();
jgen.writeObjectField("max", value.getTo());
jgen.writeObjectField(value.getType(), value.getTo());
jgen.writeEndObject();
}
}
......@@ -600,6 +686,11 @@ public class FilterHandler {
this.to = max;
}
@Override
public String getType() {
return "max";
}
public Number getTo() {
return to;
}
......@@ -636,7 +727,7 @@ public class FilterHandler {
@Override
public void serialize(MinValueFilter value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeStartObject();
jgen.writeObjectField("min", value.getFrom());
jgen.writeObjectField(value.getType(), value.getFrom());
jgen.writeEndObject();
}
}
......@@ -652,6 +743,11 @@ public class FilterHandler {
this.from = min;
}
@Override
public String getType() {
return "min";
}
public Number getFrom() {
return from;
}
......@@ -689,7 +785,7 @@ public class FilterHandler {
@Override
public void serialize(StartsWithFilter value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeStartObject();
jgen.writeObjectField("like", value.getStartsWith());
jgen.writeObjectField(value.getType(), value.getStartsWith());
jgen.writeEndObject();
}
}
......@@ -700,6 +796,11 @@ public class FilterHandler {
this.startsWith = startsWith;
}
@Override
public String getType() {
return "like";
}
public String getStartsWith() {
return startsWith;
}
......
......@@ -20,31 +20,15 @@ import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import javax.sql.DataSource;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.Predicate;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.genesys2.server.model.filters.AutocompleteFilter;
import org.genesys2.server.model.filters.CodedMethodFilter;
import org.genesys2.server.model.filters.GenesysFilter;
import org.genesys2.server.model.filters.BasicFilter;
import org.genesys2.server.model.filters.I18nListFilter;
import org.genesys2.server.model.filters.MethodFilter;
import org.genesys2.server.model.filters.ValueName;
import org.genesys2.server.model.filters.GenesysFilter.DataType;
import org.genesys2.server.model.filters.GenesysFilter.FilterType;
import org.genesys2.server.model.genesys.Accession;
import org.genesys2.server.model.genesys.Method;
import org.genesys2.server.model.genesys.TraitCode;
import org.genesys2.server.model.impl.Country;
import org.genesys2.server.model.impl.Crop;
import org.genesys2.server.model.impl.FaoInstitute;
......@@ -59,6 +43,10 @@ import org.genesys2.server.service.InstituteService;
import org.genesys2.server.service.TaxonomyService;
import org.genesys2.server.service.TraitService;
import org.genesys2.server.service.impl.DirectMysqlQuery.MethodResolver;
import org.genesys2.server.service.impl.FilterHandler.AppliedFilter;
import org.genesys2.server.service.impl.FilterHandler.AppliedFilters;
import org.genesys2.server.service.impl.FilterHandler.FilterValue;
import org.genesys2.server.service.impl.FilterHandler.LiteralValueFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
......@@ -71,10 +59,6 @@ import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
@Service
@Transactional(readOnly = true)
public class GenesysFilterServiceImpl implements GenesysFilterService {
......@@ -92,7 +76,7 @@ public class GenesysFilterServiceImpl implements GenesysFilterService {
@Autowired
private TraitService traitService;
@Autowired
private GeoService geoService;
......@@ -107,24 +91,24 @@ public class GenesysFilterServiceImpl implements GenesysFilterService {
@Autowired
private TaxonomyService taxonomyService;
@Autowired
private CropService cropService;
@Autowired
private CropService cropService;
@Autowired
@Autowired
public void setDataSource(final DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
@Override
public Page<Accession> listAccessions(ObjectNode jsonTree, Pageable pageable) {
final Iterator<Entry<String, JsonNode>> fields = jsonTree.fields();
while (fields.hasNext()) {
final Entry<String, JsonNode> entry = fields.next();
LOG.debug("Looking at " + entry.getKey() + " = " + entry.getValue());
public Page<Accession> listAccessions(AppliedFilters filters, Pageable pageable) {
if (LOG.isDebugEnabled()) {
for (AppliedFilter filter : filters) {
LOG.debug("Looking at " + filter.toString());
}
}
final DirectMysqlQuery directQuery = new DirectMysqlQuery("accession", "a");
directQuery.jsonFilter(jsonTree, new MethodResolver() {
directQuery.jsonFilter(filters, new MethodResolver() {
@Override
public Method getMethod(long methodId) {
return methodRepository.findOne(methodId);
......@@ -153,18 +137,18 @@ public class GenesysFilterServiceImpl implements GenesysFilterService {
* Filtering autocompleter
*/
@Override
public List<LabelValue<String>> autocomplete(String filter, String ac,ObjectNode jsonTree) {
public List<LabelValue<String>> autocomplete(String filter, String ac, AppliedFilters filters) {
if (LOG.isDebugEnabled()) {
LOG.debug("Autocomplete " + filter + " ac=" + ac);
}
String shortName = null;
try {
shortName = jsonTree.get(FilterConstants.CROPS).get(0).asText();
} catch (NullPointerException e) {
LOG.info("Crop not selected");
}
Crop crop = cropService.getCrop(shortName);
Crop crop = null;
{
String shortName = filters.getFirstLiteralValue(FilterConstants.CROPS, String.class);
if (shortName != null)
crop = cropService.getCrop((String) shortName);
}
final List<LabelValue<String>> completed = new ArrayList<LabelValue<String>>();
if ("instCode".equalsIgnoreCase(filter)) {
......@@ -178,24 +162,21 @@ public class GenesysFilterServiceImpl implements GenesysFilterService {
completed.add(new LabelValue<String>(c.getCode3(), c.getCode3() + ", " + c.getName()));
}
} else if ("genus".equalsIgnoreCase(filter)) {
final List<String> genera = taxonomyService.autocompleteGenus(ac,crop);
final List<String> genera = taxonomyService.autocompleteGenus(ac, crop);
for (final String value : genera) {
completed.add(new LabelValue<String>(value, value));
}
} else if ("species".equalsIgnoreCase(filter)) {
List<String> genus= new ArrayList<>();
ArrayNode arrayRoot = (ArrayNode) jsonTree.get(FilterConstants.TAXONOMY_GENUS);
if (arrayRoot!=null){
Iterator<JsonNode> elements = arrayRoot.elements();
JsonNode element;
while(elements.hasNext()){
element = elements.next();
genus.add(element.asText());
}
}
final List<String> species = taxonomyService.autocompleteSpecies(ac,crop, genus);
List<String> genus = new ArrayList<>();