Commit 9c2de3eb authored by Matija Obreza's avatar Matija Obreza

Extracted TraitServiceImpl from GenesysServiceImpl

Introduced FilterHandler component
parent b2d9a268
......@@ -18,7 +18,6 @@ package org.genesys2.server.service;
import java.util.List;
import org.genesys2.server.model.filters.GenesysFilter;
import org.genesys2.server.model.genesys.Accession;
import org.genesys2.server.service.impl.GenesysFilterServiceImpl.LabelValue;
import org.springframework.data.domain.Page;
......@@ -29,15 +28,8 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
public interface GenesysFilterService {
String[] DEFAULT_FILTERS = { "crop", "sampStat", "genus", "taxon", "orgCty", "latitude", "longitude", "organization", "instCode", "acceNumb", "available",
"mlsStat", "inTrust", "inSvalbard" };
Page<Accession> listAccessions(ObjectNode jsonTree, Pageable pageable);
List<GenesysFilter> listAvailableFilters();
List<GenesysFilter> selectFilters(String[] selectedFilters);
List<LabelValue<String>> autocomplete(String filter, String ac,ObjectNode jsonTree);
void listGeo(ObjectNode jsonTree, Integer limit, RowCallbackHandler rowHandler);
......
......@@ -88,8 +88,6 @@ public interface GenesysService {
Page<Accession> listMetadataAccessions(long metadataId, Pageable pageable);
List<Method> listMethods(Accession accession);
Map<Long, List<ExperimentTrait>> getAccessionTraitValues(Accession accession);
Map<Long, Map<Long, List<Object>>> getMetadataTraitValues(Metadata metadata, List<Accession> content);
......
......@@ -19,6 +19,7 @@ package org.genesys2.server.service;
import java.util.List;
import java.util.Map;
import org.genesys2.server.model.genesys.Accession;
import org.genesys2.server.model.genesys.Metadata;
import org.genesys2.server.model.genesys.Method;
import org.genesys2.server.model.genesys.Parameter;
......@@ -141,4 +142,6 @@ public interface TraitService {
Map<Long, List<Method>> mapMethods(Crop crop);
List<Method> listMethods(Accession accession);
}
/**
* Copyright 2014 Global Crop Diversity Trust
*
* 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 org.genesys2.server.service.impl;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
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.BasicFilter;
import org.genesys2.server.model.filters.CodedMethodFilter;
import org.genesys2.server.model.filters.GenesysFilter;
import org.genesys2.server.model.filters.GenesysFilter.DataType;
import org.genesys2.server.model.filters.GenesysFilter.FilterType;
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.genesys.Method;
import org.genesys2.server.model.genesys.TraitCode;
import org.genesys2.server.service.FilterConstants;
import org.genesys2.server.service.TraitService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* Converts filter requests (usually JSON) to internal data structures
*
* @author matijaobreza
*
*/
@Component
public class FilterHandler {
private static final Log LOG = LogFactory.getLog(FilterHandler.class);
@Autowired
private TraitService traitService;
@Autowired
private ObjectMapper objectMapper;
private final ArrayList<GenesysFilter> availableFilters;
public FilterHandler() {
this.availableFilters = new ArrayList<GenesysFilter>();
this.availableFilters.add(new BasicFilter(FilterConstants.CROPS, DataType.STRING));
this.availableFilters.add(new I18nListFilter<Integer>(FilterConstants.SAMPSTAT, DataType.NUMERIC).build("accession.sampleStatus", new Integer[] { 100,
110, 120, 130, 200, 300, 400, 410, 411, 412, 413, 414, 415, 416, 420, 421, 422, 423, 500, 600, 999 }));
this.availableFilters.add(new AutocompleteFilter(FilterConstants.TAXONOMY_GENUS, "/explore/ac/genus"));
this.availableFilters.add(new AutocompleteFilter(FilterConstants.TAXONOMY_SPECIES, "/explore/ac/species"));
this.availableFilters.add(new AutocompleteFilter(FilterConstants.TAXONOMY_SCINAME, "/explore/ac/taxonomy"));
this.availableFilters.add(new AutocompleteFilter(FilterConstants.ORGCTY_ISO3, "/explore/ac/country"));
this.availableFilters.add(new BasicFilter(FilterConstants.GEO_LATITUDE, DataType.NUMERIC));
this.availableFilters.add(new BasicFilter(FilterConstants.GEO_LONGITUDE, DataType.NUMERIC));
this.availableFilters.add(new BasicFilter(FilterConstants.GEO_ELEVATION, DataType.NUMERIC));
this.availableFilters.add(new BasicFilter(FilterConstants.ORGANIZATION, DataType.STRING));
this.availableFilters.add(new AutocompleteFilter(FilterConstants.INSTCODE, "/explore/ac/instCode"));
this.availableFilters.add(new BasicFilter(FilterConstants.ACCENUMB, DataType.STRING, FilterType.RANGE));
this.availableFilters.add(new BasicFilter(FilterConstants.ALIAS, DataType.STRING, FilterType.RANGE));
this.availableFilters.add(new BasicFilter(FilterConstants.SGSV, DataType.BOOLEAN));
this.availableFilters.add(new BasicFilter(FilterConstants.MLSSTATUS, DataType.BOOLEAN));
this.availableFilters.add(new BasicFilter(FilterConstants.ART15, DataType.BOOLEAN));
this.availableFilters.add(new BasicFilter(FilterConstants.AVAILABLE, DataType.BOOLEAN));
this.availableFilters.add(new BasicFilter(FilterConstants.COLLMISSID, DataType.STRING));
this.availableFilters.add(new I18nListFilter<Integer>(FilterConstants.STORAGE, DataType.NUMERIC).build("accession.storage", new Integer[] { 10, 11, 12,
13, 20, 30, 40, 50, 99 }));
}
public List<GenesysFilter> listAvailableFilters() {
return Collections.unmodifiableList(this.availableFilters);
}
public List<GenesysFilter> selectFilters(String[] selectedFilters) {
LOG.debug("Loading filter definitions sel=" + ArrayUtils.toString(selectedFilters));
final List<GenesysFilter> filters = new ArrayList<GenesysFilter>();
for (final String selectedFilter : selectedFilters) {
if (selectedFilter.startsWith("gm:")) {
try {
final GenesysFilter methodFilter = getMethodFilter(Long.parseLong(selectedFilter.substring(3)));
if (methodFilter != null) {
filters.add(methodFilter);
}
} catch (NumberFormatException | NullPointerException e) {
LOG.warn(e);
}
} else {
final GenesysFilter coreFilter = CollectionUtils.find(this.availableFilters, new Predicate<GenesysFilter>() {
@Override
public boolean evaluate(GenesysFilter object) {
return object.getKey().equals(selectedFilter);
}
});
if (coreFilter != null) {
filters.add(coreFilter);
}
}
}
return filters;
}
GenesysFilter getMethodFilter(long methodId) {
final Method method = traitService.getMethod(methodId);
return method == null ? null : toFilter(method);
}
private GenesysFilter toFilter(Method method) {
DataType dataType = null;
switch (method.getFieldType()) {
case 1:
case 2:
dataType = DataType.NUMERIC;
break;
case 0:
dataType = DataType.STRING;
}
GenesysFilter filter = null;
if (method.isCoded()) {
final Map<String, Long> stats = traitService.getMethodStatistics(method);
final List<ValueName<?>> options = new ArrayList<ValueName<?>>();
for (final TraitCode traitCode : TraitCode.parseOptions(method.getOptions())) {
options.add(new ValueName<String>(traitCode.getCode(), traitCode.getValue(), stats.get(traitCode.getCode())));
}
filter = new CodedMethodFilter("gm:" + method.getId(), method.getParameter().getTitle(), dataType, options);
} else {
filter = new MethodFilter("gm:" + method.getId(), method.getParameter().getTitle(), dataType);
}
return filter;
}
public List<AppliedFilter> fromJSON(String jsonFilter) throws IOException {
Map<String, List<String>> filters = objectMapper.readValue(jsonFilter, Map.class);
List<AppliedFilter> appliedFilters = new ArrayList<AppliedFilter>();
for (String key : filters.keySet()) {
List<String> filterValues = filters.get(key);
if (filterValues == null || filterValues.isEmpty())
continue;
LOG.info("key=" + key);
}
return appliedFilters;
}
private static class AppliedFilter {
}
}
......@@ -79,12 +79,8 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
@Transactional(readOnly = true)
public class GenesysFilterServiceImpl implements GenesysFilterService {
private static final Log LOG = LogFactory.getLog(GenesysFilterServiceImpl.class);
private final ArrayList<GenesysFilter> availableFilters;
@Autowired
private TraitValueRepository traitValueRepository;
......@@ -119,101 +115,6 @@ public class GenesysFilterServiceImpl implements GenesysFilterService {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public GenesysFilterServiceImpl() {
this.availableFilters = new ArrayList<GenesysFilter>();
this.availableFilters.add(new BasicFilter(FilterConstants.CROPS, DataType.STRING));
this.availableFilters.add(new I18nListFilter<Integer>(FilterConstants.SAMPSTAT, DataType.NUMERIC).build("accession.sampleStatus", new Integer[] { 100,
110, 120, 130, 200, 300, 400, 410, 411, 412, 413, 414, 415, 416, 420, 421, 422, 423, 500, 600, 999 }));
this.availableFilters.add(new AutocompleteFilter(FilterConstants.TAXONOMY_GENUS, "/explore/ac/genus"));
this.availableFilters.add(new AutocompleteFilter(FilterConstants.TAXONOMY_SPECIES, "/explore/ac/species"));
this.availableFilters.add(new AutocompleteFilter(FilterConstants.TAXONOMY_SCINAME, "/explore/ac/taxonomy"));
this.availableFilters.add(new AutocompleteFilter(FilterConstants.ORGCTY_ISO3, "/explore/ac/country"));
this.availableFilters.add(new BasicFilter(FilterConstants.GEO_LATITUDE, DataType.NUMERIC));
this.availableFilters.add(new BasicFilter(FilterConstants.GEO_LONGITUDE, DataType.NUMERIC));
this.availableFilters.add(new BasicFilter(FilterConstants.GEO_ELEVATION, DataType.NUMERIC));
this.availableFilters.add(new BasicFilter(FilterConstants.ORGANIZATION, DataType.STRING));
this.availableFilters.add(new AutocompleteFilter(FilterConstants.INSTCODE, "/explore/ac/instCode"));
this.availableFilters.add(new BasicFilter(FilterConstants.ACCENUMB, DataType.STRING, FilterType.RANGE));
this.availableFilters.add(new BasicFilter(FilterConstants.ALIAS, DataType.STRING, FilterType.RANGE));
this.availableFilters.add(new BasicFilter(FilterConstants.SGSV, DataType.BOOLEAN));
this.availableFilters.add(new BasicFilter(FilterConstants.MLSSTATUS, DataType.BOOLEAN));
this.availableFilters.add(new BasicFilter(FilterConstants.ART15, DataType.BOOLEAN));
this.availableFilters.add(new BasicFilter(FilterConstants.AVAILABLE, DataType.BOOLEAN));
this.availableFilters.add(new BasicFilter(FilterConstants.COLLMISSID, DataType.STRING));
this.availableFilters.add(new I18nListFilter<Integer>(FilterConstants.STORAGE, DataType.NUMERIC).build("accession.storage", new Integer[] { 10, 11, 12,
13, 20, 30, 40, 50, 99 }));
}
@Override
public List<GenesysFilter> listAvailableFilters() {
return Collections.unmodifiableList(this.availableFilters);
}
@Override
public List<GenesysFilter> selectFilters(String[] selectedFilters) {
LOG.debug("Loading filter definitions sel=" + ArrayUtils.toString(selectedFilters));
final List<GenesysFilter> filters = new ArrayList<GenesysFilter>();
for (final String selectedFilter : selectedFilters) {
if (selectedFilter.startsWith("gm:")) {
try {
final GenesysFilter methodFilter = getMethodFilter(Long.parseLong(selectedFilter.substring(3)));
if (methodFilter != null) {
filters.add(methodFilter);
}
} catch (NumberFormatException | NullPointerException e) {
LOG.warn(e);
}
} else {
final GenesysFilter coreFilter = CollectionUtils.find(this.availableFilters, new Predicate<GenesysFilter>() {
@Override
public boolean evaluate(GenesysFilter object) {
return object.getKey().equals(selectedFilter);
}
});
if (coreFilter != null) {
filters.add(coreFilter);
}
}
}
return filters;
}
GenesysFilter getMethodFilter(long methodId) {
final Method method = methodRepository.findOne(methodId);
return method == null ? null : toFilter(method);
}
private GenesysFilter toFilter(Method method) {
DataType dataType = null;
switch (method.getFieldType()) {
case 1:
case 2:
dataType = DataType.NUMERIC;
break;
case 0:
dataType = DataType.STRING;
}
GenesysFilter filter = null;
if (method.isCoded()) {
final Map<String, Long> stats = traitService.getMethodStatistics(method);
final List<ValueName<?>> options = new ArrayList<ValueName<?>>();
for (final TraitCode traitCode : TraitCode.parseOptions(method.getOptions())) {
options.add(new ValueName<String>(traitCode.getCode(), traitCode.getValue(), stats.get(traitCode.getCode())));
}
filter = new CodedMethodFilter("gm:" + method.getId(), method.getParameter().getTitle(), dataType, options);
} else {
filter = new MethodFilter("gm:" + method.getId(), method.getParameter().getTitle(), dataType);
}
return filter;
}
@Override
public Page<Accession> listAccessions(ObjectNode jsonTree, Pageable pageable) {
final Iterator<Entry<String, JsonNode>> fields = jsonTree.fields();
......
......@@ -26,7 +26,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
......@@ -55,8 +54,6 @@ import org.genesys2.server.model.genesys.ExperimentAccessionTrait;
import org.genesys2.server.model.genesys.ExperimentTrait;
import org.genesys2.server.model.genesys.Metadata;
import org.genesys2.server.model.genesys.Method;
import org.genesys2.server.model.genesys.Parameter;
import org.genesys2.server.model.genesys.ParameterCategory;
import org.genesys2.server.model.genesys.SvalbardData;
import org.genesys2.server.model.genesys.Taxonomy2;
import org.genesys2.server.model.genesys.TraitCode;
......@@ -81,8 +78,6 @@ import org.genesys2.server.persistence.domain.MetadataMethodRepository;
import org.genesys2.server.persistence.domain.MetadataRepository;
import org.genesys2.server.persistence.domain.MethodRepository;
import org.genesys2.server.persistence.domain.OrganizationRepository;
import org.genesys2.server.persistence.domain.ParameterCategoryRepository;
import org.genesys2.server.persistence.domain.ParameterRepository;
import org.genesys2.server.persistence.domain.SvalbardRepository;
import org.genesys2.server.persistence.domain.TraitValueRepository;
import org.genesys2.server.security.AuthUserDetails;
......@@ -92,16 +87,12 @@ import org.genesys2.server.service.DatasetService;
import org.genesys2.server.service.GenesysService;
import org.genesys2.server.service.HtmlSanitizer;
import org.genesys2.server.service.TaxonomyService;
import org.genesys2.server.service.TraitService;
import org.genesys2.spring.SecurityContextUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.data.domain.Sort.Order;
import org.springframework.data.repository.query.Param;
import org.springframework.jdbc.core.RowCallbackHandler;
import org.springframework.security.access.prepost.PreAuthorize;
......@@ -118,10 +109,20 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
@Service
@Transactional(readOnly = true)
public class GenesysServiceImpl implements GenesysService, TraitService, DatasetService {
public class GenesysServiceImpl implements GenesysService, DatasetService {
public static final Log LOG = LogFactory.getLog(GenesysServiceImpl.class);
// Services
@Autowired
private TaxonomyService taxonomyService;
@Autowired
private AclService aclService;
@Autowired
private HtmlSanitizer htmlSanitizer;
// Repositories
@Autowired
private AccessionRepository accessionRepository;
@Autowired
......@@ -143,17 +144,10 @@ public class GenesysServiceImpl implements GenesysService, TraitService, Dataset
@Autowired
private TraitValueRepository traitValueRepository;
@Autowired
private TaxonomyService taxonomyService;
private MethodRepository methodRepository;
@Autowired
private CropTaxonomyRepository cropTaxonomyRepository;
@Autowired
private ParameterCategoryRepository parameterCategoryRepository;
@Autowired
private ParameterRepository parameterRepository;
@Autowired
private MethodRepository methodRepository;
@Autowired
private OrganizationRepository organizationRepository;
@Autowired
private FaoInstituteRepository instituteRepository;
......@@ -162,10 +156,6 @@ public class GenesysServiceImpl implements GenesysService, TraitService, Dataset
@Autowired
private SvalbardRepository svalbardRepository;
@Autowired
private AclService aclService;
@Autowired
private HtmlSanitizer htmlSanitizer;
@Autowired
private AccessionAliasRepository accessionAliasRepository;
@Autowired
private AccessionRemarkRepository accessionRemarkRepository;
......@@ -427,12 +417,6 @@ public class GenesysServiceImpl implements GenesysService, TraitService, Dataset
return x.size() == 0 ? null : metadataRepository.findByIds(x);
}
@Override
public List<Method> listMethods(Accession accession) {
final List<Long> x = accessionTraitRepository.listMethodIds(accession);
return x.size() == 0 ? null : methodRepository.findByIds(x);
}
@Override
public Page<Metadata> listMetadata(Pageable pageable) {
return metadataRepository.findAll(pageable);
......@@ -531,55 +515,6 @@ public class GenesysServiceImpl implements GenesysService, TraitService, Dataset
return accessionRepository.findByInstitute(members, pageable);
}
@Override
public List<ParameterCategory> listCategories() {
return parameterCategoryRepository.findAll(new Sort(new Order(Direction.ASC, "id")));
}
@Override
public List<Parameter> listTraits() {
return parameterRepository.findAll(new Sort(new Order(Direction.ASC, "id")));
}
@Override
public Page<Parameter> listTraits(Pageable pageable) {
return parameterRepository.findAll(pageable);
}
@Override
public Page<Parameter> listTraits(Crop crop, Pageable pageable) {
return parameterRepository.findByCrop(crop, pageable);
}
@Override
public Parameter getTrait(long traitId) {
return parameterRepository.findOne(traitId);
}
@Override
public List<Method> getTraitMethods(Parameter trait) {
return methodRepository.findByParameter(trait);
}
@Override
public Method getMethod(long methodId) {
return methodRepository.findOne(methodId);
}
@Override
public List<Method> listMethods() {
return methodRepository.findAll(new Sort(new Order(Direction.ASC, "id")));
}
@Override
public Page<Method> listMethods(Pageable pageable) {
return methodRepository.findAll(pageable);
}
@Override
public List<Metadata> listMetadataByMethod(Method method) {
return metadataMethodRepository.listMetadataByMethodId(method.getId());
}
@Override
@PreAuthorize("hasRole('ADMINISTRATOR')")
......@@ -807,154 +742,6 @@ public class GenesysServiceImpl implements GenesysService, TraitService, Dataset
}
@Override
@PreAuthorize("isAuthenticated()")
@Transactional(readOnly = false)
public ParameterCategory addCategory(String name, String i18n) {
final ParameterCategory category = new ParameterCategory();
category.setName(name);
category.setNameL(i18n);
parameterCategoryRepository.save(category);
return category;
}
@Override
@PreAuthorize("isAuthenticated()")
@Transactional(readOnly = true)
public ParameterCategory getCategory(String name) {
final ParameterCategory category = parameterCategoryRepository.findByName(name);
return category;
}
@Override
@PreAuthorize("isAuthenticated()")
@Transactional(readOnly = false)
public Parameter addParameter(String rdfUri, Crop crop, String category, String title, String i18n) {
final Parameter parameter = new Parameter();
parameter.setRdfUri(StringUtils.defaultIfBlank(rdfUri, null));
parameter.setCrop(crop);
// In an ideal world, we should search for category by URI, not name...
final ParameterCategory parameterCategory = parameterCategoryRepository.findByName(category);
parameter.setCategory(parameterCategory);
parameter.setTitle(title);
parameter.setI18n(StringUtils.defaultIfBlank(i18n, null));
parameterRepository.save(parameter);
return parameter;
}
@Override
@PreAuthorize("isAuthenticated()")
@Transactional(readOnly = true)
public Parameter getParameter(String rdfUri) {
if (rdfUri == null || rdfUri.isEmpty()) {
return null;
}
final Parameter parameter = parameterRepository.findByRdfUri(rdfUri); // assumes
// that
// crop
// x
// title
// is
// unique(?)
return parameter;
}
@Override
@PreAuthorize("isAuthenticated()")
@Transactional(readOnly = true)
public Parameter getParameter(Crop crop, String title) {
final Parameter parameter = parameterRepository.findByCropAndTitle(crop, title); // assumes
// that
// crop
// x
// title
// is