Commit b440b739 authored by Matija Obreza's avatar Matija Obreza

Merge branch '373-accession-v1-api' into 'master'

Resolve "Accession v1 API"

Closes #373

See merge request genesys-pgr/genesys-server!288
parents 473f89b2 3cfdd633
......@@ -79,14 +79,14 @@ import io.swagger.annotations.Api;
*/
@RestController("accessionApi1")
@PreAuthorize("isAuthenticated()")
@RequestMapping(AccessionController.API_BASE)
@RequestMapping(AccessionController.CONTROLLER_URL)
@Api(tags = { "accession" })
public class AccessionController {
private static final Logger LOG = LoggerFactory.getLogger(AccessionController.class);
/** The Constant API_BASE. */
public static final String API_BASE = ApiBaseController.APIv1_BASE + "/acn";
/** The Constant CONTROLLER_URL. */
public static final String CONTROLLER_URL = ApiBaseController.APIv1_BASE + "/acn";
private static final int DOWNLOAD_LIMIT = 200000;
......@@ -121,9 +121,9 @@ public class AccessionController {
* @param uuid the uuid
* @return the subset
*/
@GetMapping(value = "/{UUID:\\w{8}\\-\\w{4}.+}", produces = { MediaType.APPLICATION_JSON_VALUE })
@GetMapping(value = "/{uuid:\\w{8}\\-\\w{4}.+}", produces = { MediaType.APPLICATION_JSON_VALUE })
@JsonView({ JsonViews.Protected.class })
public Accession getByUuid(@PathVariable("UUID") final UUID uuid) {
public Accession getByUuid(@PathVariable("uuid") final UUID uuid) {
return accessionService.getByUuid(uuid);
}
......@@ -215,9 +215,9 @@ public class AccessionController {
return accessionService.getAccessionDetails(accession);
}
@GetMapping(value = "/details/{UUID:\\w{8}\\-\\w{4}.+}", produces = MediaType.APPLICATION_JSON_VALUE)
@GetMapping(value = "/details/{uuid:\\w{8}\\-\\w{4}.+}", produces = MediaType.APPLICATION_JSON_VALUE)
@JsonView(JsonViews.Root.class)
public AccessionService.AccessionDetails getAccessionDetailsByUUID(@PathVariable("UUID") final UUID uuid) {
public AccessionService.AccessionDetails getAccessionDetailsByUUID(@PathVariable("uuid") final UUID uuid) {
Accession accession = accessionService.getByUuid(uuid);
return accessionService.getAccessionDetails(accession);
}
......
/*
* Copyright 2018 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.v1;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.PersistenceException;
import javax.persistence.RollbackException;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.genesys2.server.api.ApiBaseController;
import org.genesys2.server.api.PleaseRetryException;
import org.genesys2.server.api.model.AccessionHeaderJson;
import org.genesys2.server.exception.InvalidApiUsageException;
import org.genesys2.server.model.impl.FaoInstitute;
import org.genesys2.server.service.InstituteService;
import org.genesys2.server.service.impl.RESTApiException;
import org.genesys2.server.service.worker.AccessionOpResponse;
import org.genesys2.server.service.worker.AccessionOpResponse.UpsertResult;
import org.genesys2.server.service.worker.AccessionUploader;
import org.genesys2.spring.ResourceNotFoundException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.TransactionException;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import io.swagger.annotations.Api;
/**
* Accession API v1: the uploader.
*/
@RestController("accessionUploadApi1")
@PreAuthorize("isAuthenticated()")
@RequestMapping(AccessionUploadController.CONTROLLER_URL)
@Api(tags = { "accession" })
public class AccessionUploadController {
/** The Constant LOG. */
private static final Logger LOG = LoggerFactory.getLogger(AccessionUploadController.class);
/** The Constant CONTROLLER_URL. */
public static final String CONTROLLER_URL = ApiBaseController.APIv1_BASE + "/acn";
/** The Constant UPLOAD_RETRIES. */
private static final int UPLOAD_RETRIES = 10;
/** The uploader. */
@Autowired
private AccessionUploader uploader;
/** The institute service. */
@Autowired
InstituteService instituteService;
/**
* Update accessions in the system.
*
* @param instCode the WIEWS institute code
* @param updates the updates
* @return the list
* @throws Exception the exception
*/
@PreAuthorize("isAuthenticated()")
@RequestMapping(value = "/{instCode}/upsert", method = { RequestMethod.POST }, produces = { MediaType.APPLICATION_JSON_VALUE })
public List<AccessionOpResponse> upsertInstituteAccession(@PathVariable("instCode") String instCode, @RequestBody ArrayNode updates) throws Exception {
StopWatch stopWatch = StopWatch.createStarted();
LOG.trace("Received:\n {}", updates);
// User's permission to WRITE to this WIEWS institute are checked in
// BatchRESTService.
final FaoInstitute institute = instituteService.getInstitute(instCode);
if (institute == null) {
throw new ResourceNotFoundException();
}
for (int tryCount = 0; tryCount < UPLOAD_RETRIES; tryCount++) {
try {
List<AccessionOpResponse> res = uploader.upsertAccessions(institute, updates);
LOG.info("Processed {} accessions for {} in {} tries in {}ms", updates.size(), instCode, tryCount + 1, stopWatch.getTime());
return res;
} catch (DataAccessException | TransactionException | PersistenceException e) {
List<AccessionOpResponse> res = upsert1By1(institute, updates);
LOG.info("Processed {} accessions for {} 1by1 after {} tries in {}ms because of {}", updates.size(), instCode, tryCount + 1, stopWatch.getTime(), e.getMessage());
return res;
} catch (PleaseRetryException e) {
LOG.error("Retry {} of {} tries due to: {}", tryCount, UPLOAD_RETRIES, e.getMessage());
// Wait a bit
Thread.sleep((long) (RandomUtils.nextDouble(10, 100) * tryCount));
}
}
throw new InvalidApiUsageException("Just couldn't do it.");
}
/**
* Upsert 1 by 1.
*
* @param institute the institute
* @param updates the updates
* @return the list
* @throws Exception the exception
*/
private List<AccessionOpResponse> upsert1By1(FaoInstitute institute, ArrayNode updates) throws Exception {
List<AccessionOpResponse> response = new ArrayList<>();
ArrayNode single = new ObjectMapper().createArrayNode();
for (JsonNode update : updates) {
single.removeAll();
single.add(update);
Throwable lastException = null;
for (int tryCount = 0; tryCount < UPLOAD_RETRIES; tryCount++) {
try {
response.addAll(uploader.upsertAccessions(institute, single));
lastException = null;
break;
} catch (TransactionException | RollbackException | CannotAcquireLockException | DataIntegrityViolationException | PleaseRetryException e) {
lastException = e;
if (tryCount > 1) {
LOG.info("Retry {} of {} tries due to: {}", tryCount, UPLOAD_RETRIES, e.getMessage());
} else {
LOG.debug("Retrying {} of {} tries due to: {}", tryCount, UPLOAD_RETRIES, e.getMessage());
}
// Wait a bit
Thread.sleep((long) (RandomUtils.nextDouble(10, 100) * tryCount));
}
}
if (lastException != null) {
LOG.warn("Upsert failed due to: {} data={}", lastException.getMessage(), update, lastException);
// record error
response.add(new AccessionOpResponse(update.get("instituteCode").asText(), update.get("accessionNumber").asText(), update.get("taxonomy").get("genus").asText())
.setResult(new UpsertResult(UpsertResult.Type.ERROR)).setError(getDetailedErrorMessage(lastException)));
}
}
return response;
}
/**
* Delete accessions by instituteCode, acceNumb and genus.
*
* @param instCode the inst code
* @param batch the batch
* @return the list
* @throws RESTApiException the REST api exception
*/
@PreAuthorize("isAuthenticated()")
@RequestMapping(value = "/{instCode}/delete", method = { RequestMethod.POST }, consumes = { MediaType.APPLICATION_JSON_VALUE }, produces = {
MediaType.APPLICATION_JSON_VALUE })
public @ResponseBody List<AccessionOpResponse> deleteAccessions(@PathVariable("instCode") String instCode, @RequestBody List<AccessionHeaderJson> batch) throws RESTApiException {
// User's permission to WRITE to this WIEWS institute are checked in
// BatchRESTService.
final FaoInstitute institute = instituteService.getInstitute(instCode);
if (institute == null) {
throw new ResourceNotFoundException();
}
try {
List<AccessionOpResponse> response = null;
try {
response = uploader.deleteAccessions(institute, batch);
LOG.info("Deleted {} accessions from {}", response.size(), instCode);
} catch (DataAccessException | TransactionException | PersistenceException e) {
LOG.info("Retrying delete one by one due to {}", e.getMessage());
response = deleteAccessions1by1(institute, batch);
}
return response;
} catch (CannotAcquireLockException e) {
throw new PleaseRetryException("Operation failed, please retry.", e);
}
}
/**
* Delete accessions 1 by 1.
*
* @param institute the institute
* @param batch the batch
* @return the list
*/
private List<AccessionOpResponse> deleteAccessions1by1(FaoInstitute institute, List<AccessionHeaderJson> batch) {
LOG.info("Attempting delete 1 by 1");
final List<AccessionHeaderJson> batchOfOne = new ArrayList<AccessionHeaderJson>();
List<AccessionOpResponse> response = new ArrayList<AccessionOpResponse>();
for (AccessionHeaderJson acceJ : batch) {
try {
batchOfOne.clear();
batchOfOne.add(acceJ);
AccessionOpResponse accessionResponse = uploader.deleteAccessions(institute, batchOfOne).get(0);
response.add(accessionResponse);
} catch (Throwable e) {
if (LOG.isInfoEnabled()) {
LOG.info("Error deleting {}: {}", acceJ.instCode, e.getMessage());
}
AccessionOpResponse accessionResponse = new AccessionOpResponse(acceJ.instCode, acceJ.acceNumb, acceJ.genus);
accessionResponse.setError(getDetailedErrorMessage(e));
response.add(accessionResponse);
}
}
return response;
}
/**
* Gets the detailed error message.
*
* @param e the exception
* @return the detailed error message
*/
private String getDetailedErrorMessage(Throwable e) {
StringBuffer sb=new StringBuffer(e.getMessage());
Throwable r = e;
while ((r = r.getCause()) !=null) {
sb.append("\n" + r.getMessage());
}
return sb.toString();
}
}
......@@ -80,8 +80,8 @@ public class DescriptorController extends ApiBaseController {
* @param uuid the uuid
* @return the descriptor
*/
@RequestMapping(value = "/{UUID}", method = RequestMethod.GET)
public Descriptor getDescriptor(@PathVariable("UUID") final UUID uuid) {
@RequestMapping(value = "/{uuid}", method = RequestMethod.GET)
public Descriptor getDescriptor(@PathVariable("uuid") final UUID uuid) {
return descriptorService.getDescriptor(uuid);
}
......@@ -92,8 +92,8 @@ public class DescriptorController extends ApiBaseController {
* @param version the version
* @return the descriptor
*/
@DeleteMapping(value = "/{UUID},{version}")
public Descriptor deleteDescriptor(@PathVariable("UUID") final UUID uuid, @PathVariable("version") final int version) {
@DeleteMapping(value = "/{uuid},{version}")
public Descriptor deleteDescriptor(@PathVariable("uuid") final UUID uuid, @PathVariable("version") final int version) {
try {
return descriptorService.removeDescriptor(descriptorService.getDescriptor(uuid, version));
} catch (DataIntegrityViolationException e) {
......@@ -322,10 +322,10 @@ public class DescriptorController extends ApiBaseController {
* @param uuid descriptor UUID
* @return the other descriptor info
*/
@RequestMapping(value = "/extra/{UUID}", method = RequestMethod.GET)
@RequestMapping(value = "/extra/{uuid}", method = RequestMethod.GET)
@SuppressWarnings("unused")
@JsonView(JsonViews.Minimal.class)
public Object getOtherDescriptorInfo(@PathVariable("UUID") final UUID uuid) {
public Object getOtherDescriptorInfo(@PathVariable("uuid") final UUID uuid) {
final Descriptor descriptor = descriptorService.getDescriptor(uuid);
return new Object() {
......
......@@ -85,8 +85,8 @@ public class DescriptorListController {
* @param uuid the uuid
* @return the descriptor list
*/
@GetMapping(value = "/{UUID}")
public DescriptorList getDescriptorList(@PathVariable("UUID") final UUID uuid) {
@GetMapping(value = "/{uuid}")
public DescriptorList getDescriptorList(@PathVariable("uuid") final UUID uuid) {
final DescriptorList descriptorList = descriptorListService.getDescriptorList(uuid);
return descriptorList;
}
......@@ -98,8 +98,8 @@ public class DescriptorListController {
* @param version the version
* @return the descriptor list
*/
@DeleteMapping(value = "/{UUID},{version}")
public DescriptorList deleteDescriptorList(@PathVariable("UUID") final UUID uuid, @PathVariable("version") final int version) {
@DeleteMapping(value = "/{uuid},{version}")
public DescriptorList deleteDescriptorList(@PathVariable("uuid") final UUID uuid, @PathVariable("version") final int version) {
return descriptorListService.deleteDescriptorList(descriptorListService.getDescriptorList(uuid, version));
}
......@@ -111,8 +111,8 @@ public class DescriptorListController {
* @throws IOException Signals that an I/O exception has occurred.
*/
@Transactional(readOnly = true)
@GetMapping(value = "/{UUID}/html", produces = { "text/html" })
public void generateDocument(@PathVariable("UUID") final UUID uuid, final HttpServletResponse response) throws IOException {
@GetMapping(value = "/{uuid}/html", produces = { "text/html" })
public void generateDocument(@PathVariable("uuid") final UUID uuid, final HttpServletResponse response) throws IOException {
final DescriptorList descriptorList = descriptorListService.getDescriptorList(uuid);
final String descriptorListHtml = exporter.htmlDescriptorList(descriptorList);
......@@ -204,8 +204,8 @@ public class DescriptorListController {
* @param descriptorUuids the descriptor uuids
* @return the descriptor list
*/
@PostMapping(value = "/add-descriptors/{UUID},{version}")
public DescriptorList addDescriptor(@PathVariable("UUID") final UUID uuid, @PathVariable("version") final int version, @RequestBody final List<UUID> descriptorUuids) {
@PostMapping(value = "/add-descriptors/{uuid},{version}")
public DescriptorList addDescriptor(@PathVariable("uuid") final UUID uuid, @PathVariable("version") final int version, @RequestBody final List<UUID> descriptorUuids) {
final DescriptorList descriptorList = descriptorListService.getDescriptorList(uuid, version);
final List<Descriptor> descriptors = descriptorUuids.stream().map(descriptorUuid -> descriptorService.getDescriptor(descriptorUuid)).collect(Collectors.toList());
return descriptorListService.addDescriptors(descriptorList, descriptors.toArray(new Descriptor[] {}));
......@@ -219,8 +219,8 @@ public class DescriptorListController {
* @param descriptorUuids the descriptor uuids
* @return the descriptor list
*/
@PostMapping(value = "/remove-descriptors/{UUID},{version}")
public DescriptorList removeDescriptor(@PathVariable("UUID") final UUID uuid, @PathVariable("version") final int version, @RequestBody final Set<UUID> descriptorUuids) {
@PostMapping(value = "/remove-descriptors/{uuid},{version}")
public DescriptorList removeDescriptor(@PathVariable("uuid") final UUID uuid, @PathVariable("version") final int version, @RequestBody final Set<UUID> descriptorUuids) {
final DescriptorList descriptorList = descriptorListService.getDescriptorList(uuid, version);
final Set<Descriptor> descriptors = descriptorUuids.stream().map(descriptorUuid -> descriptorService.getDescriptor(descriptorUuid)).collect(Collectors.toSet());
return descriptorListService.removeDescriptors(descriptorList, descriptors.toArray(new Descriptor[] {}));
......@@ -234,8 +234,8 @@ public class DescriptorListController {
* @param descriptorUuids the descriptor uuids
* @return the descriptor list
*/
@PostMapping(value = "/set-descriptors/{UUID},{version}")
public DescriptorList setDescriptor(@PathVariable("UUID") final UUID uuid, @PathVariable("version") final int version, @RequestBody final List<UUID> descriptorUuids) {
@PostMapping(value = "/set-descriptors/{uuid},{version}")
public DescriptorList setDescriptor(@PathVariable("uuid") final UUID uuid, @PathVariable("version") final int version, @RequestBody final List<UUID> descriptorUuids) {
final DescriptorList descriptorList = descriptorListService.getDescriptorList(uuid, version);
final List<Descriptor> descriptors = descriptorUuids.stream().map(descriptorUuid -> descriptorService.getDescriptor(descriptorUuid)).collect(Collectors.toList());
return descriptorListService.setDescriptors(descriptorList, descriptors.toArray(new Descriptor[] {}));
......
......@@ -68,8 +68,8 @@ public class PartnerController {
* @param uuid the uuid
* @return the partner
*/
@GetMapping(value = "/{UUID}")
public Partner getPartner(@PathVariable("UUID") final UUID uuid) {
@GetMapping(value = "/{uuid}")
public Partner getPartner(@PathVariable("uuid") final UUID uuid) {
return partnerService.loadPartner(uuid);
}
......@@ -80,8 +80,8 @@ public class PartnerController {
* @param version the version
* @return the partner
*/
@DeleteMapping(value = "/{UUID},{version}")
public Partner deletePartner(@PathVariable("UUID") final UUID uuid, @PathVariable("version") final int version) {
@DeleteMapping(value = "/{uuid},{version}")
public Partner deletePartner(@PathVariable("uuid") final UUID uuid, @PathVariable("version") final int version) {
return partnerService.removePartner(partnerService.loadPartner(uuid, version));
}
......
......@@ -102,8 +102,8 @@ public class SubsetController {
* @param uuid the uuid
* @return the subset
*/
@GetMapping(value = "/{UUID}", produces = { MediaType.APPLICATION_JSON_VALUE })
public Subset get(@PathVariable("UUID") final UUID uuid) {
@GetMapping(value = "/{uuid}", produces = { MediaType.APPLICATION_JSON_VALUE })
public Subset get(@PathVariable("uuid") final UUID uuid) {
return subsetService.get(uuid);
}
......@@ -114,8 +114,8 @@ public class SubsetController {
* @param version the version
* @return the subset
*/
@DeleteMapping(value = "/{UUID},{version}", produces = { MediaType.APPLICATION_JSON_VALUE })
public Subset remove(@PathVariable("UUID") final UUID uuid, @PathVariable("version") final int version) {
@DeleteMapping(value = "/{uuid},{version}", produces = { MediaType.APPLICATION_JSON_VALUE })
public Subset remove(@PathVariable("uuid") final UUID uuid, @PathVariable("version") final int version) {
return subsetService.delete(subsetService.get(uuid, version));
}
......@@ -169,8 +169,8 @@ public class SubsetController {
* @param accessionsUuids the accessions UUIDs to be removed
* @return the subset
*/
@PostMapping(value = "/remove-accessions/{UUID},{version}", produces = { MediaType.APPLICATION_JSON_VALUE })
public Subset removeAccessions(@PathVariable("UUID") final UUID uuid, @PathVariable("version") final int version, @RequestBody final Set<UUID> accessionsUuids) {
@PostMapping(value = "/remove-accessions/{uuid},{version}", produces = { MediaType.APPLICATION_JSON_VALUE })
public Subset removeAccessions(@PathVariable("uuid") final UUID uuid, @PathVariable("version") final int version, @RequestBody final Set<UUID> accessionsUuids) {
final Subset subset = subsetService.get(uuid, version);
return subsetService.removeAccessions(subset, accessionsUuids);
}
......@@ -183,8 +183,8 @@ public class SubsetController {
* @param accessionIds the accessions UUIDs to be added
* @return the subset
*/
@PostMapping(value = "/add-accessions/{UUID},{version}", produces = { MediaType.APPLICATION_JSON_VALUE })
public Subset addAccessions(@PathVariable("UUID") final UUID uuid, @PathVariable("version") final int version, @RequestBody final Set<UUID> accessionIds) {
@PostMapping(value = "/add-accessions/{uuid},{version}", produces = { MediaType.APPLICATION_JSON_VALUE })
public Subset addAccessions(@PathVariable("uuid") final UUID uuid, @PathVariable("version") final int version, @RequestBody final Set<UUID> accessionIds) {
final Subset subset = subsetService.get(uuid, version);
return subsetService.addAccessions(subset, accessionIds);
}
......
......@@ -48,7 +48,7 @@ import org.springframework.web.bind.annotation.*;
public class SubsetCreatorController {
/** The Constant API_BASE. */
public static final String CONTROLLER_URL = SubsetController.API_BASE + "/{UUID}/subsetcreator";
public static final String CONTROLLER_URL = SubsetController.API_BASE + "/{uuid}/subsetcreator";
/** The subset service. */
@Autowired
......@@ -62,7 +62,7 @@ public class SubsetCreatorController {
* @return the page
*/
@GetMapping(value = "/list")
public Page<SubsetCreator> listSubsetCreators(@PathVariable("UUID") final UUID uuid, final Pagination page) {
public Page<SubsetCreator> listSubsetCreators(@PathVariable("uuid") final UUID uuid, final Pagination page) {
return subsetService.listSubsetCreators(uuid, page.toPageRequest(100, Sort.Direction.ASC, "id"));
}
......@@ -87,7 +87,7 @@ public class SubsetCreatorController {
* @throws NotFoundElement the not found element
*/
@PostMapping(value = "/create")
public SubsetCreator createSubsetCreator(@PathVariable("UUID") final UUID uuid, @RequestBody final SubsetCreator subsetCreator) throws NotFoundElement {
public SubsetCreator createSubsetCreator(@PathVariable("uuid") final UUID uuid, @RequestBody final SubsetCreator subsetCreator) throws NotFoundElement {
final Subset subset = subsetService.get(uuid);
return subsetService.createSubsetCreator(subset, subsetCreator);
}
......@@ -102,7 +102,7 @@ public class SubsetCreatorController {
*/
// uses request body
@RequestMapping(value = "/delete", method = { RequestMethod.POST, RequestMethod.DELETE })
public SubsetCreator deleteSubsetCreator(@PathVariable("UUID") final UUID subsetUuid, @RequestBody final SubsetCreator subsetCreator) throws NotFoundElement {
public SubsetCreator deleteSubsetCreator(@PathVariable("uuid") final UUID subsetUuid, @RequestBody final SubsetCreator subsetCreator) throws NotFoundElement {
final Subset subset = subsetService.get(subsetUuid);
return subsetService.removeSubsetCreator(subset, subsetCreator);
}
......@@ -116,7 +116,7 @@ public class SubsetCreatorController {
* @throws NotFoundElement the not found element
*/
@PostMapping(value = "/update")
public SubsetCreator updateSubsetCreator(@PathVariable("UUID") final UUID subsetUuid, @RequestBody final SubsetCreator subsetCreator) throws NotFoundElement {
public SubsetCreator updateSubsetCreator(@PathVariable("uuid") final UUID subsetUuid, @RequestBody final SubsetCreator subsetCreator) throws NotFoundElement {
final Subset subset = subsetService.get(subsetUuid);
return subsetService.updateSubsetCreator(subset, subsetCreator);
}
......
......@@ -106,8 +106,8 @@ public class VocabularyController {
* @param uuid the uuid
* @return the controlled vocabulary
*/
@GetMapping(value = "/{UUID}")
public ControlledVocabulary get(@PathVariable("UUID") final UUID uuid) {
@GetMapping(value = "/{uuid}")
public ControlledVocabulary get(@PathVariable("uuid") final UUID uuid) {
return vocabularyService.getVocabulary(uuid);
}
......@@ -118,8 +118,8 @@ public class VocabularyController {
* @param code the code
* @return the term
*/
@GetMapping(value = "/{UUID}/{code}")
public VocabularyTerm getTerm(@PathVariable("UUID") final UUID uuid, @PathVariable("code") final String code) throws IOException, ServletException {
@GetMapping(value = "/{uuid}/{code}")
public VocabularyTerm getTerm(@PathVariable("uuid") final UUID uuid, @PathVariable("code") final String code) throws IOException, ServletException {
switch (uuid.toString()) {
case FAO_WIEWS_UUID:
......@@ -142,9 +142,9 @@ public class VocabularyController {
* @param like the like
* @return the list
*/
@PostMapping(value = "/{UUID}/autocomplete")
@PostMapping(value = "/{uuid}/autocomplete")
@JsonView({ JsonViews.Public.class })
public List<VocabularyTerm> autocompleteTerm(@PathVariable("UUID") final UUID uuid, @RequestParam("q") final String like) {
public List<VocabularyTerm> autocompleteTerm(@PathVariable("uuid") final UUID uuid, @RequestParam("q") final String like) {
return vocabularyService.autocompleteTerms(uuid, like);
}
......@@ -155,9 +155,9 @@ public class VocabularyController {
* @param page the page
* @return the page
*/
@PostMapping(value = "/{UUID}/terms")
@PostMapping(value = "/{uuid}/terms")
@JsonView({ JsonViews.Public.class })
public Page<VocabularyTerm> listTerms(@PathVariable("UUID") final UUID uuid, final Pagination page) {
public Page<VocabularyTerm> listTerms(@PathVariable("uuid") final UUID uuid, final Pagination page) {
// LOG.warn("Loading vocab");
final ControlledVocabulary vocabulary = vocabularyService.getVocabulary(uuid);
// LOG.warn("Loading terms");
......@@ -183,8 +183,8 @@ public class VocabularyController {
* @param version the version
* @return the controlled vocabulary
*/
@DeleteMapping(value = "/{UUID},{version}")
public ControlledVocabulary delete(@PathVariable("UUID") final UUID uuid, @PathVariable("version") final int version) {
@DeleteMapping(value = "/{uuid},{version}")
public ControlledVocabulary delete(@PathVariable("uuid") final UUID uuid, @PathVariable("version") final int version) {
return vocabularyService.deleteVocabulary(vocabularyService.getVocabulary(uuid, version));
}
......
......@@ -256,8 +256,8 @@ public class AccessionController extends BaseController {
return "/accession/resolve";
}
@GetMapping(value = "/{UUID:\\w{8}\\-\\w{4}.+}")
public String viewAccessionByUUID(final ModelMap model, @PathVariable("UUID") final UUID uuid) {
@GetMapping(value = "/{uuid:\\w{8}\\-\\w{4}.+}")
public String viewAccessionByUUID(final ModelMap model, @PathVariable("uuid") final UUID uuid) {
final Accession accession = accessionService.getByUuid(uuid);
if (accession == null) {
......
......@@ -79,8 +79,8 @@ public class SubsetController extends BaseController {
return "/subset/index";
}
@GetMapping(value = "/{UUID}")
public String subset(final HttpServletResponse response, final ModelMap model, @PathVariable("UUID") final UUID uuid,
@GetMapping(value = "/{uuid}")
public String subset(final HttpServletResponse response, final ModelMap model, @PathVariable("uuid") final UUID uuid,
@RequestParam(value = "page", required = false, defaultValue = "1") int page) {
Subset subset;
......
......@@ -140,6 +140,9 @@ public class AccessionUploader implements InitializingBean {
LOG.trace("Received: {}", accn);
try {
Accession accession = reader.readValue(accn);
if (accession.getInstituteCode() == null || (accession.getDoi() == null && accession.getAccessionNumber() == null)) {
throw new InvalidApiUsageException("instituteCode, accessionNumber OR doi missing in " + accn);
}
accessions.add(accession);
responses.add(new AccessionOpResponse(accession.getInstituteCode(), accession.getAccessionNumber(), accession.getTaxonomy().getGenus()));
} catch (IOException e) {
......
......@@ -16,21 +16,24 @@
package org.genesys2.spring.config;
import static com.google.common.collect.Lists.newArrayList;
import static springfox.documentation.builders.PathSelectors.ant;
import static springfox.documentation.builders.PathSelectors.regex;
import static springfox.documentation.builders.PathSelectors.*;
import static springfox.documentation.schema.AlternateTypeRules.newRule;
import java.net.URL;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.google.common.base.Predicate;
import com.fasterxml.classmate.TypeResolver;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.AuthorizationCodeGrantBuilder;
import springfox.documentation.builders.OAuthBuilder;
import springfox.documentation.schema.AlternateTypeRule;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.service.AuthorizationScope;
......@@ -57,11 +60,24 @@ public class SwaggerConfig {
@Value("${build.version}")
private String version;
private TypeResolver resolver = new TypeResolver();
public SwaggerConfig() {
System.err.println("Making SwaggerConfig!");
}
private AlternateTypeRule[] alternateTypes() {
return new AlternateTypeRule[] {
// URL as String
newRule(URL.class, String.class),
newRule(resolver.arrayType(URL.class), resolver.arrayType(String.class)),
newRule(resolver.resolve(List.class, URL.class), resolver.resolve(List.class, String.class)),
newRule(resolver.resolve(Set.class, URL.class), resolver.resolve(Set.class, String.class))
// Other..
};
}
/**
* Every Docket bean is picked up by the swagger-mvc framework - allowing for
* multiple swagger groups i.e. same code base multiple swagger resource
......@@ -70,19 +86,40 @@ public class SwaggerConfig {
* @return Docket
*/
@Bean
public Docket apiDocket() {
public Docket apiV0Docket() {
return new Docket(DocumentationType.SWAGGER_2).host(hostAndPort)
// .protocols(newHashSet("http", "https"))
// Paths
.select().paths(apiPaths()).build()
.select().paths(regex("/api/v0/.+")).build()
// General info
.apiInfo(apiInfo())
.groupName("v0")
// Alternative types