Skip to content

Commit

Permalink
Merge branch 'hotfix-1.5.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
arteymix committed Sep 29, 2022
2 parents a3b5f8c + b7f171c commit 38aee1a
Show file tree
Hide file tree
Showing 26 changed files with 188 additions and 55 deletions.
4 changes: 4 additions & 0 deletions docs/customization.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,10 @@ rdp.ontologies.{ontologyName}.terms.{termName}.title
rdp.ontologies.{ontologyName}.terms.{termName}.definition
```

If your ontology/category is based on a [PURL](https://obofoundry.org/principles/fp-003-uris.html) source, its name will
be rendered un uppercase. For example, "uberon" from http://purl.obolibrary.org/obo/uberon.obo will be displayed as
"UBERON". You may override this by setting a custom title as described above.

Note that we provide defaults for Reactome in the JAR package, so you must use custom messages for overriding those
values. A warning will be displayed in the admin section if this is the case.

Expand Down
7 changes: 6 additions & 1 deletion 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.1</version>
<version>1.5.2</version>

<description>
Registry for model organism researchers, developed for the Canadian Rare Disease Models &amp; Mechanisms Network.
Expand Down Expand Up @@ -72,6 +72,11 @@
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
</dependency>
<!-- mentioned explicitly in CacheUtils for removeAll -->
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/ubc/pavlab/rdp/RemoteResourceConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,16 @@ public AsyncRestTemplate remoteResourceRestTemplate( ApplicationSettings applica
SimpleClientHttpRequestFactory httpRequestFactory = new SimpleClientHttpRequestFactory();
httpRequestFactory.setTaskExecutor( new SimpleAsyncTaskExecutor() );
if ( applicationSettings.getIsearch().getRequestTimeout() != null ) {
log.warn( "The 'rdp.settings.isearch.request-timeout' configuration is deprecated." );
httpRequestFactory.setConnectTimeout( 1000 );
httpRequestFactory.setReadTimeout( (int) applicationSettings.getIsearch().getRequestTimeout().toMillis() );
} else {
if ( applicationSettings.getIsearch().getConnectTimeout() != null ) {
httpRequestFactory.setConnectTimeout( (int) applicationSettings.getIsearch().getConnectTimeout().toMillis() );
}
if ( applicationSettings.getIsearch().getReadTimeout() != null ) {
httpRequestFactory.setReadTimeout( (int) applicationSettings.getIsearch().getReadTimeout().toMillis() );
}
}
return new AsyncRestTemplate( httpRequestFactory );
}
Expand Down
8 changes: 8 additions & 0 deletions src/main/java/ubc/pavlab/rdp/model/GeneOntologyTermInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ public static Comparator<GeneOntologyTermInfo> getComparator() {
@JsonIgnore
private MultiValueMap<Integer, Integer> directGeneIdsByTaxonId = new LinkedMultiValueMap<>();

/**
* Alias for {@link #getGoId()}.
*/
@JsonIgnore
public String getId() {
return getGoId();
}

/**
* Obtain the size of the term as a number of genes in a taxon.
* <p>
Expand Down
17 changes: 17 additions & 0 deletions src/main/java/ubc/pavlab/rdp/model/Organ.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@
import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.annotations.NaturalId;
import org.springframework.context.MessageSourceResolvable;
import org.springframework.context.support.DefaultMessageSourceResolvable;

import javax.persistence.Column;
import javax.persistence.Lob;
Expand All @@ -28,4 +31,18 @@ public abstract class Organ {
@Lob
@Column(columnDefinition = "TEXT")
private String description;

/**
* Obtain a resolvable title for this organ system.
*/
public MessageSourceResolvable resolvableTitle() {
return new DefaultMessageSourceResolvable( new String[]{ "rdp.ontologies.uberon." + name + ".title" }, null, StringUtils.capitalize( name ) );
}

/**
* Obtain a resolvable definition for this organ system.
*/
public MessageSourceResolvable resolvableDefinition() {
return new DefaultMessageSourceResolvable( new String[]{ "rdp.ontologies.uberon." + name + ".definition" }, null, description );
}
}
4 changes: 4 additions & 0 deletions src/main/java/ubc/pavlab/rdp/model/Profile.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.SchemaProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
Expand Down Expand Up @@ -87,10 +89,12 @@ public String getFullName() {
@Column(name = "privacy_level")
private PrivacyLevelType privacyLevel;

@Schema(hidden = true)
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
@Column(name = "shared", nullable = false)
private boolean shared;

@Schema(hidden = true)
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
@Column(name = "hide_genelist", nullable = false)
private boolean hideGenelist;
Expand Down
8 changes: 6 additions & 2 deletions src/main/java/ubc/pavlab/rdp/model/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonUnwrapped;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.SchemaProperty;
import lombok.*;
import lombok.extern.apachecommons.CommonsLog;
import org.hibernate.annotations.CacheConcurrencyStrategy;
Expand Down Expand Up @@ -63,7 +65,9 @@ public static UserBuilder builder( Profile profile ) {
}

public static Comparator<User> getComparator() {
return Comparator.comparing( u -> u.getProfile().getFullName() );
return Comparator.comparing( ( User u ) -> u.getProfile().getFullName() )
.thenComparing( User::getEmail )
.thenComparing( User::getOriginUrl );
}

@Id
Expand Down Expand Up @@ -109,7 +113,7 @@ public static Comparator<User> getComparator() {
private Timestamp modifiedAt;

@Column(name = "enabled", nullable = false)
@JsonIgnore
@Schema(description = "This is deprecated: users exposed through the API are always enabled.", deprecated = true)
private boolean enabled;

/**
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/ubc/pavlab/rdp/model/UserGene.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.hibernate.annotations.NaturalId;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import org.springframework.lang.Nullable;
import ubc.pavlab.rdp.model.enums.PrivacyLevelType;
import ubc.pavlab.rdp.model.enums.TierType;

Expand Down Expand Up @@ -61,6 +62,8 @@ public static UserGeneBuilder builder( User user ) {
public static Comparator<UserGene> getComparator() {
return Comparator.comparing( UserGene::getTaxon, Taxon.getComparator() )
.thenComparing( UserGene::getTier )
.thenComparing( UserGene::getSymbol )
.thenComparing( UserGene::getGeneId )
.thenComparing( UserGene::getUser, User.getComparator() );
}

Expand Down Expand Up @@ -101,6 +104,7 @@ public static Comparator<UserGene> getComparator() {
@JsonIgnore
private Timestamp createdAt;

@Nullable
@ManyToOne
@JoinColumn(name = "gene_id", referencedColumnName = "gene_id", insertable = false, updatable = false, foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT))
@JsonIgnore
Expand Down
19 changes: 16 additions & 3 deletions src/main/java/ubc/pavlab/rdp/model/ontology/Ontology.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import java.util.SortedSet;
import java.util.TreeSet;

import static ubc.pavlab.rdp.util.PurlUtils.isPurl;

/**
* An ontology of terms.
*
Expand Down Expand Up @@ -127,11 +129,21 @@ public int compareTo( Ontology ontology ) {
/**
* Obtain a resolvable for the title of this ontology.
* <p>
* The default value is the upper case {@link #name}.
* The default value is the upper case {@link #name} if {@link #ontologyUrl} is set and is a
* <a href="https://obofoundry.org/principles/fp-003-uris.html">PURL</a>.
*
* @see ubc.pavlab.rdp.util.PurlUtils#isPurl(URL)
*/
@JsonIgnore
public DefaultMessageSourceResolvable getResolvableTitle() {
return new DefaultMessageSourceResolvable( new String[]{ "rdp.ontologies." + Ontology.this.getName() + ".title" }, name.toUpperCase() );
String defaultMessage;
if ( ontologyUrl != null && isPurl( ontologyUrl ) ) {
// this implies that the name is pulled from the OBO format, so its default value is not suitable for display
defaultMessage = name.toUpperCase();
} else {
defaultMessage = name;
}
return new DefaultMessageSourceResolvable( new String[]{ "rdp.ontologies." + name + ".title" }, defaultMessage );
}

/**
Expand All @@ -141,7 +153,8 @@ public DefaultMessageSourceResolvable getResolvableTitle() {
* when calling {@link org.springframework.context.MessageSource#getMessage(MessageSourceResolvable, Locale)}.
*/
@JsonIgnore

public DefaultMessageSourceResolvable getResolvableDefinition() {
return new DefaultMessageSourceResolvable( new String[]{ "rdp.ontologies." + Ontology.this.getName() + ".definition" }, definition );
return new DefaultMessageSourceResolvable( new String[]{ "rdp.ontologies." + name + ".definition" }, definition );
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import org.springframework.lang.Nullable;
import ubc.pavlab.rdp.model.User;
import ubc.pavlab.rdp.model.UserContent;
import ubc.pavlab.rdp.model.enums.PrivacyLevelType;
Expand Down Expand Up @@ -63,6 +64,7 @@ public static UserOntologyTerm fromOntologyTermInfo( User user, OntologyTermInfo
/**
* Original term from which this user term derived, if still available otherwise null.
*/
@Nullable
@ManyToOne
@JoinColumns(value = {
@JoinColumn(name = "ontology_id", referencedColumnName = "ontology_id", insertable = false, updatable = false),
Expand Down
17 changes: 5 additions & 12 deletions src/main/java/ubc/pavlab/rdp/services/GOServiceImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -517,25 +517,18 @@ private void evict( Iterable<GeneOntologyTermInfo> terms ) {
.collect( Collectors.toSet() );

// evict the terms from both caches
for ( GeneOntologyTermInfo term : termsToEvict ) {
ancestorsCache.evict( term );
descendantsCache.evict( term );
}
CacheUtils.evictAll( descendantsCache, termsToEvict );

// all the ancestors mention one of the updated terms in their descendants, so we evict those
for ( GeneOntologyTermInfo ancestor : ancestors ) {
descendantsCache.evict( ancestor );
}
CacheUtils.evictAll( descendantsCache, ancestors );

// conversely, all the descendants mention one of the updated term in their ancestors
for ( GeneOntologyTermInfo descendant : descendants ) {
ancestorsCache.evict( descendant );
}
CacheUtils.evictAll( ancestorsCache, descendants );
}

private void evictAll() {
log.debug( "Evicting all the terms from ancestors and descendants caches." );
ancestorsCache.invalidate();
descendantsCache.invalidate();
ancestorsCache.clear();
descendantsCache.clear();
}
}
14 changes: 14 additions & 0 deletions src/main/java/ubc/pavlab/rdp/settings/ApplicationSettings.java
Original file line number Diff line number Diff line change
Expand Up @@ -217,9 +217,23 @@ public static class InternationalSearchSettings {
* <p>
* When formatted as a number, it is interpreted as a number of seconds. You may also use a unit suffix (i.e. '100ms')
* to specify a precise amount of time.
*
* @deprecated use {@link #connectTimeout} and {@link #readTimeout} instead which provide more granularity in
* defining the timeout.
*/
@Deprecated
@DurationUnit(value = ChronoUnit.SECONDS)
private Duration requestTimeout;
/**
* Connection timeout in milliseconds, or null to disable.
*/
@DurationUnit(value = ChronoUnit.MILLIS)
private Duration connectTimeout;
/**
* Read timeout in milliseconds, or null to disable.
*/
@DurationUnit(value = ChronoUnit.MILLIS)
private Duration readTimeout;
}

@Data
Expand Down
22 changes: 22 additions & 0 deletions src/main/java/ubc/pavlab/rdp/util/CacheUtils.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
package ubc.pavlab.rdp.util;

import net.sf.ehcache.Ehcache;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;

import java.util.Collection;
import java.util.Map;

/**
* Utilities for working with {@link CacheManager} and {@link Cache}.
*
Expand All @@ -25,4 +29,22 @@ public static Cache getCache( CacheManager cacheManager, String cacheName ) thro
}
return cache;
}

/**
* Evict all the given keys from the cache.
* <p>
* This takes advantage of cache-specific collection eviction such as {@link Ehcache#removeAll(Collection)}.
*
* @param cache cache from which keys are evicte
* @param keys keys to be evicted
*/
public static void evictAll( Cache cache, Collection<?> keys ) {
if ( cache.getNativeCache() instanceof Ehcache ) {
( (Ehcache) cache.getNativeCache() ).removeAll( keys );
} else {
for ( Object key : keys ) {
cache.evict( key );
}
}
}
}
7 changes: 4 additions & 3 deletions src/main/java/ubc/pavlab/rdp/util/PurlResolver.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,19 +18,20 @@
import java.net.MalformedURLException;
import java.net.URL;

import static ubc.pavlab.rdp.util.PurlUtils.isPurl;

/**
* Resolve resources from <a href="http://purl.obolibrary.org">purl.obolibrary.org</a>.
*
* @author poirigui
* @see PurlUtils
*/
@CommonsLog
public class PurlResolver implements ProtocolResolver {

private static final String PURL_PREFIX = "http://purl.obolibrary.org";

@Override
public Resource resolve( String location, ResourceLoader resourceLoader ) {
if ( !location.startsWith( PURL_PREFIX ) ) {
if ( !isPurl( location ) ) {
return null;
}

Expand Down
19 changes: 19 additions & 0 deletions src/main/java/ubc/pavlab/rdp/util/PurlUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package ubc.pavlab.rdp.util;

import java.net.URL;

/**
* Utilities to operate with <a href="https://obofoundry.org/principles/fp-003-uris.html">PURL</a>.
*/
public class PurlUtils {

private static final String PURL_PREFIX = "http://purl.obolibrary.org";

public static boolean isPurl( String url ) {
return url.startsWith( PURL_PREFIX );
}

public static boolean isPurl( URL url ) {
return isPurl( url.toExternalForm() );
}
}
5 changes: 3 additions & 2 deletions src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,9 @@ rdp.settings.isearch.user-id=
#rdp.settings.isearch.search-token=
## Tokens for remote requests that authorize administrative access. Usually equal to the search-token, but can contain multiple entries separated by comma.
rdp.settings.isearch.auth-tokens=
## Timeout in seconds for remote search so that slow partners have limited incidence on search result speed.
rdp.settings.isearch.request-timeout=3
## Timeout in milliseconds for remote search connection and read so that slow partners have limited incidence on search result speed
rdp.settings.isearch.connect-timeout=1000
rdp.settings.isearch.read-timeout=3000

# ontology settings
rdp.settings.ontology.enabled=true
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/static/js/model.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@
}
row.push('<span class="align-middle">' +
'<a href="https://www.ebi.ac.uk/QuickGO/GTerm?id=' + encodeURIComponent(term.goId) + '" ' +
'target="_blank" rel="noopener" data-toggle="tooltip" class="align-middle" title="' + term.definition + '">' + term.goId + '</a></span>');
'target="_blank" rel="noopener" data-toggle="tooltip" data-boundary="window" class="align-middle" title="' + term.definition + '">' + term.goId + '</a></span>');
row.push('<span class="align-middle">' + term.name + '</span>');
row.push('<span class="align-middle">' + term.aspect + '</span>');
row.push('<a href="#" class="align-middle overlap-show-modal" data-toggle="modal" data-target="#overlapModal" data-go-id="' + term.goId + '">' + term.frequency + '</a>');
Expand Down
Loading

0 comments on commit 38aee1a

Please sign in to comment.