Commit d8bb188c authored by Matija Obreza's avatar Matija Obreza

Merge branch 'ui-134-accession-map-info-click' into 'master'

Added api endpoint for receiving accession leaflet data

See merge request genesys-pgr/genesys-server!292
parents 266aa26a d2c4e722
Pipeline #7991 passed with stages
in 7 minutes
......@@ -69,6 +69,8 @@ import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.Sets;
import com.hazelcast.util.CollectionUtil;
......@@ -104,6 +106,8 @@ public class AccessionController {
@Autowired
private AccessionProcessor accessionProcessor;
private final ObjectMapper mapper = new ObjectMapper();
@Value("${base.url}")
private String baseUrl;
......@@ -248,6 +252,58 @@ public class AccessionController {
return mapInfo;
}
/**
* Returns accession json by filter
*
* @param limit - max count of accession returned
* @param filter - filter
* @return json with minimal accession data
*/
@PostMapping(value = "/geoJson", produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public ObjectNode geoJson(@RequestParam(value = "limit", required = false, defaultValue = "100") Long limit,
@RequestBody AccessionFilter filter) throws Exception {
final ObjectNode geoJson = mapper.createObjectNode();
final ArrayNode featuresArray = geoJson.arrayNode();
accessionProcessor.process(filter, (accession) -> {
final ObjectNode feature = featuresArray.objectNode();
feature.put("type", "Feature");
feature.put("id", accession.getId());
ObjectNode geometry;
feature.set("geometry", geometry = feature.objectNode());
geometry.put("type", "Point");
ArrayNode coordArray;
geometry.set("coordinates", coordArray = geometry.arrayNode());
coordArray.add(accession.getAccessionId().getGeo().getLongitude());
coordArray.add(accession.getAccessionId().getGeo().getLatitude());
ObjectNode properties;
feature.set("properties", properties = feature.objectNode());
properties.put("uuid", accession.getAccessionId().getUuid().toString());
properties.put("accessionNumber", accession.getAccessionNumber());
properties.put("instCode", accession.getInstCode());
properties.put("datum", accession.getAccessionId().getGeo().getDatum());
properties.put("uncertainty", accession.getAccessionId().getGeo().getUncertainty());
featuresArray.add(feature);
return accession;
}, limit);
geoJson.set("geoJson", featuresArray);
long accessionCount = accessionService.countAccessions(filter);
if (accessionCount > limit) {
geoJson.put("otherCount", accessionCount - limit);
}
return geoJson;
}
/**
* Get term overview for filters
*
......
......@@ -66,7 +66,7 @@ public class AccessionProcessor {
private int batchSize = 1000;
@Transactional(readOnly = true, propagation = Propagation.REQUIRES_NEW)
public void process(AccessionFilter filter, IAccessionAction action) throws Exception {
public void process(AccessionFilter filter, IAccessionAction action, Long maxSize) throws Exception {
Predicate predicate = filter.buildQuery();
long count = accessionRepository.count(predicate);
......@@ -74,17 +74,15 @@ public class AccessionProcessor {
PathBuilder<Accession> builder = new PathBuilderFactory().create(Accession.class);
Querydsl querydsl = new Querydsl(em, builder);
JPQLQuery<Long> query = querydsl.createQuery(QAccession.accession)
// select id only
.select(QAccession.accession.id)
// order by id
.orderBy(QAccession.accession.id.asc());
// select id only
.select(QAccession.accession.id)
// order by id
.orderBy(QAccession.accession.id.asc());
// apply filter
query.where(predicate);
int startPosition = 0;
query.offset(startPosition);
query.limit(batchSize);
StopWatch stopWatch = new StopWatch();
stopWatch.start();
......@@ -92,21 +90,36 @@ public class AccessionProcessor {
List<Long> results;
do {
query.offset(startPosition);
// Respect maxSize
if (maxSize != null && startPosition + batchSize > maxSize) {
// we would be over allowed number of records
query.limit(maxSize - startPosition);
} else {
query.limit(batchSize);
}
stopWatch.split();
LOG.debug("Reading Accessions. Stopwatch={}s {}+{} of {}. Processing at {} accessions/s", stopWatch.getSplitTime() / 1000, startPosition, batchSize, count, (double)(startPosition+batchSize)/(stopWatch.getSplitTime() / 1000));
results = query.fetch();
loadAndProcess(results, action);
// Next page
query.offset(startPosition += results.size());
// Start position is updated above.
startPosition += results.size();
// Clear anything cached in the entity manager
em.clear();
} while (results.size() > 0);
} while (results.size() > 0 && (maxSize == null || startPosition < maxSize));
stopWatch.stop();
LOG.info("Processing Accessions for filter {} took {}ms", filter, stopWatch.getTime());
}
@Transactional(readOnly = true, propagation = Propagation.REQUIRES_NEW)
public void process(AccessionFilter filter, IAccessionAction action) throws Exception {
process(filter, action, null);
}
private void loadAndProcess(List<Long> accessionIds, IAccessionAction action) throws Exception {
List<Accession> accessions = accessionRepository.findAll(accessionIds);
......
......@@ -34,6 +34,7 @@ import org.genesys2.server.api.v1.AccessionUploadController;
import org.genesys2.server.model.genesys.*;
import org.genesys2.server.model.genesys.AccessionAlias.AliasType;
import org.genesys2.server.model.impl.FaoInstitute;
import org.genesys2.server.persistence.AccessionGeoRepository;
import org.genesys2.server.persistence.AccessionIdRepository;
import org.genesys2.server.persistence.AccessionRepository;
import org.genesys2.server.persistence.FaoInstituteRepository;
......@@ -81,6 +82,8 @@ public class AccessionControllerTest extends AbstractApiTest {
@Autowired
private AccessionIdRepository accessionIdRepository;
@Autowired
private AccessionGeoRepository accessionGeoRepository;
@Autowired
private FaoInstituteRepository instituteRepository;
@Autowired
private InstituteService instituteService;
......@@ -111,6 +114,7 @@ public class AccessionControllerTest extends AbstractApiTest {
public void cleanup() throws Exception {
accessionRepository.deleteAll();
accessionIdRepository.deleteAll();
accessionGeoRepository.deleteAll();
taxonomyRepository.deleteAll();
instituteRepository.deleteAll();
super.cleanup();
......@@ -312,6 +316,50 @@ public class AccessionControllerTest extends AbstractApiTest {
assertThat("breederCode must be an empty array", result.getAccessionId().getBreederCode().size(), is(0));
}
@Test
public void testGeoJson() throws Exception {
final int accAmount = 5;
List<Accession> accessions = setUpAccessions(accAmount);
assertThat(accessionRepository.count(), is((long)accAmount));
ObjectNode filter = objectMapper.createObjectNode();
ObjectNode geo = objectMapper.createObjectNode();
ObjectNode lat = objectMapper.createObjectNode();
lat.put("ge", 74);
lat.put("le", 76);
ObjectNode lng = objectMapper.createObjectNode();
lng.put("ge", 74);
lng.put("le", 76);
geo.set("lat", lat);
geo.set("lng", lng);
filter.set("geo", geo);
mockMvc.perform(post(AccessionController.CONTROLLER_URL + "/geoJson")
.contentType(MediaType.APPLICATION_JSON)
.content(filter.toString()))
.andExpect(status().isOk())
// .andDo(MockMvcResultHandlers.print())
.andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(jsonPath("$.geoJson", is(notNullValue())))
.andExpect(jsonPath("$.geoJson", hasSize(accAmount)))
.andExpect(jsonPath("$.geoJson[0].type", is("Feature")))
.andExpect(jsonPath("$.geoJson[0].id", is(notNullValue())))
.andExpect(jsonPath("$.geoJson[0].geometry", is(notNullValue())))
.andExpect(jsonPath("$.geoJson[0].geometry.coordinates", hasSize(2)))
.andExpect(jsonPath("$.geoJson[0].geometry.coordinates[1]", is(accessions.get(0).getAccessionId().getGeo().getLatitude())))
.andExpect(jsonPath("$.geoJson[0].geometry.coordinates[1]", is(accessions.get(0).getAccessionId().getGeo().getLongitude())))
.andExpect(jsonPath("$.geoJson[0].geometry.type", is("Point")))
.andExpect(jsonPath("$.geoJson[0].properties", is(notNullValue())))
.andExpect(jsonPath("$.geoJson[0].properties.accessionNumber", is(notNullValue())))
.andExpect(jsonPath("$.geoJson[0].properties.instCode", is(notNullValue())))
.andExpect(jsonPath("$.geoJson[0].properties.uuid", is(notNullValue())))
;
}
@Test
public void testAliases() throws Exception {
ObjectNode accessionJson = setUpAccession();
......@@ -414,6 +462,10 @@ public class AccessionControllerTest extends AbstractApiTest {
private Accession addAccessionInDB() {
Accession a = new Accession();
a.setAccessionId(new AccessionId());
AccessionGeo accessionGeo = new AccessionGeo();
accessionGeo.setLongitude(75d);
accessionGeo.setLatitude(75d);
a.getAccessionId().setGeo(accessionGeo);
a.setInstitute(institute);
a.setAccessionNumber("ACC" + System.currentTimeMillis() + "-" + acceNumb.incrementAndGet());
Taxonomy2 taxon = new Taxonomy2();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment