Commit 36d25f39 authored by Matija Obreza's avatar Matija Obreza

Merge branch 'filter-subsets-datasets' into 'master'

Filter subsets datasets

See merge request genesys-pgr/genesys-server!455
parents 1207f049 304f3ec2
......@@ -15,8 +15,6 @@
*/
package org.genesys.catalog.model.filters;
import static org.genesys.catalog.model.dataset.QDataset.dataset;
import java.util.HashSet;
import java.util.Set;
......@@ -24,6 +22,7 @@ import org.apache.commons.collections4.CollectionUtils;
import org.genesys.blocks.model.filters.StringFilter;
import org.genesys.blocks.model.filters.UuidModelFilter;
import org.genesys.catalog.model.dataset.Dataset;
import org.genesys.catalog.model.dataset.QDataset;
import org.genesys2.server.model.PublishState;
import org.genesys2.server.service.filter.IFullTextFilter;
......@@ -72,6 +71,7 @@ public class DatasetFilter extends UuidModelFilter<DatasetFilter, Dataset> imple
/** Is current version */
public Boolean current;
/**
* Builds the query.
......@@ -79,6 +79,15 @@ public class DatasetFilter extends UuidModelFilter<DatasetFilter, Dataset> imple
* @return the predicate
*/
public Predicate buildPredicate() {
return buildQuery(QDataset.dataset);
}
/**
* Builds the query.
*
* @return the predicate
*/
public Predicate buildQuery(QDataset dataset) {
final BooleanBuilder and = new BooleanBuilder();
super.buildQuery(dataset, dataset._super, and);
......
/**
* 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.api;
import java.util.Collection;
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.impl.Crop;
import org.genesys2.server.model.impl.CropRule;
import org.genesys2.server.model.impl.CropTaxonomy;
import org.genesys2.server.model.impl.Team;
import org.genesys2.server.model.impl.User;
import org.springframework.data.domain.Page;
public class OAuth2Cleanup {
public static <T> T clean(T t) {
if (t instanceof User) {
final User user = (User) t;
user.setId(null);
user.setPassword(null);
}
if (t instanceof Method) {
final Method method = (Method) t;
method.setParameter(null);
}
if (t instanceof Parameter) {
final Parameter param = (Parameter) t;
param.setCrop(null);
}
if (t instanceof Crop) {
final Crop crop = (Crop) t;
crop.setCropRules(null);
}
if (t instanceof CropRule) {
final CropRule cropRule = (CropRule) t;
cropRule.setCrop(null);
cropRule.setId(null);
}
if (t instanceof CropTaxonomy) {
final CropTaxonomy cropTaxa = (CropTaxonomy) t;
cropTaxa.setCrop(null);
cropTaxa.getTaxonomy().setCropTaxonomies(null);
}
if (t instanceof Team) {
final Team team = (Team) t;
team.setMembers(null);
team.setInstitutes(null);
}
if (t instanceof Metadata) {
// Metadata metadata = (Metadata) t;
}
return t;
}
public static <T> Collection<T> clean(Collection<T> x) {
for (final T m : x) {
clean(m);
}
return x;
}
public static <T> Page<T> clean(Page<T> x) {
for (final T m : x.getContent()) {
clean(m);
}
return x;
}
}
......@@ -40,13 +40,11 @@ import org.genesys2.server.model.json.AccessionJson;
import org.genesys2.server.model.json.Api0Constants;
import org.genesys2.server.model.json.Api1Constants;
import org.genesys2.server.service.ElasticsearchService;
import org.genesys2.server.service.GenesysFilterService;
import org.genesys2.server.service.GenesysRESTService;
import org.genesys2.server.service.GenesysService;
import org.genesys2.server.service.GeoService;
import org.genesys2.server.service.InstituteService;
import org.genesys2.server.service.TaxonomyService;
import org.genesys2.server.service.impl.FilterHandler.AppliedFilters;
import org.genesys2.server.service.impl.NonUniqueAccessionException;
import org.genesys2.server.service.impl.RESTApiException;
import org.genesys2.server.service.impl.RESTApiValueException;
......@@ -58,9 +56,6 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.CannotAcquireLockException;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.TransactionException;
......@@ -94,9 +89,6 @@ public class AccessionController extends ApiBaseController {
@Autowired
GenesysService genesysService;
@Autowired
private GenesysFilterService filterService;
@Autowired
private AccessionUploader uploader;
......@@ -385,19 +377,6 @@ public class AccessionController extends ApiBaseController {
return restService.getAccessionJSON(accessionIds);
}
@RequestMapping(value = "/filter", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public Object getAcc(@RequestBody AppliedFilters appliedFilters, @RequestParam(name = "p", required = false, defaultValue = "1") int page,
@RequestParam(name = "l", required = false, defaultValue = "50") int pageSize) throws IOException {
if (LOG.isDebugEnabled()) {
LOG.debug(appliedFilters.toString());
}
Page<AccessionDetails> accessions = filterService.listAccessionDetails(appliedFilters, new PageRequest(page, Integer.min(pageSize, maxPageSize), new Sort("seqNo")));
return accessions;
}
@PostMapping(value="/details", consumes = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public List<AccessionDetails> getDetails(@RequestBody Set<AccessionHeaderJson> acceIds) throws RESTApiException {
......
......@@ -16,33 +16,25 @@
package org.genesys2.server.api.v0;
import java.io.EOFException;
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import javax.servlet.http.HttpServletResponse;
import javax.xml.bind.ValidationException;
import org.genesys2.server.api.ApiBaseController;
import org.genesys2.server.api.ModelValidationException;
import org.genesys2.server.api.OAuth2Cleanup;
import org.genesys2.server.exception.AuthorizationException;
import org.genesys2.server.exception.NotFoundElement;
import org.genesys2.server.model.genesys.Parameter;
import org.genesys2.server.model.impl.Crop;
import org.genesys2.server.model.impl.CropRule;
import org.genesys2.server.model.impl.CropTaxonomy;
import org.genesys2.server.service.CropService;
import org.genesys2.server.service.GenesysService;
import org.genesys2.server.service.TraitService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
......@@ -65,9 +57,6 @@ public class CropsController extends ApiBaseController {
@Autowired
GenesysService genesysService;
@Autowired
TraitService traitService;
@Autowired
CropService cropService;
......@@ -138,21 +127,6 @@ public class CropsController extends ApiBaseController {
return cropService.delete(cropService.getCrop(shortName));
}
/**
* Get crop descriptors /crops/{shortName}/descriptors
* @return
*
* @return
* @throws AuthorizationException
*/
@RequestMapping(value = "/{shortName}/descriptors", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE })
public Page<Parameter> getCropDescriptors(@PathVariable("shortName") String shortName) throws AuthorizationException {
LOG.info("Getting crop descriptors {}", shortName);
final Crop crop = cropService.getCrop(shortName);
final Page<Parameter> descriptors = traitService.listTraits(crop, new PageRequest(0, 50));
return OAuth2Cleanup.clean(descriptors);
}
/**
* Get crop taxonomy rules /crops/{shortName}/rules
* @return
......@@ -200,7 +174,7 @@ public class CropsController extends ApiBaseController {
LOG.info("Getting crop taxa {}", shortName);
final Crop crop = cropService.getCrop(shortName);
final Page<CropTaxonomy> cropTaxa = cropService.getCropTaxonomies(crop, new PageRequest(0, 50));
return OAuth2Cleanup.clean(cropTaxa);
return cropTaxa;
}
/**
......@@ -230,26 +204,4 @@ public class CropsController extends ApiBaseController {
cropService.rebuildTaxonomies(crop);
}
@RequestMapping(value = "/{shortName}/descriptors/xlsx", method = RequestMethod.POST)
public void downloadExcel(ModelMap model, @PathVariable(value = "shortName") String shortName, HttpServletResponse response) throws IOException {
final Crop crop = cropService.getCrop(shortName);
if (crop == null) {
throw new NotFoundElement();
}
LOG.debug("Downloading descriptors for crop {}", shortName);
// Write descriptors to the stream.
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.addHeader("Content-Disposition", String.format("attachment; filename=\"genesys-descriptors-%1$s.xlsx\"", crop.getShortName()));
final OutputStream outputStream = response.getOutputStream();
try {
traitService.writeDescriptorsXlsx(crop, outputStream);
response.flushBuffer();
} catch (EOFException e) {
LOG.warn("Download was aborted: {}", e.getMessage());
}
}
}
......@@ -21,11 +21,8 @@ import java.util.List;
import org.genesys.blocks.oauth.service.OAuthClientDetailsService;
import org.genesys2.server.api.ApiBaseController;
import org.genesys2.server.api.ModelValidationException;
import org.genesys2.server.api.OAuth2Cleanup;
import org.genesys2.server.component.security.SecurityUtils;
import org.genesys2.server.exception.AuthorizationException;
import org.genesys2.server.exception.NotFoundElement;
import org.genesys2.server.model.impl.User;
import org.genesys2.server.service.InstituteService;
import org.genesys2.server.service.TeamService;
import org.genesys2.server.service.UserService;
......@@ -161,7 +158,7 @@ public class MeController extends ApiBaseController {
throw new ModelValidationException("Validation error", violations);
}
LOG.info("Creating team {}", teamJson);
return OAuth2Cleanup.clean(teamService.addTeam(teamJson.name));
return teamService.addTeam(teamJson.name);
}
@RequestMapping(value = "/teams/{teamId}/leave", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
......
......@@ -24,15 +24,12 @@ import org.genesys.blocks.model.JsonViews;
import org.genesys.filerepository.InvalidRepositoryPathException;
import org.genesys2.server.api.ApiBaseController;
import org.genesys2.server.api.ModelValidationException;
import org.genesys2.server.api.OAuth2Cleanup;
import org.genesys2.server.exception.AuthorizationException;
import org.genesys2.server.exception.NotFoundElement;
import org.genesys2.server.model.genesys.Parameter;
import org.genesys2.server.model.impl.Crop;
import org.genesys2.server.model.impl.CropRule;
import org.genesys2.server.model.impl.CropTaxonomy;
import org.genesys2.server.service.CropService;
import org.genesys2.server.service.TraitService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.data.domain.Page;
......@@ -60,9 +57,6 @@ public class CropsController extends ApiBaseController {
public static final String CONTROLLER_URL = ApiBaseController.APIv1_BASE + "/crops";
@Autowired
private TraitService traitService;
@Autowired
private CropService cropService;
......@@ -163,21 +157,6 @@ public class CropsController extends ApiBaseController {
return cropService.delete(cropService.getCrop(shortName));
}
/**
* Get crop descriptors /crops/{shortName}/descriptors
* @return
*
* @return
* @throws AuthorizationException
*/
@RequestMapping(value = "/{shortName}/descriptors", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE })
public Page<Parameter> getCropDescriptors(@PathVariable("shortName") String shortName) throws AuthorizationException {
LOG.info("Getting crop descriptors {}", shortName);
final Crop crop = cropService.getCrop(shortName);
final Page<Parameter> descriptors = traitService.listTraits(crop, new PageRequest(0, 50));
return OAuth2Cleanup.clean(descriptors);
}
/**
* Get crop taxonomy rules /crops/{shortName}/rules
* @return
......@@ -225,8 +204,7 @@ public class CropsController extends ApiBaseController {
public Page<CropTaxonomy> getCropTaxa(@PathVariable("shortName") String shortName) throws AuthorizationException {
LOG.info("Getting crop taxa {}", shortName);
final Crop crop = cropService.getCrop(shortName);
final Page<CropTaxonomy> cropTaxa = cropService.getCropTaxonomies(crop, new PageRequest(0, 50));
return OAuth2Cleanup.clean(cropTaxa);
return cropService.getCropTaxonomies(crop, new PageRequest(0, 50));
}
/**
......
......@@ -16,6 +16,9 @@
package org.genesys2.server.component.aspect;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import javax.annotation.Resource;
......@@ -26,6 +29,7 @@ import org.aspectj.lang.annotation.Aspect;
import org.genesys2.server.component.elastic.ElasticReindex;
import org.genesys2.server.model.genesys.Accession;
import org.genesys2.server.model.genesys.AccessionId;
import org.genesys2.server.model.genesys.AccessionRef;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -59,6 +63,24 @@ public class ExtraReindexingAspect {
}
}
/**
* After AccessionIdRepository#save
*
* @param joinPoint the join point
* @param result the result
*/
@AfterReturning(value = "execution(* org.genesys2.server.persistence.AccessionRefRepository.save(..))", returning = "result")
public void afterPersistAccessionRef(final JoinPoint joinPoint, final Object result) {
LOG.trace("accessionRefRepository#save {} {}", joinPoint.toLongString(), joinPoint.getTarget());
try {
scheduleReindexing(result);
} catch (Throwable e) {
LOG.error(e.getMessage(), e);
}
}
/**
* Flatten collections (if Iterable) and check each object class if indexed
*
......@@ -72,13 +94,32 @@ public class ExtraReindexingAspect {
if (toReindex instanceof Iterable<?>) {
// Iterate and test
Iterable<?> it = (Iterable<?>) toReindex;
for (Object obj : it) {
scheduleReindexing(obj);
}
List<ElasticReindex> list = new ArrayList<>();
it.forEach((item) -> addNotNull(list, forReindexing(item)));
elasticReindexQueue.addAll(list);
} else {
addNotNull(elasticReindexQueue, forReindexing(toReindex));
}
}
private <T> void addNotNull(Collection<T> destination, T element) {
if (element != null) {
destination.add(element);
}
}
private ElasticReindex forReindexing(Object toReindex) {
if (toReindex instanceof AccessionId){
AccessionId accessionId = (AccessionId) toReindex;
LOG.trace("Scheduling reindexing of {} {}", Accession.class.getName(), accessionId.getId());
elasticReindexQueue.add(new ElasticReindex(Accession.class.getName(), accessionId.getId()));
return new ElasticReindex(Accession.class.getName(), accessionId.getId());
} else if (toReindex instanceof AccessionRef){
AccessionRef accessionRef = (AccessionRef) toReindex;
if (accessionRef.getAccession() != null) {
LOG.trace("Scheduling reindexing of {} {}", Accession.class.getName(), accessionRef.getAccession().getId());
return new ElasticReindex(Accession.class.getName(), accessionRef.getAccession().getId());
}
}
return null;
}
}
......@@ -18,8 +18,11 @@ package org.genesys2.server.component.elastic;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
......@@ -129,6 +132,7 @@ public class ElasticJPAListener {
}
}
/**
* Flatten collections (if Iterable) and check each object class if indexed
*
......@@ -142,23 +146,35 @@ public class ElasticJPAListener {
if (toReindex instanceof Iterable<?>) {
// Iterate and test
Iterable<?> it = (Iterable<?>) toReindex;
for (Object obj : it) {
scheduleReindexing(obj);
}
List<ElasticReindex> list = new ArrayList<>();
it.forEach((item) -> addNotNull(list, forReindexing(item)));
elasticReindexQueue.addAll(list);
} else {
Class<?> clazz = toReindex.getClass();
if (isIndexed(clazz)) {
LOG.trace("Scheduling reindexing of {} {}", clazz.getName(), toReindex);
if (toReindex instanceof BasicModel) {
BasicModel entity = (BasicModel) toReindex;
elasticReindexQueue.add(new ElasticReindex(clazz.getName(), entity.getId()));
} else {
LOG.warn("Don't know how to index {}. Not a BasicModel.", clazz.getName());
}
addNotNull(elasticReindexQueue, forReindexing(toReindex));
}
}
private <T> void addNotNull(Collection<T> destination, T element) {
if (element != null) {
destination.add(element);
}
}
private ElasticReindex forReindexing(Object toReindex) {
Class<?> clazz = toReindex.getClass();
if (isIndexed(clazz)) {
LOG.trace("Scheduling reindexing of {} {}", clazz.getName(), toReindex);
if (toReindex instanceof BasicModel) {
BasicModel entity = (BasicModel) toReindex;
return new ElasticReindex(clazz.getName(), entity.getId());
} else {
LOG.warn("Don't know how to index {}. Not a BasicModel.", clazz.getName());
}
}
return null;
}
private boolean isIndexed(Class<?> clazz) {
if (ignoredClasses.contains(clazz)) {
return false;
......
......@@ -69,6 +69,12 @@ public class ElasticQueryBuilder implements Visitor<Void, Void> {
if (path.equals("accessionId.lists.uuid")) {
// Example of @JsonIdentityReference(alwaysAsId = true)
return "lists";
} else if (path.equals("datasets.uuid")) {
// Example of @JsonIdentityReference(alwaysAsId = true)
return "datasets";
} else if (path.equals("subsets.uuid")) {
// Example of @JsonIdentityReference(alwaysAsId = true)
return "subsets";
} else if (path.startsWith("accessionId.")) {
// Example of @JsonUnwrapped
return path.replace("accessionId.", "");
......
......@@ -15,13 +15,7 @@
*/
package org.genesys2.server.component.listener;
import java.util.List;
import org.genesys.blocks.util.CurrentApplicationContext;
import org.genesys.catalog.model.ShortFilter;
import org.genesys.catalog.persistence.ShortFilterRepository;
import org.genesys.catalog.service.ShortFilterService;
import org.genesys.catalog.service.impl.ShortFilterServiceImpl;
import org.genesys2.server.component.security.AsAdminInvoker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -56,26 +50,26 @@ public class ApplicationUpgrades implements InitializingBean {
LOG.info("Executing {}", this.getClass().getName());
// aclEnsureClassOIDs();
// aclMakePartnersPublic();
upgradeShortFiltrerCodeFromV1ToV2();
// upgradeShortFiltrerCodeFromV1ToV2();
}
@Autowired
private ShortFilterRepository shortFilterRepository;
@Autowired
private ShortFilterService shortFilterService;
private void upgradeShortFiltrerCodeFromV1ToV2() throws Exception {
asAdminInvoker.invoke(() -> {
List<ShortFilter> allShortFilters = shortFilterRepository.findAll();
allShortFilters.forEach((filter) -> {
if (filter.getCode().startsWith(ShortFilterServiceImpl.CODE_PREFIX_V1)) {
shortFilterService.upgradeFilterCode(filter);
}
});
return true;
});
}
// @Autowired
// private ShortFilterRepository shortFilterRepository;
// @Autowired
// private ShortFilterService shortFilterService;
//
// private void upgradeShortFiltrerCodeFromV1ToV2() throws Exception {
// asAdminInvoker.invoke(() -> {
// List<ShortFilter> allShortFilters = shortFilterRepository.findAll();
// allShortFilters.forEach((filter) -> {
// if (filter.getCode().startsWith(ShortFilterServiceImpl.CODE_PREFIX_V1)) {
// shortFilterService.upgradeFilterCode(filter);
// }
// });
//
// return true;
// });
// }
// @Autowired
// private CustomAclService aclService;
......
package org.genesys2.server.model.elastic;
import java.math.BigDecimal;