Commit 24edd59b authored by Alexander Prendetskiy's avatar Alexander Prendetskiy Committed by Matija Obreza

Accession API v1: Geo info

parent 177d6dc1
......@@ -87,7 +87,7 @@ import io.swagger.annotations.Api;
@Api(tags = { "accession" })
public class AccessionController {
private static final Logger LOG = LoggerFactory.getLogger(AccessionController.class);
private static final Logger LOG = LoggerFactory.getLogger(AccessionController.class);
/** The Constant API_BASE. */
public static final String API_BASE = ApiBaseController.APIv1_BASE + "/acn";
......@@ -115,13 +115,15 @@ public class AccessionController {
@Value("${base.url}")
private String baseUrl;
@Value("${cdn.servers}")
private String[] cdnServers;
private final Set<String> terms = Sets.newHashSet("institute.code", "institute.country.code3", "cropName", "crop.shortName", "taxonomy.genus", "taxonomy.species",
"taxonomy.genusSpecies", "countryOfOrigin.code3", "sampStat", "available", "mlsStatus", "donorCode", "sgsv", "storage", "duplSite", "breederCode");
private ObjectMapper objectMapper = new ObjectMapper();
/**
* Gets the accession
*
......@@ -238,6 +240,21 @@ public class AccessionController {
return accessionDetails;
}
@PostMapping(value = "/geo", produces = MediaType.APPLICATION_JSON_VALUE)
@JsonView({ JsonViews.Public.class })
public GeoInfoJson getGeoInfo(@PathVariable(value = "f", required = false) String filterCode, @RequestBody(required = false) AccessionFilter filter) throws IOException {
if (filterCode != null) {
filter = shortFilterService.filterByCode(filterCode, AccessionFilter.class);
}
GeoInfoJson geoInfo = new GeoInfoJson();
geoInfo.bounds = accessionService.getBounds(filter);
geoInfo.accessionCount = accessionService.countAccessions(filter);
geoInfo.tileServers = cdnServers;
return geoInfo;
}
/**
* Get term overview for filters
*
......@@ -321,9 +338,9 @@ public class AccessionController {
response.setContentType("application/vnd.google-earth.kml+xml");
response.addHeader("Content-Disposition", String.format("attachment; filename=\"genesys-kml-" + filterCode + ".kml\""));
DecimalFormatSymbols dfs=new DecimalFormatSymbols();
DecimalFormatSymbols dfs = new DecimalFormatSymbols();
dfs.setDecimalSeparator('.');
DecimalFormat decimalFormat=new DecimalFormat("0.#", dfs);
DecimalFormat decimalFormat = new DecimalFormat("0.#", dfs);
decimalFormat.setMinimumIntegerDigits(1);
decimalFormat.setMinimumFractionDigits(6);
decimalFormat.setGroupingUsed(false);
......@@ -339,13 +356,13 @@ public class AccessionController {
if (geo != null && geo.getLongitude() != null && geo.getLatitude() != null) {
writer.append("<Placemark>");
writer.append("<name>").append(accession.getAccessionNumber()).append("</name>");
writer.append("<description><![CDATA[\n");
writer.append("<p>").append(accession.getTaxonomy().getTaxonNameHtml()).append("</p>");
writer.append("<p>").append(accession.getInstitute().getCode()).append(" ").append(accession.getInstitute().getFullName()).append("</p>");
writer.append("<p><a href=\"").append(baseUrl).append("/acn/").append(accession.getUuid().toString()).append("\">Passport data</a></p>");
writer.append("\n]]></description>");
writer.append("<Point><coordinates>");
writer.append(decimalFormat.format(geo.getLongitude())).append(",").append(decimalFormat.format(geo.getLatitude()));
writer.append("</coordinates></Point>");
......@@ -357,13 +374,13 @@ public class AccessionController {
writer.write("</Document>\n</kml>\n");
} catch (EOFException e) {
LOG.warn("Download was aborted: {}", e.getMessage());
LOG.warn("Download was aborted: {}", e.getMessage());
} catch (Exception e) {
LOG.warn("Error generating KML: {}", e.getMessage());
LOG.warn("Error generating KML: {}", e.getMessage());
} finally {
writer.flush();
writer.close();
response.flushBuffer();
response.flushBuffer();
}
}
......@@ -374,4 +391,10 @@ public class AccessionController {
public List<Subset> subsets;
}
public static class GeoInfoJson {
public List<Object[]> bounds;
public long accessionCount;
public String[] tileServers;
}
}
......@@ -28,10 +28,11 @@ import org.springframework.data.domain.Pageable;
public interface AccessionService {
/**
* Count accessions. Uses Elasticsearch, but counts from database when number is small enough.
* Count accessions. Uses Elasticsearch, but counts from database when number is
* small enough.
*
* @param filter the filter
* @return the count
* @return the count
*/
long countAccessions(AccessionFilter filter);
......@@ -44,6 +45,14 @@ public interface AccessionService {
*/
Page<Accession> list(AccessionFilter filter, Pageable page);
/**
* Gets the bounds.
*
* @param filter the filter
* @return the bounds
*/
List<Object[]> getBounds(AccessionFilter filter);
/**
* Gets accession by uuid
*
......@@ -62,6 +71,7 @@ public interface AccessionService {
/**
* Converts AccessionIdentifiers to UUID
*
* @param identifiers accession identifiers to lookup in DB
* @return map with UUIDs and related AccessionIdentifiers
*/
......@@ -70,7 +80,7 @@ public interface AccessionService {
/**
* Loads {@link Accession} by IDs and executes the action on each accession in a
* Spring transaction. Spring security context not supported.
*
*
* @param accessionIds List of accession IDs
* @param action the action to execute on each accession
* @return the list of processed accessions
......@@ -80,7 +90,7 @@ public interface AccessionService {
public static interface IAccessionAction {
/**
* Run action on Accession
*
*
* @param a the accession
* @return must return the resulting {@link Accession}
*/
......
......@@ -15,15 +15,19 @@
*/
package org.genesys2.server.service.impl;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import javax.persistence.EntityManager;
import org.genesys2.server.model.genesys.Accession;
import org.genesys2.server.model.genesys.AccessionData;
import org.genesys2.server.model.genesys.AccessionId;
import org.genesys2.server.model.genesys.QAccession;
import org.genesys2.server.model.impl.AccessionIdentifier3;
import org.genesys2.server.persistence.AccessionRepository;
import org.genesys2.server.service.AccessionService;
......@@ -37,10 +41,16 @@ import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.support.Querydsl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.querydsl.core.Tuple;
import com.querydsl.core.types.dsl.PathBuilder;
import com.querydsl.core.types.dsl.PathBuilderFactory;
import com.querydsl.jpa.JPQLQuery;
/**
* Accession services.
*/
......@@ -56,10 +66,14 @@ public class AccessionServiceImpl implements AccessionService {
@Autowired
private ElasticsearchService elasticsearchService;
@Autowired
private AccessionCounter accessionCounter;
@Autowired
private EntityManager entityManager;
private PathBuilder<Accession> accessionPathBuilder = new PathBuilderFactory().create(Accession.class);
private <T extends AccessionData> T lazyLoad(T accession) {
if (accession != null) {
......@@ -116,12 +130,9 @@ public class AccessionServiceImpl implements AccessionService {
Map<UUID, AccessionIdentifier3> res = new HashMap<>();
List<Accession> foundAccessions = accessionRepository.findById(identifiers);
for(Accession accession: foundAccessions) {
Optional<? extends AccessionIdentifier3> toPut = identifiers.stream()
.filter(id -> id.getAccessionNumber().equals(accession.getAccessionNumber())
&& id.getGenus().equals(accession.getGenus())
&& id.getHoldingInstitute().equals(accession.getInstCode())
).findFirst();
for (Accession accession : foundAccessions) {
Optional<? extends AccessionIdentifier3> toPut = identifiers.stream().filter(id -> id.getAccessionNumber().equals(accession.getAccessionNumber()) && id.getGenus()
.equals(accession.getGenus()) && id.getHoldingInstitute().equals(accession.getInstCode())).findFirst();
toPut.ifPresent(accessionIdentifier3 -> res.put(accession.getUuid(), accessionIdentifier3));
}
......@@ -137,7 +148,7 @@ public class AccessionServiceImpl implements AccessionService {
// If total is below 10K, use actual count
total = accessionRepository.count(filter.buildQuery());
}
return total;
}
......@@ -151,15 +162,32 @@ public class AccessionServiceImpl implements AccessionService {
@Cacheable(value = "apiResponses.accessionApi1.list", unless = "#result == null", keyGenerator = "shortFilterKeyGenerator")
public Page<Accession> list(AccessionFilter filter, Pageable page) {
List<Accession> content = accessionRepository.findAll(filter, page);
long total = elasticsearchService.count(Accession.class, filter);
if (total < 10000) {
// If total is below 10K, use actual count
total = accessionRepository.count(filter.buildQuery());
}
long total = countAccessions(filter);
return new PageImpl<>(content, page, total);
}
@Override
public List<Object[]> getBounds(AccessionFilter filter) {
QAccession accession = QAccession.accession;
Querydsl querydsl = new Querydsl(entityManager, accessionPathBuilder);
JPQLQuery<Tuple> query = querydsl.createQuery(accession).select(accession.accessionId.geo.latitude.min(), accession.accessionId.geo.longitude.max(),
accession.accessionId.geo.latitude.max(), accession.accessionId.geo.longitude.min()).from(accession).where(filter.buildQuery());
Object[] results = query.fetchOne().toArray();
List<Object[]> latLngBounds = new ArrayList<>();
// corner1
latLngBounds.add(new Object[] { results[0], results[1] });
// corner2
latLngBounds.add(new Object[] { results[2], results[3] });
return latLngBounds;
}
@Override
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public List<Accession> processAccessions(List<Long> accessionIds, IAccessionAction action) {
......
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