Commit c054dac5 authored by Matija Obreza's avatar Matija Obreza

MCPD XLSX

parent c117b8ce
...@@ -522,7 +522,12 @@ ...@@ -522,7 +522,12 @@
<artifactId>transifex-client</artifactId> <artifactId>transifex-client</artifactId>
<version>0.2-SNAPSHOT</version> <version>0.2-SNAPSHOT</version>
</dependency> </dependency>
</dependencies> <dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.10.1</version>
</dependency>
</dependencies>
<build> <build>
<plugins> <plugins>
......
...@@ -20,6 +20,7 @@ import org.genesys2.server.model.genesys.Method; ...@@ -20,6 +20,7 @@ import org.genesys2.server.model.genesys.Method;
import org.genesys2.server.model.impl.Country; import org.genesys2.server.model.impl.Country;
import org.genesys2.server.model.impl.FaoInstitute; import org.genesys2.server.model.impl.FaoInstitute;
import org.genesys2.server.service.impl.FilterHandler.AppliedFilters; import org.genesys2.server.service.impl.FilterHandler.AppliedFilters;
import org.springframework.data.domain.Sort;
import org.springframework.jdbc.core.RowCallbackHandler; import org.springframework.jdbc.core.RowCallbackHandler;
public interface GenesysLowlevelRepository { public interface GenesysLowlevelRepository {
...@@ -53,4 +54,6 @@ public interface GenesysLowlevelRepository { ...@@ -53,4 +54,6 @@ public interface GenesysLowlevelRepository {
int countAccessions(AppliedFilters filter); int countAccessions(AppliedFilters filter);
void listAccessionIds(AppliedFilters filter, Sort sort, RowCallbackHandler rowCallbackHandler);
} }
...@@ -32,6 +32,7 @@ import org.genesys2.server.service.impl.DirectMysqlQuery; ...@@ -32,6 +32,7 @@ import org.genesys2.server.service.impl.DirectMysqlQuery;
import org.genesys2.server.service.impl.DirectMysqlQuery.MethodResolver; import org.genesys2.server.service.impl.DirectMysqlQuery.MethodResolver;
import org.genesys2.server.service.impl.FilterHandler.AppliedFilters; import org.genesys2.server.service.impl.FilterHandler.AppliedFilters;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort;
import org.springframework.jdbc.BadSqlGrammarException; import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.jdbc.core.ArgumentPreparedStatementSetter; import org.springframework.jdbc.core.ArgumentPreparedStatementSetter;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
...@@ -255,6 +256,34 @@ public class GenesysLowlevelRepositoryImpl implements GenesysLowlevelRepository ...@@ -255,6 +256,34 @@ public class GenesysLowlevelRepositoryImpl implements GenesysLowlevelRepository
} }
}, rowCallbackHandler); }, rowCallbackHandler);
} }
@Override
public void listAccessionIds(final AppliedFilters filter, final Sort sort, final RowCallbackHandler rowCallbackHandler) {
final DirectMysqlQuery directQuery = new DirectMysqlQuery("accession", "a");
directQuery.jsonFilter(filter, new MethodResolver() {
@Override
public Method getMethod(final long methodId) {
return GenesysLowlevelRepositoryImpl.this.methodRepository.findOne(methodId);
}
});
directQuery.sort(sort);
this.jdbcTemplate.query(new PreparedStatementCreator() {
@Override
public PreparedStatement createPreparedStatement(final Connection con) throws SQLException {
final PreparedStatement stmt = con.prepareStatement(directQuery
.getQuery("a.id"));
final ArgumentPreparedStatementSetter apss = new ArgumentPreparedStatementSetter(directQuery.getParameters());
apss.setValues(stmt);
// Set mysql JConnector to stream results
// stmt.setFetchSize(Integer.MIN_VALUE);
return stmt;
}
}, rowCallbackHandler);
}
@Override @Override
public void listAccessionsGeo(final AppliedFilters filter, final RowCallbackHandler rowCallbackHandler) { public void listAccessionsGeo(final AppliedFilters filter, final RowCallbackHandler rowCallbackHandler) {
......
/**
* 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;
import java.io.IOException;
import java.io.OutputStream;
import org.genesys2.server.service.impl.FilterHandler.AppliedFilters;
/**
* Defines available downloads
*
* @author matijaobreza
*
*/
public interface DownloadService {
void writeXlsxMCPD(AppliedFilters filters, OutputStream outputStream) throws IOException;
}
...@@ -37,6 +37,7 @@ import org.genesys2.server.service.impl.FilterHandler.MinValueFilter; ...@@ -37,6 +37,7 @@ import org.genesys2.server.service.impl.FilterHandler.MinValueFilter;
import org.genesys2.server.service.impl.FilterHandler.StartsWithFilter; import org.genesys2.server.service.impl.FilterHandler.StartsWithFilter;
import org.genesys2.server.service.impl.FilterHandler.ValueRangeFilter; import org.genesys2.server.service.impl.FilterHandler.ValueRangeFilter;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.domain.Sort.Order; import org.springframework.data.domain.Sort.Order;
public class DirectMysqlQuery { public class DirectMysqlQuery {
...@@ -85,7 +86,9 @@ public class DirectMysqlQuery { ...@@ -85,7 +86,9 @@ public class DirectMysqlQuery {
if (StringUtils.isNotBlank(alias)) { if (StringUtils.isNotBlank(alias)) {
sb.append(alias).append(StringUtils.SPACE); sb.append(alias).append(StringUtils.SPACE);
} }
sb.append("on ").append(onExpr).append(StringUtils.SPACE); if (StringUtils.isNotBlank(onExpr)) {
sb.append("on ").append(onExpr).append(StringUtils.SPACE);
}
return this; return this;
} }
...@@ -397,6 +400,30 @@ public class DirectMysqlQuery { ...@@ -397,6 +400,30 @@ public class DirectMysqlQuery {
return params.toArray(); return params.toArray();
} }
public DirectMysqlQuery sort(Sort sort) {
if (sortBuffer.length() != 0) {
throw new RuntimeException("sortBuffer is not blank, invalid use of #pageable(Pageable)");
}
sortBuffer.append("\n order by ");
for (final Order o : sort) {
if (LOG.isDebugEnabled()) {
LOG.debug("Order: " + o);
}
// ClassMetadata md =
// sessionFactory.getClassMetadata(Accession.class);
// md.
// EntityType<Accession> x =
// entityManager.getMetamodel().entity(Accession.class);
// System.err.println(x.getAttribute(o.getProperty()).getName());
// sb.append(x.getAttribute(o.getProperty()).getName());
sortBuffer.append("a.").append(o.getProperty());
sortBuffer.append(" ").append(o.getDirection());
}
return this;
}
public DirectMysqlQuery pageable(Pageable pageable) { public DirectMysqlQuery pageable(Pageable pageable) {
if (sortBuffer.length() != 0) { if (sortBuffer.length() != 0) {
throw new RuntimeException("sortBuffer is not blank, invalid use of #pageable(Pageable)"); throw new RuntimeException("sortBuffer is not blank, invalid use of #pageable(Pageable)");
...@@ -407,21 +434,7 @@ public class DirectMysqlQuery { ...@@ -407,21 +434,7 @@ public class DirectMysqlQuery {
} }
if (pageable.getSort() != null) { if (pageable.getSort() != null) {
sortBuffer.append("\n order by "); sort(pageable.getSort());
for (final Order o : pageable.getSort()) {
if (LOG.isDebugEnabled()) {
LOG.debug("Order: " + o);
}
// ClassMetadata md =
// sessionFactory.getClassMetadata(Accession.class);
// md.
// EntityType<Accession> x =
// entityManager.getMetamodel().entity(Accession.class);
// System.err.println(x.getAttribute(o.getProperty()).getName());
// sb.append(x.getAttribute(o.getProperty()).getName());
sortBuffer.append("a.").append(o.getProperty());
sortBuffer.append(" ").append(o.getDirection());
}
} }
sortBuffer.append(" limit "); sortBuffer.append(" limit ");
if (LOG.isDebugEnabled()) { if (LOG.isDebugEnabled()) {
......
...@@ -38,6 +38,7 @@ import org.genesys2.server.model.genesys.Parameter; ...@@ -38,6 +38,7 @@ import org.genesys2.server.model.genesys.Parameter;
import org.genesys2.server.model.genesys.ParameterCategory; import org.genesys2.server.model.genesys.ParameterCategory;
import org.genesys2.server.model.impl.Crop; import org.genesys2.server.model.impl.Crop;
import org.genesys2.server.service.CropService; import org.genesys2.server.service.CropService;
import org.genesys2.server.service.DownloadService;
import org.genesys2.server.service.ElasticService; import org.genesys2.server.service.ElasticService;
import org.genesys2.server.service.FilterConstants; import org.genesys2.server.service.FilterConstants;
import org.genesys2.server.service.GenesysFilterService; import org.genesys2.server.service.GenesysFilterService;
...@@ -57,6 +58,7 @@ import org.springframework.data.domain.Page; ...@@ -57,6 +58,7 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap; import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
...@@ -71,9 +73,11 @@ import com.jhlabs.image.MapColorsFilter; ...@@ -71,9 +73,11 @@ import com.jhlabs.image.MapColorsFilter;
@Controller @Controller
public class ExplorerController extends BaseController { public class ExplorerController extends BaseController {
private static final int DOWNLOAD_LIMIT = 100000;
@Autowired @Autowired
private GenesysFilterService filterService; private GenesysFilterService filterService;
@Autowired @Autowired
private ElasticService elasticService; private ElasticService elasticService;
...@@ -98,6 +102,9 @@ public class ExplorerController extends BaseController { ...@@ -98,6 +102,9 @@ public class ExplorerController extends BaseController {
@Autowired @Autowired
private FilterHandler filterHandler; private FilterHandler filterHandler;
@Autowired
private DownloadService downloadService;
private final ObjectMapper mapper = new ObjectMapper(); private final ObjectMapper mapper = new ObjectMapper();
/** /**
...@@ -161,11 +168,9 @@ public class ExplorerController extends BaseController { ...@@ -161,11 +168,9 @@ public class ExplorerController extends BaseController {
} }
model.addAttribute("crop", crop); model.addAttribute("crop", crop);
// JSP works with JsonObject // JSP works with JsonObject
final Map<?, ?> filters = mapper.readValue(appliedFilters.toString(), Map.class); final Map<?, ?> filters = mapper.readValue(appliedFilters.toString(), Map.class);
model.addAttribute("filters", filters); model.addAttribute("filters", filters);
selectedFilters = appliedFilters.getFilterNames(); selectedFilters = appliedFilters.getFilterNames();
final List<GenesysFilter> currentFilters = filterHandler.selectFilters(selectedFilters); final List<GenesysFilter> currentFilters = filterHandler.selectFilters(selectedFilters);
...@@ -187,7 +192,6 @@ public class ExplorerController extends BaseController { ...@@ -187,7 +192,6 @@ public class ExplorerController extends BaseController {
return "/accession/explore"; return "/accession/explore";
} }
/** /**
* Browse all using Elasticsearch * Browse all using Elasticsearch
* *
...@@ -195,7 +199,7 @@ public class ExplorerController extends BaseController { ...@@ -195,7 +199,7 @@ public class ExplorerController extends BaseController {
* @param page * @param page
* @return * @return
* @throws IOException * @throws IOException
* @throws SearchException * @throws SearchException
*/ */
@RequestMapping("/explore-es") @RequestMapping("/explore-es")
public String viewElasticFiltered(ModelMap model, @RequestParam(value = "page", required = false, defaultValue = "1") int page, public String viewElasticFiltered(ModelMap model, @RequestParam(value = "page", required = false, defaultValue = "1") int page,
...@@ -221,11 +225,9 @@ public class ExplorerController extends BaseController { ...@@ -221,11 +225,9 @@ public class ExplorerController extends BaseController {
} }
model.addAttribute("crop", crop); model.addAttribute("crop", crop);
// JSP works with JsonObject // TODO Handle -filter.key!!
// JSP works with JsonObject // TODO Handle -filter.key!!
final Map<?, ?> filters = mapper.readValue(appliedFilters.toString(), Map.class); final Map<?, ?> filters = mapper.readValue(appliedFilters.toString(), Map.class);
model.addAttribute("filters", filters); model.addAttribute("filters", filters);
selectedFilters = appliedFilters.getFilterNames(); selectedFilters = appliedFilters.getFilterNames();
final List<GenesysFilter> currentFilters = filterHandler.selectFilters(selectedFilters); final List<GenesysFilter> currentFilters = filterHandler.selectFilters(selectedFilters);
...@@ -247,7 +249,6 @@ public class ExplorerController extends BaseController { ...@@ -247,7 +249,6 @@ public class ExplorerController extends BaseController {
return "/accession/explore-es"; return "/accession/explore-es";
} }
@RequestMapping(value = "/additional-filter", method = RequestMethod.GET) @RequestMapping(value = "/additional-filter", method = RequestMethod.GET)
public String getAdditionalFilters(ModelMap model, @RequestParam(value = "filter", required = true, defaultValue = "") String[] selectedFilters) public String getAdditionalFilters(ModelMap model, @RequestParam(value = "filter", required = true, defaultValue = "") String[] selectedFilters)
throws IOException { throws IOException {
...@@ -332,6 +333,29 @@ public class ExplorerController extends BaseController { ...@@ -332,6 +333,29 @@ public class ExplorerController extends BaseController {
response.flushBuffer(); response.flushBuffer();
} }
@PreAuthorize("isAuthenticated()")
@RequestMapping(value = "/explore/download/mcpd", method = RequestMethod.POST)
public void downloadXlsxMCPD(ModelMap model, @RequestParam(value = "filter", required = false, defaultValue = "{}") String jsonFilter,
HttpServletResponse response) throws IOException {
final AppliedFilters appliedFilters = updateFilterWithCrop(null, jsonFilter);
final int countFiltered = genesysService.countAccessions(appliedFilters);
_logger.info("Attempting to download XLSX MCPD for " + countFiltered + " accessions");
if (countFiltered > DOWNLOAD_LIMIT) {
throw new RuntimeException("Refusing to export more than " + DOWNLOAD_LIMIT + " entries");
}
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.addHeader("Content-Disposition", String.format("attachment; filename=\"genesys-accessions-filtered.xlsx\""));
// Write Darwin Core Archive to the stream.
final OutputStream outputStream = response.getOutputStream();
downloadService.writeXlsxMCPD(appliedFilters, outputStream);
response.flushBuffer();
}
private AppliedFilters updateFilterWithCrop(String cropName, String jsonFilter) throws IOException { private AppliedFilters updateFilterWithCrop(String cropName, String jsonFilter) throws IOException {
AppliedFilters appliedFilters = mapper.readValue(jsonFilter, AppliedFilters.class); AppliedFilters appliedFilters = mapper.readValue(jsonFilter, AppliedFilters.class);
...@@ -385,11 +409,10 @@ public class ExplorerController extends BaseController { ...@@ -385,11 +409,10 @@ public class ExplorerController extends BaseController {
public void tile(@PathVariable("zoom") int zoom, @PathVariable("x") int x, @PathVariable("y") int y, public void tile(@PathVariable("zoom") int zoom, @PathVariable("x") int x, @PathVariable("y") int y,
@RequestParam(value = "filter", required = true) String jsonFilter, @RequestParam(value = "color", required = false) String color, @RequestParam(value = "filter", required = true) String jsonFilter, @RequestParam(value = "color", required = false) String color,
HttpServletResponse response) { HttpServletResponse response) {
try { try {
AppliedFilters appliedFilters = mapper.readValue(jsonFilter, AppliedFilters.class); AppliedFilters appliedFilters = mapper.readValue(jsonFilter, AppliedFilters.class);
byte[] image = mappingService.getTile(appliedFilters, zoom, x, y); byte[] image = mappingService.getTile(appliedFilters, zoom, x, y);
image = changeColor(color, image); image = changeColor(color, image);
response.getOutputStream().write(image, 0, image.length); response.getOutputStream().write(image, 0, image.length);
...@@ -444,7 +467,8 @@ public class ExplorerController extends BaseController { ...@@ -444,7 +467,8 @@ public class ExplorerController extends BaseController {
} }
@RequestMapping(value = "/explore/overview") @RequestMapping(value = "/explore/overview")
public String overview(ModelMap model, @RequestParam(value = "filter", required = false, defaultValue = "{}") String jsonFilter) throws IOException, SearchException { public String overview(ModelMap model, @RequestParam(value = "filter", required = false, defaultValue = "{}") String jsonFilter) throws IOException,
SearchException {
AppliedFilters appliedFilters = mapper.readValue(jsonFilter, AppliedFilters.class); AppliedFilters appliedFilters = mapper.readValue(jsonFilter, AppliedFilters.class);
String[] selectedFilters = appliedFilters.getFilterNames(); String[] selectedFilters = appliedFilters.getFilterNames();
......
...@@ -26,6 +26,7 @@ import javax.servlet.http.HttpServletResponse; ...@@ -26,6 +26,7 @@ import javax.servlet.http.HttpServletResponse;
import org.genesys2.server.model.genesys.Accession; import org.genesys2.server.model.genesys.Accession;
import org.genesys2.server.model.genesys.AccessionGeo; import org.genesys2.server.model.genesys.AccessionGeo;
import org.genesys2.server.service.DownloadService;
import org.genesys2.server.service.FilterConstants; import org.genesys2.server.service.FilterConstants;
import org.genesys2.server.service.GenesysService; import org.genesys2.server.service.GenesysService;
import org.genesys2.server.service.impl.FilterHandler; import org.genesys2.server.service.impl.FilterHandler;
...@@ -45,21 +46,20 @@ import org.springframework.web.bind.annotation.RequestMethod; ...@@ -45,21 +46,20 @@ import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseBody;
import com.fasterxml.jackson.databind.ObjectMapper;
@Controller @Controller
@Scope("request") @Scope("request")
@RequestMapping("/sel") @RequestMapping("/sel")
public class SelectionController extends BaseController { public class SelectionController extends BaseController {
private final ObjectMapper mapper = new ObjectMapper();
@Autowired @Autowired
private SelectionBean selectionBean; private SelectionBean selectionBean;
@Autowired @Autowired
private GenesysService genesysService; private GenesysService genesysService;
@Autowired
private DownloadService downloadService;
@RequestMapping("/") @RequestMapping("/")
public String view(ModelMap model, @RequestParam(value = "page", required = false, defaultValue = "1") int page) { public String view(ModelMap model, @RequestParam(value = "page", required = false, defaultValue = "1") int page) {
...@@ -151,6 +151,29 @@ public class SelectionController extends BaseController { ...@@ -151,6 +151,29 @@ public class SelectionController extends BaseController {
response.flushBuffer(); response.flushBuffer();
} }
@RequestMapping(value = "/download/mcpd", method = RequestMethod.POST)
public void downloadXlsxMCPD(ModelMap model, HttpServletResponse response) throws IOException {
// Create JSON filter
final AppliedFilters appliedFilters = new AppliedFilters();
AppliedFilter arr = new FilterHandler.AppliedFilter().setFilterName(FilterConstants.ID);
for (final long id : selectionBean.copy()) {
arr.addFilterValue(new FilterHandler.LiteralValueFilter(id));
}
appliedFilters.add(arr);
final int countFiltered = genesysService.countAccessions(appliedFilters);
_logger.info("Attempting to download XLSX MCPD for " + countFiltered + " accessions");
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.addHeader("Content-Disposition", String.format("attachment; filename=\"genesys-accessions-selected.xlsx\""));
// Write Darwin Core Archive to the stream.
final OutputStream outputStream = response.getOutputStream();
downloadService.writeXlsxMCPD(appliedFilters, outputStream);
response.flushBuffer();
}
// TODO REMOVE // TODO REMOVE
@RequestMapping(value = "/json/count", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE }) @RequestMapping(value = "/json/count", method = RequestMethod.GET, produces = { MediaType.APPLICATION_JSON_VALUE })
@ResponseBody @ResponseBody
......
...@@ -358,6 +358,7 @@ filter.available=Available for distribution ...@@ -358,6 +358,7 @@ filter.available=Available for distribution
filter.donorCode=Donor institute filter.donorCode=Donor institute
filter.duplSite=Site of safety duplication filter.duplSite=Site of safety duplication
filter.download-dwca=Download ZIP filter.download-dwca=Download ZIP
filter.download-mcpd=Download MCPD
filter.add=Add filter filter.add=Add filter
filter.additional=Additional filters filter.additional=Additional filters
filter.apply=Apply filter.apply=Apply
......
...@@ -37,6 +37,13 @@ ...@@ -37,6 +37,13 @@
<button class="btn btn-default" type="submit"><spring:message code="filter.download-dwca" /></button> <button class="btn btn-default" type="submit"><spring:message code="filter.download-dwca" /></button>
</form> </form>
</c:if> </c:if>
<security:authorize access="isAuthenticated()">
<form style="display: inline-block" method="post" action="<c:url value="/explore/download/mcpd" />">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
<input type="hidden" name="filter" value="<c:out value="${jsonFilter}" />" />
<button class="btn btn-default" type="submit"><spring:message code="filter.download-mcpd" /></button>
</form>
</security:authorize>
<a class="btn btn-default" href="<c:url value="/explore/overview"><c:param name="filter">${jsonFilter}</c:param></c:url>"><span class="glyphicon glyphicon-eye-open"></span><span style="margin-left: 0.5em;"><spring:message code="data-overview.short" /></span></a> <a class="btn btn-default" href="<c:url value="/explore/overview"><c:param name="filter">${jsonFilter}</c:param></c:url>"><span class="glyphicon glyphicon-eye-open"></span><span style="margin-left: 0.5em;"><spring:message code="data-overview.short" /></span></a>
<a class="btn btn-default" href="<c:url value="/explore/map"><c:param name="filter">${jsonFilter}</c:param></c:url>"><span class="glyphicon glyphicon-globe"></span><span style="margin-left: 0.5em;"><spring:message code="maps.view-map" /></span></a> <a class="btn btn-default" href="<c:url value="/explore/map"><c:param name="filter">${jsonFilter}</c:param></c:url>"><span class="glyphicon glyphicon-globe"></span><span style="margin-left: 0.5em;"><spring:message code="maps.view-map" /></span></a>
</div> </div>
......
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