Skip to content

Commit

Permalink
Use @NonNullApis annotations and fix numerous possible NPEs
Browse files Browse the repository at this point in the history
  • Loading branch information
arteymix committed Apr 3, 2024
1 parent 98bd73b commit 1b14ea3
Show file tree
Hide file tree
Showing 61 changed files with 388 additions and 290 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.lang.Nullable;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;
import org.springframework.web.bind.WebDataBinder;
Expand Down Expand Up @@ -60,14 +61,18 @@ public abstract class AbstractSearchController {
@Data
@NoArgsConstructor
@AllArgsConstructor(access = AccessLevel.PROTECTED)
protected static class SearchParams {
public static class SearchParams {
private boolean iSearch;
@Nullable
private Set<ResearcherPosition> researcherPositions;
@Nullable
private Set<ResearcherCategory> researcherCategories;
@Nullable
private Set<String> organUberonIds;
/**
* Order matters here because we want to preserve the UI rendering.
*/
@Nullable
private List<Integer> ontologyTermIds;

/**
Expand All @@ -81,14 +86,14 @@ public boolean isEmpty() {
@Data
@EqualsAndHashCode(callSuper = true)
@NoArgsConstructor
protected static class UserSearchParams extends SearchParams {
public static class UserSearchParams extends SearchParams {
@NotNull
private String nameLike;
private boolean prefix;
@NotNull
private String descriptionLike;

public UserSearchParams( String nameLike, boolean prefix, String descriptionLike, boolean iSearch, Set<ResearcherPosition> researcherPositions, Set<ResearcherCategory> researcherCategories, Set<String> organUberonIds, List<Integer> ontologyTermIds ) {
public UserSearchParams( String nameLike, boolean prefix, String descriptionLike, boolean iSearch, @Nullable Set<ResearcherPosition> researcherPositions, @Nullable Set<ResearcherCategory> researcherCategories, @Nullable Set<String> organUberonIds, @Nullable List<Integer> ontologyTermIds ) {
super( iSearch, researcherPositions, researcherCategories, organUberonIds, ontologyTermIds );
this.nameLike = nameLike;
this.prefix = prefix;
Expand All @@ -101,7 +106,7 @@ public boolean isEmpty() {
}
}

protected static class UserSearchParamsValidator implements Validator {
public static class UserSearchParamsValidator implements Validator {

@Override
public boolean supports( Class<?> clazz ) {
Expand Down Expand Up @@ -129,9 +134,10 @@ protected static class GeneSearchParams extends SearchParams {
@NotNull
private GeneInfo gene;
private Set<TierType> tiers;
@Nullable
private Taxon orthologTaxon;

public GeneSearchParams( GeneInfo gene, Set<TierType> tiers, Taxon orthologTaxon, boolean iSearch, Set<ResearcherPosition> researcherPositions, Set<ResearcherCategory> researcherCategories, Set<String> organUberonIds, List<Integer> ontologyTermIds ) {
public GeneSearchParams( GeneInfo gene, Set<TierType> tiers, @Nullable Taxon orthologTaxon, boolean iSearch, @Nullable Set<ResearcherPosition> researcherPositions, @Nullable Set<ResearcherCategory> researcherCategories, @Nullable Set<String> organUberonIds, @Nullable List<Integer> ontologyTermIds ) {
super( iSearch, researcherPositions, researcherCategories, organUberonIds, ontologyTermIds );
this.gene = gene;
this.tiers = tiers;
Expand Down Expand Up @@ -371,17 +377,13 @@ private static <K, T> Map<K, T> collectAsManyFuturesAsPossible( Map<K, ? extends
return results;
}

protected Collection<OrganInfo> organsFromUberonIds( Set<String> organUberonIds ) {
@Nullable
protected Collection<OrganInfo> organsFromUberonIds( @Nullable Set<String> organUberonIds ) {
return organUberonIds == null ? null : organInfoService.findByUberonIdIn( organUberonIds );
}

/**
* No need to perform the same
*
* @param ontologyTermIds
* @return
*/
protected Map<Ontology, Set<OntologyTermInfo>> ontologyTermsFromIds( List<Integer> ontologyTermIds ) {
@Nullable
protected Map<Ontology, Set<OntologyTermInfo>> ontologyTermsFromIds( @Nullable List<Integer> ontologyTermIds ) {
return ontologyTermIds == null ? null : ontologyService.findAllTermsByIdIn( ontologyTermIds ).stream()
.collect( Collectors.groupingBy( OntologyTermInfo::getOntology, Collectors.toSet() ) );
}
Expand Down
28 changes: 19 additions & 9 deletions src/main/java/ubc/pavlab/rdp/controllers/AdminController.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.lang.Nullable;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.concurrent.DelegatingSecurityContextRunnable;
import org.springframework.stereotype.Controller;
Expand Down Expand Up @@ -713,16 +714,24 @@ public Object importReactomePathways( RedirectAttributes redirectAttributes ) {
}

@PostMapping("/admin/ontologies/{ontology}/update-reactome-pathways")
public Object updateReactomePathways( @PathVariable(required = false) Ontology ontology, RedirectAttributes redirectAttributes, Locale locale ) {
public Object updateReactomePathways( @PathVariable(required = false) @Nullable Ontology ontology, RedirectAttributes redirectAttributes, Locale locale ) {
// null-check is not necessary, but can save a database call
if ( ontology == null || !ontology.equals( reactomeService.findPathwaysOntology() ) ) {
return new ModelAndView( "error/404", HttpStatus.NOT_FOUND )
.addObject( "message", messageSource.getMessage( "AdminController.ontologyNotFoundById", null, locale ) );
}
try {
Ontology reactomeOntology = reactomeService.updatePathwaysOntology();
redirectAttributes.addFlashAttribute( "message", "Successfully updated Reactome pathways ontology." );
return "redirect:/admin/ontologies/" + reactomeOntology.getId();
if ( reactomeOntology != null ) {
redirectAttributes.addFlashAttribute( "message", "Successfully updated Reactome pathways ontology." );
return "redirect:/admin/ontologies/" + reactomeOntology.getId();
} else {
String message = "It seems that Reactome ontology does not setup.";
log.error( message );
redirectAttributes.addFlashAttribute( "message", message );
redirectAttributes.addFlashAttribute( "error", Boolean.TRUE );
return "redirect:/admin/ontologies";
}
} catch ( ReactomeException e ) {
log.error( "Failed to update Reactome pathways. Could this be an issue with the ontology configuration?", e );
redirectAttributes.addFlashAttribute( "message", "Failed to update Reactome pathways: " + e.getMessage() + "." );
Expand All @@ -735,9 +744,9 @@ public Object updateReactomePathways( @PathVariable(required = false) Ontology o
* Update Reactome Pathways summations.
*/
@PostMapping(value = "/admin/ontologies/{ontology}/update-reactome-pathway-summations")
public Object updateReactomePathwaySummations( @PathVariable(required = false) Ontology ontology, Locale locale ) {
public Object updateReactomePathwaySummations( @PathVariable(required = false) @Nullable Ontology ontology, Locale locale ) {
// null-check is not necessary, but can save a database call
if ( ontology == null || !reactomeService.findPathwaysOntology().equals( ontology ) ) {
if ( ontology == null || !Objects.equals( reactomeService.findPathwaysOntology(), ontology ) ) {
return new ModelAndView( "error/404", HttpStatus.NOT_FOUND )
.addObject( "message", messageSource.getMessage( "AdminController.ontologyNotFoundById", null, locale ) );
}
Expand All @@ -756,9 +765,9 @@ public Object updateReactomePathwaySummations( @PathVariable(required = false) O
* @see #updateReactomePathwaySummations(Ontology, Locale)
*/
@GetMapping(value = "/admin/ontologies/{ontology}/update-reactome-pathway-summations", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Object updateReactomePathwaySummationsSse( @PathVariable(required = false) Ontology ontology, Locale locale ) {
public Object updateReactomePathwaySummationsSse( @PathVariable(required = false) @Nullable Ontology ontology, Locale locale ) {
// null-check is not necessary, but can save a database call
if ( ontology == null || !reactomeService.findPathwaysOntology().equals( ontology ) ) {
if ( ontology == null || !Objects.equals( reactomeService.findPathwaysOntology(), ontology ) ) {
return ResponseEntity.status( HttpStatus.NOT_FOUND )
.body( messageSource.getMessage( "AdminController.ontologyNotFoundById", null, locale ) );
}
Expand Down Expand Up @@ -1011,6 +1020,7 @@ public static class ImportOntologyForm {
private URL ontologyUrl;
private MultipartFile ontologyFile;

@Nullable
public String getFilename() {
if ( ontologyUrl != null ) {
// path cannot be null, but it can be empty if missing (i.e. http://github.com)
Expand All @@ -1034,13 +1044,13 @@ private Reader getReaderForImportOntologyForm( ImportOntologyForm importOntology
} else if ( !isMultipartFileEmpty( importOntologyForm.ontologyFile ) ) {
is = importOntologyForm.ontologyFile.getInputStream();
} else {
return null;
throw new RuntimeException( "No reader can be created from the import ontology form." );
}
boolean hasGzipExtension = FilenameUtils.isExtension( importOntologyForm.getFilename(), "gz" );
return new InputStreamReader( hasGzipExtension ? new GZIPInputStream( is ) : is );
}

private static boolean isMultipartFileEmpty( MultipartFile mp ) {
private static boolean isMultipartFileEmpty( @Nullable MultipartFile mp ) {
return mp == null || mp.isEmpty();
}

Expand Down
23 changes: 13 additions & 10 deletions src/main/java/ubc/pavlab/rdp/controllers/ApiController.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.lang.Nullable;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.core.Authentication;
Expand Down Expand Up @@ -179,7 +180,7 @@ public Page<RemoteOntologyTermInfo> getOntologyTerms( @PathVariable String ontol
}

@GetMapping(value = "/api/ontologies/{ontologyName}/terms", params = { "ontologyTermIds" }, produces = MediaType.APPLICATION_JSON_VALUE)
public List<RemoteOntologyTermInfo> getOntologyTermsByOntologyNameAndTermIds( @PathVariable String ontologyName, @RequestParam List<String> ontologyTermIds, Locale locale ) {
public List<RemoteOntologyTermInfo> getOntologyTermsByOntologyNameAndTermIds( @PathVariable String ontologyName, @Nullable @RequestParam List<String> ontologyTermIds, Locale locale ) {
Ontology ontology = ontologyService.findByName( ontologyName );
if ( ontology == null || !ontology.isActive() ) {
throw new ApiException( HttpStatus.NOT_FOUND, String.format( locale, "No ontology %s.", ontologyName ) );
Expand Down Expand Up @@ -247,13 +248,13 @@ public List<User> searchUsersByNameAndDescription( @RequestParam String nameLike
@GetMapping(value = "/api/genes/search", params = { "symbol", "taxonId" }, produces = MediaType.APPLICATION_JSON_VALUE)
public List<UserGene> searchUsersByGeneSymbol( @RequestParam String symbol,
@RequestParam Integer taxonId,
@RequestParam(required = false) Set<TierType> tiers,
@RequestParam(required = false) Integer orthologTaxonId,
@RequestParam(required = false) Set<ResearcherPosition> researcherPositions,
@RequestParam(required = false) Set<ResearcherCategory> researcherCategories,
@RequestParam(required = false) Set<String> organUberonIds,
@RequestParam(required = false) List<String> ontologyNames,
@RequestParam(required = false) List<String> ontologyTermIds,
@Nullable @RequestParam(required = false) Set<TierType> tiers,
@Nullable @RequestParam(required = false) Integer orthologTaxonId,
@Nullable @RequestParam(required = false) Set<ResearcherPosition> researcherPositions,
@Nullable @RequestParam(required = false) Set<ResearcherCategory> researcherCategories,
@Nullable @RequestParam(required = false) Set<String> organUberonIds,
@Nullable @RequestParam(required = false) List<String> ontologyNames,
@Nullable @RequestParam(required = false) List<String> ontologyTermIds,
Locale locale ) {

Taxon taxon = taxonService.findById( taxonId );
Expand Down Expand Up @@ -448,11 +449,13 @@ private Set<TierType> restrictTiers( Set<TierType> tiers ) {
.collect( Collectors.toSet() );
}

private Collection<OrganInfo> organsFromUberonIds( Set<String> organUberonIds ) {
@Nullable
private Collection<OrganInfo> organsFromUberonIds( @Nullable Set<String> organUberonIds ) {
return organUberonIds == null ? null : organInfoService.findByUberonIdIn( organUberonIds );
}

private Map<Ontology, Set<OntologyTermInfo>> ontologyTermsFromOntologyWithTermIds( List<String> ontologyNames, List<String> termIds ) {
@Nullable
private Map<Ontology, Set<OntologyTermInfo>> ontologyTermsFromOntologyWithTermIds( @Nullable List<String> ontologyNames, @Nullable List<String> termIds ) {
if ( ontologyNames == null || termIds == null ) {
return null;
}
Expand Down
11 changes: 9 additions & 2 deletions src/main/java/ubc/pavlab/rdp/controllers/GeneController.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import ubc.pavlab.rdp.model.GeneInfo;
import ubc.pavlab.rdp.model.Taxon;
import ubc.pavlab.rdp.services.GOService;
Expand Down Expand Up @@ -82,6 +85,10 @@ public Object getGeneByTaxonAndSymbol( @PathVariable Integer taxonId, @PathVaria
if ( taxon == null ) {
return ResponseEntity.notFound().build();
}
return geneService.findBySymbolAndTaxon( symbol, taxon );
GeneInfo gene = geneService.findBySymbolAndTaxon( symbol, taxon );
if ( gene == null ) {
return ResponseEntity.notFound().build();
}
return gene;
}
}
Loading

0 comments on commit 1b14ea3

Please sign in to comment.