Skip to content

Commit

Permalink
Merge branch 'hotfix-1.5.1'
Browse files Browse the repository at this point in the history
  • Loading branch information
arteymix committed Sep 23, 2022
2 parents 4b3fdde + e1e876f commit a3b5f8c
Show file tree
Hide file tree
Showing 25 changed files with 126 additions and 95 deletions.
6 changes: 3 additions & 3 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

<groupId>ubc.pavlab</groupId>
<artifactId>rdp</artifactId>
<version>1.5.0</version>
<version>1.5.1</version>

<description>
Registry for model organism researchers, developed for the Canadian Rare Disease Models &amp; Mechanisms Network.
Expand All @@ -28,7 +28,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.6.10</version>
<version>2.6.12</version>
</parent>

<dependencies>
Expand Down Expand Up @@ -108,7 +108,7 @@
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-webmvc-core</artifactId>
<version>1.6.9</version>
<version>1.6.11</version>
</dependency>

<!-- Database Migration -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -291,7 +291,7 @@ protected Map<URI, List<OntologyAvailability>> getOntologyAvailabilityByApiUri(

Map<URI, List<OntologyAvailability>> availability = new HashMap<>();
for ( URI remoteHost : remoteResourceService.getApiUris() ) {
List<OntologyAvailability> availabilities = new ArrayList<>();
List<OntologyAvailability> availabilities = new ArrayList<>( termsByOntology.size() );
// lookup origin and origin URL in all terms from all ontologies
// when an ontology is not present, there are no terms returned and thus no way to determine the origin, so
// we increase our chance by of finding something useful this way
Expand Down
32 changes: 15 additions & 17 deletions src/main/java/ubc/pavlab/rdp/controllers/AdminController.java
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ public Object updateRoles( @PathVariable User user, @RequestParam(required = fal
}
} catch ( RoleException e ) {
redirectAttributes.addFlashAttribute( "message", e.getMessage() );
redirectAttributes.addFlashAttribute( "error", true );
redirectAttributes.addFlashAttribute( "error", Boolean.TRUE );
}
return "redirect:/admin/users/" + user.getId();

Expand Down Expand Up @@ -361,9 +361,9 @@ public Object deleteOntology( @PathVariable(required = false) Ontology ontology,
redirectAttributes.addFlashAttribute( "message", String.format( "The %s category has been deleted.", messageSource.getMessage( ontology.getResolvableTitle(), locale ) ) );
return "redirect:/admin/ontologies";
} catch ( DataIntegrityViolationException e ) {
log.warn( String.format( "An administrator attempted to delete %s, but it failed: %s", ontology, e.getMessage() ) );
log.warn( String.format( "An administrator attempted to delete %s, but it failed: %s", ontology.toString().replaceAll( "[\r\n]", "" ), e.getMessage() ) );
modelAndView.setStatus( HttpStatus.BAD_REQUEST );
modelAndView.addObject( "error", true );
modelAndView.addObject( "error", Boolean.TRUE );
modelAndView.addObject( "message", String.format( "The %s category could not be deleted because it is being used. Instead, you should deactivate it.", messageSource.getMessage( ontology.getResolvableTitle(), locale ) ) );
}
}
Expand Down Expand Up @@ -592,9 +592,9 @@ public void validate( Object target, Errors errors ) {
.filter( row -> !row.isEmpty() )
.map( SimpleOntologyTermForm::getTermId )
.filter( termId -> !StringUtils.isEmpty( termId ) ) // empty or null term IDs are generated
.collect( Collectors.groupingBy( t -> t, Collectors.counting() ) );
.collect( Collectors.groupingBy( identity(), Collectors.counting() ) );
if ( countsByTermId.values().stream().anyMatch( x -> x > 1 ) ) {
errors.rejectValue( "ontologyTerms", "AdminController.SimpleOntologyForm.ontologyTerms.nonUniqueTermIds", "termId must be unique" );
errors.rejectValue( "ontologyTerms", "AdminController.SimpleOntologyForm.ontologyTerms.nonUniqueTermIds" );
}

// validate non-empty rows
Expand Down Expand Up @@ -643,19 +643,19 @@ public Object updateOntology( @PathVariable(required = false) Ontology ontology,
return new ModelAndView( "admin/ontology", HttpStatus.BAD_REQUEST )
.addAllObjects( defaultsForOntologyModelAndView( ontology ) )
.addObject( "message", "The provided ontology cannot be updated because it lacks an external URL." )
.addObject( "error", true );
.addObject( "error", Boolean.TRUE );
} else {
Resource urlResource = ontologyService.resolveOntologyUrl( ontology.getOntologyUrl() );
try ( Reader reader = new InputStreamReader( urlResource.getInputStream() ) ) {
ontologyService.updateFromObo( ontology, reader );
int numActivated = ontologyService.propagateSubtreeActivation( ontology );
redirectAttributes.addFlashAttribute( "message", String.format( "Updated %s from %s. %d terms got activated via subtree propagation.", messageSource.getMessage( ontology.getResolvableTitle(), locale ), ontology.getOntologyUrl(), numActivated ) );
} catch ( IOException | ParseException e ) {
log.warn( String.format( "Failed to update ontology %s from administrative section.", ontology ), e );
log.warn( String.format( "Failed to update ontology %s from administrative section.", ontology.toString().replaceAll( "[\r\n]", "" ) ), e );
return new ModelAndView( "admin/ontology", HttpStatus.BAD_REQUEST )
.addAllObjects( defaultsForOntologyModelAndView( ontology ) )
.addObject( "message", String.format( "Failed to update %s: %s", messageSource.getMessage( ontology.getResolvableTitle(), locale ), e.getMessage() ) )
.addObject( "error", true );
.addObject( "error", Boolean.TRUE );
}
}
return "redirect:/admin/ontologies/" + ontology.getId();
Expand All @@ -673,14 +673,12 @@ public Object importOntology( @Valid ImportOntologyForm importOntologyForm, Bind
ontologyService.update( ontology );
return "redirect:/admin/ontologies/" + ontology.getId();
} catch ( OntologyNameAlreadyUsedException e ) {
bindingResult.reject( "AdminController.ImportOntologyForm.ontologyWithSameNameAlreadyUsed", new String[]{ e.getOntologyName() },
String.format( "An ontology with the same name '%s' is already used.", e.getOntologyName() ) );
bindingResult.reject( "AdminController.ImportOntologyForm.ontologyWithSameNameAlreadyUsed", new String[]{ e.getOntologyName() }, null );
return new ModelAndView( "admin/ontologies", HttpStatus.BAD_REQUEST )
.addObject( "simpleOntologyForm", SimpleOntologyForm.withInitialRows() );
} catch ( IOException | ParseException e ) {
log.warn( String.format( "Failed to import ontology from submitted form: %s.", importOntologyForm ), e );
bindingResult.reject( "AdminController.ImportOntologyForm.failedToParseOboFormat", new String[]{ importOntologyForm.getFilename(), e.getMessage() },
String.format( "Failed to parse the ontology OBO format from %s: %s", importOntologyForm.getFilename(), e.getMessage() ) );
bindingResult.reject( "AdminController.ImportOntologyForm.failedToParseOboFormat", new String[]{ importOntologyForm.getFilename(), e.getMessage() }, null );
return new ModelAndView( "admin/ontologies", HttpStatus.INTERNAL_SERVER_ERROR )
.addObject( "simpleOntologyForm", SimpleOntologyForm.withInitialRows() );
}
Expand Down Expand Up @@ -711,7 +709,7 @@ public Object importReactomePathways( RedirectAttributes redirectAttributes ) {
} catch ( ReactomeException e ) {
log.error( "Failed to import Reactome pathways. Could this be an issue with the ontology configuration?", e );
redirectAttributes.addFlashAttribute( "message", "Failed to import Reactome pathways: " + e.getMessage() + "." );
redirectAttributes.addFlashAttribute( "error", true );
redirectAttributes.addFlashAttribute( "error", Boolean.TRUE );
return "redirect:/admin/ontologies";
}
}
Expand All @@ -730,7 +728,7 @@ public Object updateReactomePathways( @PathVariable(required = false) Ontology o
} 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() + "." );
redirectAttributes.addFlashAttribute( "error", true );
redirectAttributes.addFlashAttribute( "error", Boolean.TRUE );
return "redirect:/admin/ontologies";
}
}
Expand Down Expand Up @@ -948,7 +946,7 @@ private Object activateOrDeactivateTerm( Ontology ontology,
* Provides the ontology in OBO format.
*/
@GetMapping(value = "/admin/ontologies/{ontology}/download", produces = "text/plain")
public ResponseEntity<StreamingResponseBody> downloadOntology( @PathVariable(required = false) Ontology ontology ) {
public ResponseEntity<StreamingResponseBody> downloadOntology( @PathVariable(required = false) Ontology ontology, TimeZone timeZone ) {
if ( ontology == null ) {
return ResponseEntity.notFound().build();
}
Expand All @@ -957,7 +955,7 @@ public ResponseEntity<StreamingResponseBody> downloadOntology( @PathVariable(req
headers.set( "Content-Disposition", String.format( "attachment; filename=%s.obo", ontology.getName() ) );
return new ResponseEntity<>( outputStream -> {
try ( Writer writer = new OutputStreamWriter( outputStream ) ) {
ontologyService.writeObo( ontology, writer );
ontologyService.writeObo( ontology, writer, timeZone );
}
}, headers, HttpStatus.OK );
}
Expand Down Expand Up @@ -1002,7 +1000,7 @@ public Object move( @PathVariable(required = false) Ontology ontology, @RequestP
d = OntologyService.Direction.DOWN;
} else {
return new ModelAndView( "admin/ontologies", HttpStatus.BAD_REQUEST )
.addObject( "error", true )
.addObject( "error", Boolean.TRUE )
.addObject( "message", String.format( "Invalid direction %s.", direction ) )
.addObject( "simpleOntologyForm", SimpleOntologyForm.withInitialRows() );
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ public Object searchUsers( @Valid UserSearchParams userSearchParams, BindingResu
} else {
modelAndView.addObject( "Invalid user search parameters." );
}
modelAndView.addObject( "error", true );
modelAndView.addObject( "error", Boolean.TRUE );
modelAndView.addObject( "users", Collections.emptyList() );
if ( userSearchParams.isISearch() ) {
modelAndView.addObject( "itlUsers", Collections.emptyList() );
Expand Down Expand Up @@ -163,7 +163,7 @@ public ModelAndView searchUsersByName( @RequestParam String nameLike,
if ( nameLike.isEmpty() ) {
modelAndView.setStatus( HttpStatus.BAD_REQUEST );
modelAndView.addObject( "message", "Researcher name cannot be empty." );
modelAndView.addObject( "error", true );
modelAndView.addObject( "error", Boolean.TRUE );
modelAndView.addObject( "users", Collections.emptyList() );
modelAndView.addObject( "itlUsers", Collections.emptyList() );
modelAndView.addObject( "termsAvailabilityByApiUri", Collections.emptyMap() );
Expand Down Expand Up @@ -206,7 +206,7 @@ public ModelAndView searchUsersByDescription( @RequestParam String descriptionLi
if ( descriptionLike.isEmpty() ) {
modelAndView.setStatus( HttpStatus.BAD_REQUEST );
modelAndView.addObject( "message", "Research interests cannot be empty." );
modelAndView.addObject( "error", true );
modelAndView.addObject( "error", Boolean.TRUE );
modelAndView.addObject( "users", Collections.emptyList() );
modelAndView.addObject( "itlUsers", Collections.emptyList() );
modelAndView.addObject( "termsAvailabilityByApiUri", Collections.emptyMap() );
Expand Down Expand Up @@ -275,7 +275,7 @@ public ModelAndView searchUsersByGene( @RequestParam String symbol,
if ( symbol.isEmpty() ) {
modelAndView.setStatus( HttpStatus.BAD_REQUEST );
modelAndView.addObject( "message", "Gene symbol cannot be empty." );
modelAndView.addObject( "error", true );
modelAndView.addObject( "error", Boolean.TRUE );
return modelAndView;
}

Expand Down
8 changes: 3 additions & 5 deletions src/main/java/ubc/pavlab/rdp/listeners/OntologyListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionalEventListener;
import org.springframework.util.Assert;
import ubc.pavlab.rdp.events.OnOntologyUpdateEvent;
import ubc.pavlab.rdp.services.OntologyService;
import ubc.pavlab.rdp.util.CacheUtils;

/**
* Listener for {@link ubc.pavlab.rdp.model.ontology.Ontology}-related events.
Expand All @@ -28,10 +28,8 @@ public class OntologyListener implements InitializingBean {

@Override
public void afterPropertiesSet() {
subtreeSizeCache = cacheManager.getCache( OntologyService.SUBTREE_SIZE_BY_TERM_CACHE_NAME );
Assert.notNull( subtreeSizeCache, String.format( "There is no cache named %s.", OntologyService.SIMPLE_ONTOLOGIES_CACHE_NAME ) );
simpleOntologiesCache = cacheManager.getCache( OntologyService.SUBTREE_SIZE_BY_TERM_CACHE_NAME );
Assert.notNull( simpleOntologiesCache, String.format( "There is no cache named %s.", OntologyService.SIMPLE_ONTOLOGIES_CACHE_NAME ) );
subtreeSizeCache = CacheUtils.getCache( cacheManager, OntologyService.SUBTREE_SIZE_BY_TERM_CACHE_NAME );
simpleOntologiesCache = CacheUtils.getCache( cacheManager, OntologyService.SUBTREE_SIZE_BY_TERM_CACHE_NAME );
}

@TransactionalEventListener
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/ubc/pavlab/rdp/model/Gene.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
@Setter
@EqualsAndHashCode(of = { "geneId" })
@ToString(of = { "geneId", "symbol", "taxon" })
public abstract class Gene {
public abstract class Gene implements Serializable {

@NaturalId
@Column(name = "gene_id")
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/ubc/pavlab/rdp/model/GeneInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
@Index(columnList = "gene_id, taxon_id"),
@Index(columnList = "symbol, taxon_id") })
@Getter
public class GeneInfo extends Gene implements Comparable<GeneInfo>, Serializable {
public class GeneInfo extends Gene implements Comparable<GeneInfo> {

public static Comparator<GeneInfo> getComparator() {
return Comparator.comparing( GeneInfo::getGeneId );
Expand Down
2 changes: 1 addition & 1 deletion src/main/java/ubc/pavlab/rdp/model/UserGene.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
@CommonsLog
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
@ToString(of = { "user", "tier", "privacyLevel" }, callSuper = true)
public class UserGene extends Gene implements UserContent, Serializable {
public class UserGene extends Gene implements UserContent {

public static UserGeneBuilder builder( User user ) {
return new UserGeneBuilder().user( user );
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/ubc/pavlab/rdp/model/ontology/OntologyTerm.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package ubc.pavlab.rdp.model.ontology;

import com.fasterxml.jackson.annotation.JsonIgnore;
import io.micrometer.core.lang.Nullable;
import lombok.*;
import lombok.experimental.SuperBuilder;
import org.hibernate.annotations.NaturalId;
Expand All @@ -12,6 +11,7 @@
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.MappedSuperclass;
import java.io.Serializable;
import java.util.Locale;

/**
Expand All @@ -26,7 +26,7 @@
@EqualsAndHashCode(of = { "ontology", "termId" })
@ToString(of = { "ontology", "termId", "name" })
@SuperBuilder
public abstract class OntologyTerm {
public abstract class OntologyTerm implements Serializable {

/**
* Ontology to which is term is part of.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import org.springframework.context.support.DefaultMessageSourceResolvable;

import javax.persistence.*;
import java.io.Serializable;
import java.text.Collator;
import java.util.*;

Expand All @@ -35,7 +34,7 @@
@ToString(of = { "id" }, callSuper = true)
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@SuperBuilder
public class OntologyTermInfo extends OntologyTerm implements Serializable, Comparable<OntologyTermInfo> {
public class OntologyTermInfo extends OntologyTerm implements Comparable<OntologyTermInfo> {

/**
* Maximum size of term ID and name.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class OlsResolver implements OntologyResolver {

@Override
public boolean accepts( Ontology ontology ) {
return ontology.getOntologyUrl() != null && ontology.getOntologyUrl().toString().startsWith( DEFAULT_IRI_PREFIX );
return ontology.getOntologyUrl() != null && ontology.getOntologyUrl().toExternalForm().startsWith( DEFAULT_IRI_PREFIX );
}

@Override
Expand All @@ -34,6 +34,6 @@ public URI resolveViewOntologyUrl( Ontology ontology ) {
public URI resolveViewTermUrl( OntologyTerm term ) {
return UriComponentsBuilder.fromHttpUrl( "https://www.ebi.ac.uk/ols/ontologies/{0}/terms" )
.queryParam( "iri", "{1}" )
.build( term.getOntology().getName(), DEFAULT_IRI_PREFIX + term.getTermId().replace( ":", "_" ) );
.build( term.getOntology().getName(), DEFAULT_IRI_PREFIX + term.getTermId().replace( ':', '_' ) );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class OntobeeResolver implements OntologyResolver {

@Override
public boolean accepts( Ontology ontology ) {
return ontology.getOntologyUrl().toString().startsWith( DEFAULT_IRI_PREFIX );
return ontology.getOntologyUrl().toExternalForm().startsWith( DEFAULT_IRI_PREFIX );
}

@Override
Expand All @@ -34,6 +34,6 @@ public URI resolveViewOntologyUrl( Ontology ontology ) {
public URI resolveViewTermUrl( OntologyTerm term ) {
return UriComponentsBuilder.fromHttpUrl( "https://ontobee.org/ontology/{0}" )
.queryParam( "iri", "{1}" )
.build( term.getOntology().getName().toUpperCase(), DEFAULT_IRI_PREFIX + term.getTermId().replace( ":", "_" ) );
.build( term.getOntology().getName().toUpperCase(), DEFAULT_IRI_PREFIX + term.getTermId().replace( ':', '_' ) );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,14 @@ public Collection<GeneOntologyTermInfo> findAllById( Iterable<String> iterable )
public Stream<GeneOntologyTermInfo> findAllAsStream() {
Lock lock = rwLock.readLock();
lock.lock();
return termsByIdOrAlias.values().stream()
.onClose( lock::unlock )
.distinct();
try {
return termsByIdOrAlias.values().stream()
.onClose( lock::unlock )
.distinct();
} catch ( Throwable t ) {
lock.unlock();
throw t;
}
}

/**
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/ubc/pavlab/rdp/services/GOServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ public Collection<Integer> getGenesInTaxon( String id, Taxon taxon ) {
}
return goRepository.findById( id )
.map( term -> getGenesInTaxon( term, taxon ) )
.orElse( Collections.emptySet() );
.orElseGet( Collections::emptySet );
}

@Override
Expand Down Expand Up @@ -535,7 +535,7 @@ private void evict( Iterable<GeneOntologyTermInfo> terms ) {

private void evictAll() {
log.debug( "Evicting all the terms from ancestors and descendants caches." );
ancestorsCache.clear();
descendantsCache.clear();
ancestorsCache.invalidate();
descendantsCache.invalidate();
}
}
Loading

0 comments on commit a3b5f8c

Please sign in to comment.