From 12808b7f06a3a7bebbf2122b4fd9c7887b8bd5b4 Mon Sep 17 00:00:00 2001 From: Guillaume Poirier-Morency Date: Tue, 6 Dec 2022 12:24:58 -0800 Subject: [PATCH 01/12] Update versions for hotfix --- gemma-cli/pom.xml | 2 +- gemma-core/pom.xml | 2 +- gemma-web/pom.xml | 2 +- pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gemma-cli/pom.xml b/gemma-cli/pom.xml index 05e17d74ff..2645c20d84 100644 --- a/gemma-cli/pom.xml +++ b/gemma-cli/pom.xml @@ -3,7 +3,7 @@ gemma gemma - 1.29.1 + 1.29.2 4.0.0 gemma-cli diff --git a/gemma-core/pom.xml b/gemma-core/pom.xml index 8974134286..97291c4d55 100644 --- a/gemma-core/pom.xml +++ b/gemma-core/pom.xml @@ -3,7 +3,7 @@ gemma gemma - 1.29.1 + 1.29.2 4.0.0 gemma-core diff --git a/gemma-web/pom.xml b/gemma-web/pom.xml index 73c92aa464..0ecbe24634 100644 --- a/gemma-web/pom.xml +++ b/gemma-web/pom.xml @@ -3,7 +3,7 @@ gemma gemma - 1.29.1 + 1.29.2 4.0.0 gemma-web diff --git a/pom.xml b/pom.xml index 84e46fee61..2e7b508e10 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ Gemma gemma gemma - 1.29.1 + 1.29.2 2005 The Gemma Project for meta-analysis of genomics data https://gemma.msl.ubc.ca From 6220852f278db77654bbcd94abf4229c99ad6387 Mon Sep 17 00:00:00 2001 From: Guillaume Poirier-Morency Date: Tue, 6 Dec 2022 12:05:24 -0800 Subject: [PATCH 02/12] Fix negative limit inverting the sort direction for the dataset manager --- .../ExpressionExperimentServiceImpl.java | 2 +- .../ExpressionExperimentController.java | 18 +++++++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentServiceImpl.java b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentServiceImpl.java index 6d43127bdc..d0f55c8ec8 100755 --- a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentServiceImpl.java +++ b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentServiceImpl.java @@ -839,7 +839,7 @@ public boolean isTroubled( ExpressionExperiment ee ) { @Override @Transactional(readOnly = true) - public Slice loadDetailsValueObjects( Collection ids, @Nullable Taxon taxon, @Nullable Sort sort, int offset, int limit ) { + public Slice loadDetailsValueObjects( @Nullable Collection ids, @Nullable Taxon taxon, @Nullable Sort sort, int offset, int limit ) { return this.expressionExperimentDao.loadDetailsValueObjectsByIds( ids, taxon, sort, offset, limit ); } diff --git a/gemma-web/src/main/java/ubic/gemma/web/controller/expression/experiment/ExpressionExperimentController.java b/gemma-web/src/main/java/ubic/gemma/web/controller/expression/experiment/ExpressionExperimentController.java index 7e7a7c6b5c..30fc00bc70 100644 --- a/gemma-web/src/main/java/ubic/gemma/web/controller/expression/experiment/ExpressionExperimentController.java +++ b/gemma-web/src/main/java/ubic/gemma/web/controller/expression/experiment/ExpressionExperimentController.java @@ -699,11 +699,8 @@ public Collection loadExperimentsForPlat */ public Collection loadDetailedExpressionExperiments( Collection ids ) { - if ( ids.isEmpty() ) { - return new HashSet<>(); - } Collection result = this - .getFilteredExpressionExperimentValueObjects( null, null, 0, true ); + .getFilteredExpressionExperimentValueObjects( null, ids, 0, true ); this.expressionExperimentReportService.populateReportInformation( result ); return result; } @@ -782,7 +779,7 @@ public Collection loadStatusSummaries( L } // -1 is used in the frontend as a substitute for null - if ( taxonId == -1L ) { + if ( taxonId != null && taxonId == -1L ) { taxonId = null; } @@ -1522,6 +1519,10 @@ private Collection getEEVOsForManager( L taxon = null; } + if ( limit == null ) { + limit = 0; + } + // Limit default desc - lastUpdated is a date and the most recent date is the largest one. eeVos = this .getFilteredExpressionExperimentValueObjects( taxon, ids, limit, showPublic ); @@ -1605,10 +1606,13 @@ private Collection getExpressionExperimentSe * @return Collection */ private Collection getFilteredExpressionExperimentValueObjects( Taxon taxon, - Collection eeIds, Integer limit, boolean showPublic ) { + Collection eeIds, int limit, boolean showPublic ) { + Sort.Direction direction = limit < 0 ? Sort.Direction.ASC : Sort.Direction.DESC; Slice vos = expressionExperimentService - .loadDetailsValueObjects( eeIds, taxon, expressionExperimentService.getSort( "curationDetails.lastUpdated", Sort.Direction.DESC ), 0, Math.abs( limit ) ); + .loadDetailsValueObjects( eeIds, taxon, + expressionExperimentService.getSort( "curationDetails.lastUpdated", direction ), + 0, Math.abs( limit ) ); // Hide public data sets if desired. if ( !vos.isEmpty() && !showPublic ) { Collection publicEEs = securityService.choosePublic( vos ); From 330271c617fb82cd6c308b12009f468df487a49d Mon Sep 17 00:00:00 2001 From: Guillaume Poirier-Morency Date: Tue, 6 Dec 2022 13:33:13 -0800 Subject: [PATCH 03/12] Fix missing return of an empty slice when no dataset IDs are supplied --- .../expression/experiment/ExpressionExperimentDaoImpl.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentDaoImpl.java b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentDaoImpl.java index 75ed6b9afc..b130418c71 100644 --- a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentDaoImpl.java +++ b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentDaoImpl.java @@ -1114,8 +1114,9 @@ public Slice loadDetailsValueObjectsById Filters filters = new Filters(); if ( ids != null ) { - if ( ids.isEmpty() ) - Slice.empty(); + if ( ids.isEmpty() ) { + return Slice.empty(); + } List idList = new ArrayList<>( ids ); Collections.sort( idList ); filters.add( new ObjectFilter( getObjectAlias(), "id", Long.class, ObjectFilter.Operator.in, idList ) ); From b026a94d0a9b123d1ff0cba26186cdc0b9605b85 Mon Sep 17 00:00:00 2001 From: Guillaume Poirier-Morency Date: Wed, 7 Dec 2022 09:39:01 -0800 Subject: [PATCH 04/12] Fix incorrectly bound 'threshold' parameter when retrieving top hits (fix #512) --- .../expression/diff/DifferentialExpressionResultDaoImpl.java | 1 - 1 file changed, 1 deletion(-) diff --git a/gemma-core/src/main/java/ubic/gemma/persistence/service/analysis/expression/diff/DifferentialExpressionResultDaoImpl.java b/gemma-core/src/main/java/ubic/gemma/persistence/service/analysis/expression/diff/DifferentialExpressionResultDaoImpl.java index 4d0b60a01c..bfcd82b62b 100644 --- a/gemma-core/src/main/java/ubic/gemma/persistence/service/analysis/expression/diff/DifferentialExpressionResultDaoImpl.java +++ b/gemma-core/src/main/java/ubic/gemma/persistence/service/analysis/expression/diff/DifferentialExpressionResultDaoImpl.java @@ -543,7 +543,6 @@ public List findInResultSet( ExpressionAnalys qs = DifferentialExpressionResultDaoImpl.fetchResultsBySingleResultSetQuery + " order by r.correctedPvalue"; qResult = getSessionFactory().getCurrentSession().createQuery( qs ) .setParameterList( "resultsSets", resultsSets ) - .setParameter( "threshold", threshold ) .setMaxResults( minNumberOfResults ) .list(); } From f3003c0593cdc21bb55d126076e03a17ac204590 Mon Sep 17 00:00:00 2001 From: Guillaume Poirier-Morency Date: Wed, 7 Dec 2022 10:00:47 -0800 Subject: [PATCH 05/12] Use a simple equality for fetching result set results --- .../diff/DifferentialExpressionResultDaoImpl.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/gemma-core/src/main/java/ubic/gemma/persistence/service/analysis/expression/diff/DifferentialExpressionResultDaoImpl.java b/gemma-core/src/main/java/ubic/gemma/persistence/service/analysis/expression/diff/DifferentialExpressionResultDaoImpl.java index bfcd82b62b..578e54f30e 100644 --- a/gemma-core/src/main/java/ubic/gemma/persistence/service/analysis/expression/diff/DifferentialExpressionResultDaoImpl.java +++ b/gemma-core/src/main/java/ubic/gemma/persistence/service/analysis/expression/diff/DifferentialExpressionResultDaoImpl.java @@ -107,7 +107,7 @@ public class DifferentialExpressionResultDaoImpl extends AbstractDao findInResultSet( ExpressionAnalys // get it. - Collection resultsSets = new ArrayList<>(); - resultsSets.add( resultSet ); - StopWatch timer = new StopWatch(); timer.start(); String qs = DifferentialExpressionResultDaoImpl.fetchResultsBySingleResultSetQuery + " and r.correctedPvalue <= :threshold order by r.correctedPvalue"; List qResult = getSessionFactory().getCurrentSession().createQuery( qs ) - .setParameterList( "resultsSets", resultsSets ) + .setParameter( "resultSet", resultSet ) .setParameter( "threshold", threshold ) .setMaxResults( limit ) .list(); @@ -542,7 +539,7 @@ public List findInResultSet( ExpressionAnalys AbstractDao.log.info( "No results met threshold, repeating to just get the top hits" ); qs = DifferentialExpressionResultDaoImpl.fetchResultsBySingleResultSetQuery + " order by r.correctedPvalue"; qResult = getSessionFactory().getCurrentSession().createQuery( qs ) - .setParameterList( "resultsSets", resultsSets ) + .setParameter( "resultSet", resultSet ) .setMaxResults( minNumberOfResults ) .list(); } From 603b4def2a5391aad400eda1e3339e55acf15df2 Mon Sep 17 00:00:00 2001 From: Guillaume Poirier-Morency Date: Thu, 8 Dec 2022 11:13:32 -0800 Subject: [PATCH 06/12] Add missing default constructor in TaxonValueObject (fix #513) --- .../ubic/gemma/model/genome/TaxonValueObject.java | 4 ++++ .../gemma/model/genome/TaxonValueObjectTest.java | 13 +++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 gemma-core/src/test/java/ubic/gemma/model/genome/TaxonValueObjectTest.java diff --git a/gemma-core/src/main/java/ubic/gemma/model/genome/TaxonValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/genome/TaxonValueObject.java index a24b1ccab0..a0444ddb97 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/genome/TaxonValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/genome/TaxonValueObject.java @@ -35,6 +35,10 @@ public class TaxonValueObject extends IdentifiableValueObject implements private Boolean isGenesUsable; private ExternalDatabaseValueObject externalDatabase; + public TaxonValueObject() { + super(); + } + public TaxonValueObject( Taxon taxon ) { super( taxon.getId() ); this.setScientificName( taxon.getScientificName() ); diff --git a/gemma-core/src/test/java/ubic/gemma/model/genome/TaxonValueObjectTest.java b/gemma-core/src/test/java/ubic/gemma/model/genome/TaxonValueObjectTest.java new file mode 100644 index 0000000000..ce2480d560 --- /dev/null +++ b/gemma-core/src/test/java/ubic/gemma/model/genome/TaxonValueObjectTest.java @@ -0,0 +1,13 @@ +package ubic.gemma.model.genome; + +import org.junit.Test; + +import static org.junit.Assert.*; + +public class TaxonValueObjectTest { + + @Test + public void testDefaultNoArgConstructor() throws InstantiationException, IllegalAccessException { + TaxonValueObject tvo = TaxonValueObject.class.newInstance(); + } +} \ No newline at end of file From 3ec91e7d84bf10ea114cbc3859c17c1af40974c0 Mon Sep 17 00:00:00 2001 From: Guillaume Poirier-Morency Date: Thu, 8 Dec 2022 12:09:12 -0800 Subject: [PATCH 07/12] Fix incorrect result type for phenotype search results (fix #511) --- .../java/ubic/gemma/core/search/SearchResult.java | 15 +++++++++++++++ .../ubic/gemma/core/search/SearchServiceImpl.java | 2 +- .../controller/GeneralSearchControllerImpl.java | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/gemma-core/src/main/java/ubic/gemma/core/search/SearchResult.java b/gemma-core/src/main/java/ubic/gemma/core/search/SearchResult.java index 5d370dea8f..5eaf6ec49b 100644 --- a/gemma-core/src/main/java/ubic/gemma/core/search/SearchResult.java +++ b/gemma-core/src/main/java/ubic/gemma/core/search/SearchResult.java @@ -55,6 +55,21 @@ public static SearchResult from( T entity, double sc return sr; } + /** + * Create a search result whose result class differ from the object. + *

+ * This can be useful if you wrap a proxy, or don't want to expose the object class publicly. For example, our + * {@link ubic.gemma.model.association.phenotype.PhenotypeAssociation} use a {@link ubic.gemma.model.genome.gene.phenotype.valueObject.CharacteristicValueObject} + * for the result object. + */ + public static SearchResult from( Class resultClass, T entity, double score, @Nullable String highlightedText, Object source ) { + SearchResult sr = new SearchResult<>( resultClass, entity.getId(), source ); + sr.setResultObject( entity ); + sr.setScore( score ); + sr.setHighlightedText( highlightedText ); + return sr; + } + /** * Create a search result from an existing one, replacing the result object with the target one. *

diff --git a/gemma-core/src/main/java/ubic/gemma/core/search/SearchServiceImpl.java b/gemma-core/src/main/java/ubic/gemma/core/search/SearchServiceImpl.java index 77e75104cd..6626619acb 100644 --- a/gemma-core/src/main/java/ubic/gemma/core/search/SearchServiceImpl.java +++ b/gemma-core/src/main/java/ubic/gemma/core/search/SearchServiceImpl.java @@ -450,7 +450,7 @@ private Collection> searchPhenotype( Sea // FIXME: add support for OR, but there's a bug in baseCode that prevents this https://github.com/PavlidisLab/baseCode/issues/22 String query = settings.getQuery().replaceAll( "\\s+OR\\s+", "" ); return this.phenotypeAssociationManagerService.searchInDatabaseForPhenotype( query ).stream() - .map( r -> SearchResult.from( r, 1.0, null, "PhenotypeAssociationManagerService.searchInDatabaseForPhenotype" ) ) + .map( r -> SearchResult.from( PhenotypeAssociation.class, r, 1.0, null, "PhenotypeAssociationManagerService.searchInDatabaseForPhenotype" ) ) .collect( Collectors.toSet() ); } catch ( OntologySearchException e ) { throw new BaseCodeOntologySearchException( "Failed to search for phenotype associations.", e ); diff --git a/gemma-web/src/main/java/ubic/gemma/web/controller/GeneralSearchControllerImpl.java b/gemma-web/src/main/java/ubic/gemma/web/controller/GeneralSearchControllerImpl.java index b7351045f2..a5058c6864 100644 --- a/gemma-web/src/main/java/ubic/gemma/web/controller/GeneralSearchControllerImpl.java +++ b/gemma-web/src/main/java/ubic/gemma/web/controller/GeneralSearchControllerImpl.java @@ -331,7 +331,7 @@ private void fillValueObjects( Class entityClass, List> resul Collection genes = geneService.load( ids ); genes = geneService.thawLite( genes ); vos = geneService.loadValueObjects( genes ); - } else if ( CharacteristicValueObject.class.isAssignableFrom( entityClass ) ) { + } else if ( PhenotypeAssociation.class.isAssignableFrom( entityClass ) ) { // This is used for phenotypes. Collection cvos = new ArrayList<>(); for ( SearchResult sr : results ) { From ff73ad2a5add7ebdf7bda7d80efaf90f62ec3f99 Mon Sep 17 00:00:00 2001 From: Guillaume Poirier-Morency Date: Sat, 10 Dec 2022 15:06:41 -0800 Subject: [PATCH 08/12] Add support for filtering platform by taxon --- .../AbstractFilteringVoEnabledService.java | 48 +++++------- .../arrayDesign/ArrayDesignServiceImpl.java | 16 ++++ .../ExpressionExperimentServiceImpl.java | 44 +++-------- .../arrayDesign/ArrayDesignServiceTest.java | 76 +++++++++++++++++++ 4 files changed, 122 insertions(+), 62 deletions(-) create mode 100644 gemma-core/src/test/java/ubic/gemma/persistence/service/expression/arrayDesign/ArrayDesignServiceTest.java diff --git a/gemma-core/src/main/java/ubic/gemma/persistence/service/AbstractFilteringVoEnabledService.java b/gemma-core/src/main/java/ubic/gemma/persistence/service/AbstractFilteringVoEnabledService.java index 19e2e0f70d..0e31d8d672 100644 --- a/gemma-core/src/main/java/ubic/gemma/persistence/service/AbstractFilteringVoEnabledService.java +++ b/gemma-core/src/main/java/ubic/gemma/persistence/service/AbstractFilteringVoEnabledService.java @@ -1,5 +1,6 @@ package ubic.gemma.persistence.service; +import lombok.Value; import org.springframework.transaction.annotation.Transactional; import ubic.gemma.model.IdentifiableValueObject; import ubic.gemma.model.common.Identifiable; @@ -25,7 +26,8 @@ protected AbstractFilteringVoEnabledService( FilteringVoEnabledDao voDao @Override public ObjectFilter getObjectFilter( String property, ObjectFilter.Operator operator, String value ) { try { - return ObjectFilter.parseObjectFilter( getPropertyAlias( property ), getPropertyName( property ), getPropertyType( property ), operator, value ); + ObjectFilterPropertyMeta propertyMeta = getObjectFilterPropertyMeta( property ); + return ObjectFilter.parseObjectFilter( propertyMeta.objectAlias, propertyMeta.propertyName, propertyMeta.propertyType, operator, value ); } catch ( NoSuchFieldException e ) { throw new IllegalArgumentException( "Could not create object filter for " + property + " on " + voDao.getElementClass().getName() + ".", e ); } @@ -34,7 +36,8 @@ public ObjectFilter getObjectFilter( String property, ObjectFilter.Operator oper @Override public ObjectFilter getObjectFilter( String property, ObjectFilter.Operator operator, Collection values ) { try { - return ObjectFilter.parseObjectFilter( getPropertyAlias( property ), getPropertyName( property ), getPropertyType( property ), operator, values ); + ObjectFilterPropertyMeta propertyMeta = getObjectFilterPropertyMeta( property ); + return ObjectFilter.parseObjectFilter( propertyMeta.objectAlias, propertyMeta.propertyName, propertyMeta.propertyType, operator, values ); } catch ( NoSuchFieldException e ) { throw new IllegalArgumentException( "Could not create object filter for " + property + " on " + voDao.getElementClass().getName() + ".", e ); } @@ -44,7 +47,8 @@ public ObjectFilter getObjectFilter( String property, ObjectFilter.Operator oper public Sort getSort( String property, @Nullable Sort.Direction direction ) { // this only serves as a pre-condition to ensure that the propertyName exists try { - return Sort.by( getPropertyAlias( property ), getPropertyName( property ), direction ); + ObjectFilterPropertyMeta propertyMeta = getObjectFilterPropertyMeta( property ); + return Sort.by( propertyMeta.objectAlias, propertyMeta.propertyName, direction ); } catch ( NoSuchFieldException e ) { throw new IllegalArgumentException( String.format( "Could not resolve propertyName '%s' on %s.", property, voDao.getElementClass().getName() ), e ); } @@ -62,39 +66,25 @@ public List loadValueObjectsPreFilter( @Nullable Filters filters, @Nullable return voDao.loadValueObjectsPreFilter( filters, sort ); } - /** - * Obtain the alias that refers to the entity. - * - * Defaults to {@link FilteringVoEnabledDao#getElementClass()}. - * - * @throws NoSuchFieldException if no such propertyName exists in {@link O} - */ - protected String getPropertyAlias( String propertyName ) throws NoSuchFieldException { - EntityUtils.getDeclaredField( voDao.getElementClass(), propertyName ); - return voDao.getObjectAlias(); + @Value + protected static class ObjectFilterPropertyMeta { + String objectAlias; + String propertyName; + Class propertyType; } /** - * Obtain the propertyName on {@link O} that correspond to the passed propertyName name. + * Obtain various meta-information used to infer what to use in a {@link ObjectFilter} or {@link Sort}. * - * Defaults to the propertyName name itself. + * This is used by {@link #getObjectFilter(String, ObjectFilter.Operator, String)} and {@link #getSort(String, Sort.Direction)}. * * @throws NoSuchFieldException if no such propertyName exists in {@link O} + * @see #getObjectFilter(String, ObjectFilter.Operator, String) + * @see #getObjectFilter(String, ObjectFilter.Operator, Collection) + * @see #getSort(String, Sort.Direction) */ - protected String getPropertyName( String propertyName ) throws NoSuchFieldException { + protected ObjectFilterPropertyMeta getObjectFilterPropertyMeta( String propertyName ) throws NoSuchFieldException { EntityUtils.getDeclaredField( voDao.getElementClass(), propertyName ); - return propertyName; - } - - /** - * Obtain the propertyName type on {@link O} that correspond to the passed propertyName name. - * - * Defaults to {@link EntityUtils#getDeclaredFieldType(String, Class)} invoked with {@link #getPropertyName(String)} - * and {@link FilteringVoEnabledDao#getElementClass()}. - * - * @throws NoSuchFieldException if no such propertyName exists in {@link O} - */ - protected Class getPropertyType( String propertyName ) throws NoSuchFieldException { - return EntityUtils.getDeclaredFieldType( getPropertyName( propertyName ), voDao.getElementClass() ); + return new ObjectFilterPropertyMeta( voDao.getObjectAlias(), propertyName, EntityUtils.getDeclaredFieldType( propertyName, voDao.getElementClass() ) ); } } diff --git a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/arrayDesign/ArrayDesignServiceImpl.java b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/arrayDesign/ArrayDesignServiceImpl.java index dff9f78ca1..975a02d325 100644 --- a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/arrayDesign/ArrayDesignServiceImpl.java +++ b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/arrayDesign/ArrayDesignServiceImpl.java @@ -30,6 +30,7 @@ import ubic.gemma.persistence.service.AbstractFilteringVoEnabledService; import ubic.gemma.persistence.service.common.auditAndSecurity.AuditEventDao; import ubic.gemma.persistence.service.expression.experiment.BlacklistedEntityService; +import ubic.gemma.persistence.util.EntityUtils; import java.util.*; @@ -418,6 +419,21 @@ public Boolean updateSubsumingStatus( ArrayDesign candidateSubsumer, ArrayDesign return this.arrayDesignDao.updateSubsumingStatus( candidateSubsumer, candidateSubsumee ); } + @Override + protected ObjectFilterPropertyMeta getObjectFilterPropertyMeta( String propertyName ) throws NoSuchFieldException { + // handle cases such as taxon = 1 + if ( propertyName.equals( "taxon" ) ) { + return new ObjectFilterPropertyMeta( "t", "id", Long.class ); + } + // handles taxon.{propertyName} {op} {value} + else if ( propertyName.startsWith( "taxon." ) ) { + String fieldName = propertyName.replaceFirst( "^taxon\\.", "" ); + return new ObjectFilterPropertyMeta( "t", fieldName, EntityUtils.getDeclaredFieldType( fieldName, Taxon.class ) ); + } else { + return super.getObjectFilterPropertyMeta( propertyName ); + } + } + private void checkForMoreRecentMethod( Map lastEventMap, Class eventclass, Long arrayDesignId, ArrayDesign subsumedInto ) { AuditEvent lastSubsumerEvent = this.auditEventDao.getLastEvent( subsumedInto, eventclass ); diff --git a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentServiceImpl.java b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentServiceImpl.java index d0f55c8ec8..cefc29617d 100755 --- a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentServiceImpl.java +++ b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentServiceImpl.java @@ -20,7 +20,6 @@ import com.google.common.base.Strings; import gemma.gsec.SecurityService; -import lombok.Data; import org.apache.commons.math3.exception.NotStrictlyPositiveException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -1128,58 +1127,37 @@ public Collection getExperimentsLackingPublications() { * {@inheritDoc} */ @Override - protected String getPropertyAlias( String propertyName ) throws NoSuchFieldException { - return getAliasForProperty( propertyName ).objectAlias; - } - - @Override - protected String getPropertyName( String propertyName ) throws NoSuchFieldException { - return getAliasForProperty( propertyName ).propertyName; - } - - @Override - protected Class getPropertyType( String propertyName ) throws NoSuchFieldException { - return getAliasForProperty( propertyName ).propertyType; - } - - private AliasPropertyNameType getAliasForProperty( String propertyName ) throws NoSuchFieldException { + protected ObjectFilterPropertyMeta getObjectFilterPropertyMeta( String propertyName ) throws NoSuchFieldException { if ( propertyName.startsWith( "characteristics." ) ) { - String fieldName = propertyName.replaceFirst( "characteristics.", "" ); - return new AliasPropertyNameType( CharacteristicDao.OBJECT_ALIAS, fieldName, EntityUtils.getDeclaredFieldType( fieldName, Characteristic.class ) ); + String fieldName = propertyName.replaceFirst( "^characteristics\\.", "" ); + return new ObjectFilterPropertyMeta( CharacteristicDao.OBJECT_ALIAS, fieldName, EntityUtils.getDeclaredFieldType( fieldName, Characteristic.class ) ); } if ( propertyName.startsWith( "bioAssays." ) ) { - String fieldName = propertyName.replaceFirst( "bioAssays.", "" ); - return new AliasPropertyNameType( BioAssayDao.OBJECT_ALIAS, fieldName, EntityUtils.getDeclaredFieldType( fieldName, BioAssay.class ) ); + String fieldName = propertyName.replaceFirst( "^bioAssays\\.", "" ); + return new ObjectFilterPropertyMeta( BioAssayDao.OBJECT_ALIAS, fieldName, EntityUtils.getDeclaredFieldType( fieldName, BioAssay.class ) ); } if ( propertyName.equals( "taxon" ) ) { - return new AliasPropertyNameType( TaxonDao.OBJECT_ALIAS, "id", Long.class ); + return new ObjectFilterPropertyMeta( TaxonDao.OBJECT_ALIAS, "id", Long.class ); } if ( propertyName.equals( "bioAssayCount" ) ) { - return new AliasPropertyNameType( expressionExperimentDao.getObjectAlias(), "bioAssays.size", Integer.class ); + return new ObjectFilterPropertyMeta( expressionExperimentDao.getObjectAlias(), "bioAssays.size", Integer.class ); } if ( propertyName.equals( "lastUpdated" ) ) { - return new AliasPropertyNameType( "s", "lastUpdated", Date.class ); + return new ObjectFilterPropertyMeta( "s", "lastUpdated", Date.class ); } if ( propertyName.equals( "troubled" ) ) { - return new AliasPropertyNameType( "s", "troubled", Boolean.class ); + return new ObjectFilterPropertyMeta( "s", "troubled", Boolean.class ); } if ( propertyName.equals( "needsAttention" ) ) { - return new AliasPropertyNameType( "s", "needsAttention", Boolean.class ); + return new ObjectFilterPropertyMeta( "s", "needsAttention", Boolean.class ); } - return new AliasPropertyNameType( expressionExperimentDao.getObjectAlias(), propertyName, EntityUtils.getDeclaredFieldType( propertyName, expressionExperimentDao.getElementClass() ) ); - } - - @Data - private static class AliasPropertyNameType { - private final String objectAlias; - private final String propertyName; - private final Class propertyType; + return super.getObjectFilterPropertyMeta( propertyName ); } } \ No newline at end of file diff --git a/gemma-core/src/test/java/ubic/gemma/persistence/service/expression/arrayDesign/ArrayDesignServiceTest.java b/gemma-core/src/test/java/ubic/gemma/persistence/service/expression/arrayDesign/ArrayDesignServiceTest.java new file mode 100644 index 0000000000..fbeb0e60ff --- /dev/null +++ b/gemma-core/src/test/java/ubic/gemma/persistence/service/expression/arrayDesign/ArrayDesignServiceTest.java @@ -0,0 +1,76 @@ +package ubic.gemma.persistence.service.expression.arrayDesign; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import ubic.gemma.model.expression.arrayDesign.ArrayDesign; +import ubic.gemma.persistence.service.common.auditAndSecurity.AuditEventDao; +import ubic.gemma.persistence.service.expression.experiment.BlacklistedEntityService; +import ubic.gemma.persistence.util.ObjectFilter; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.InstanceOfAssertFactories.array; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class ArrayDesignServiceTest { + + @Configuration + static class ArrayDesignServiceTestContextConfiguration { + + @Bean + public ArrayDesignDao arrayDesignDao() { + ArrayDesignDao arrayDesignDao = mock( ArrayDesignDao.class ); + when( arrayDesignDao.getElementClass() ).thenAnswer( a -> ArrayDesign.class ); + when( arrayDesignDao.getObjectAlias() ).thenReturn( "ad" ); + return arrayDesignDao; + } + + @Bean + public BlacklistedEntityService blacklistedEntityService() { + return mock( BlacklistedEntityService.class ); + } + + @Bean + public ArrayDesignService arrayDesignService( ArrayDesignDao arrayDesignDao ) { + return new ArrayDesignServiceImpl( arrayDesignDao, mock( AuditEventDao.class ) ); + } + } + + @Autowired + private ArrayDesignDao arrayDesignDao; + + @Autowired + private ArrayDesignService arrayDesignService; + + @Test + public void testGetObjectFilter() { + assertThat( arrayDesignService.getObjectFilter( "id", ObjectFilter.Operator.eq, "1" ) ) + .hasFieldOrPropertyWithValue( "objectAlias", "ad" ) + .hasFieldOrPropertyWithValue( "propertyName", "id" ) + .hasFieldOrPropertyWithValue( "requiredValue", 1L ); + } + + @Test + public void testTaxonPropertyResolutionInGetObjectFilter() { + assertThat( arrayDesignService.getObjectFilter( "taxon", ObjectFilter.Operator.eq, "1" ) ) + .hasFieldOrPropertyWithValue( "objectAlias", "t" ) + .hasFieldOrPropertyWithValue( "propertyName", "id" ) + .hasFieldOrPropertyWithValue( "requiredValue", 1L ); + assertThat( arrayDesignService.getObjectFilter( "taxon.ncbiId", ObjectFilter.Operator.eq, "9606" ) ) + .hasFieldOrPropertyWithValue( "objectAlias", "t" ) + .hasFieldOrPropertyWithValue( "propertyName", "ncbiId" ) + .hasFieldOrPropertyWithValue( "requiredValue", 9606 ); + assertThat( arrayDesignService.getObjectFilter( "taxon.commonName", ObjectFilter.Operator.eq, "human" ) ) + .hasFieldOrPropertyWithValue( "objectAlias", "t" ) + .hasFieldOrPropertyWithValue( "propertyName", "commonName" ) + .hasFieldOrPropertyWithValue( "requiredValue", "human" ); + } + +} \ No newline at end of file From 4273bf0330dbac0b2c2862f383d8ad97f5e8e380 Mon Sep 17 00:00:00 2001 From: Guillaume Poirier-Morency Date: Sat, 10 Dec 2022 23:00:33 -0800 Subject: [PATCH 09/12] Bump REST API version to 2.6.1 and add release notes --- .../src/main/resources/openapi-configuration.yaml | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/gemma-web/src/main/resources/openapi-configuration.yaml b/gemma-web/src/main/resources/openapi-configuration.yaml index 5f434987b2..c0eb28a44f 100644 --- a/gemma-web/src/main/resources/openapi-configuration.yaml +++ b/gemma-web/src/main/resources/openapi-configuration.yaml @@ -8,7 +8,7 @@ openAPI: url: https://dev.gemma.msl.ubc.ca/rest/v2 info: title: Gemma RESTful API - version: 2.6.0 + version: 2.6.1 description: | This website documents the usage of the [Gemma RESTful API](https://gemma.msl.ubc.ca/rest/v2/). Here you can find example script usage of the API, as well as graphical interface for each endpoint, with description of its @@ -17,12 +17,11 @@ openAPI: Use of this webpage and the Gemma Web services, including the REST API, is subject to [these terms and conditions](https://pavlidislab.github.io/Gemma/terms.html). Please read these in full before continuing to use this webpage or any other part of the Gemma system. - Fix return type for `getResultSets` which was incorrectly referring to a renamed VO. + ## Updates - Annotate all possible types for `SearchResult.resultObject`. This incidentally includes the `GeneSetValueObject` - in the specification which is not exposed elsewhere in the API. + ### Update 2.6.1 - ## Updates + Add support for filtering platforms by taxon ID, common name, scientific name, etc. for the `/platforms` endpoint. ### Update 2.6.0 @@ -42,6 +41,11 @@ openAPI: to extends `getDatasetExpression` to also support quantitation type while retaining the filter feature, we decided to deprecate it and reintroduce filtering for both raw and processed expression in the future. + Fix return type for `getResultSets` which was incorrectly referring to a renamed VO. + + Annotate all possible types for `SearchResult.resultObject`. This incidentally includes the `GeneSetValueObject` + in the specification which is not exposed elsewhere in the API. + ### Update 2.5.1 Restore `objectClass` visibility in `AnnotationValueObject`. From 588e0dcc06dde30d87727730d1cc16691b16b690 Mon Sep 17 00:00:00 2001 From: Guillaume Poirier-Morency Date: Thu, 8 Dec 2022 11:24:07 -0800 Subject: [PATCH 10/12] Enforce JavaBeans contract for all subclasses of IdentifiableValueObject Add a default constructor, implement the Serializable interface and add missing missing getters/setters for properties when possible. Add a test and a StrictBeanDefinitionValidator to enumerate and validate VO definitions under ubic.gemma. This produces a warning for invalid VOs and a full breakdown when debug logging is enabled. Rename BatchConfound to BatchConfoundUtils and BatchConfoundValueObject to BatchConfound. Better isolate BioAssayDimensionValueObject's holding of a BioAssayDimension by making the accessor package-private and the field transient and thus excluded from serialization. --- .../CoexpressionMetaValueObject.java | 3 +- .../CoexpressionSummaryValueObject.java | 15 +- ...tialExpressionMetaAnalysisValueObject.java | 3 +- .../batcheffects/BatchConfound.java | 269 ++++------------- .../batcheffects/BatchConfoundUtils.java | 259 ++++++++++++++++ .../BatchConfoundValueObject.java | 84 ------ .../preprocess/svd/SVDValueObject.java | 4 + .../CompositeSequenceMapValueObject.java | 4 +- .../gene/FreeTextGeneResultsValueObject.java | 1 - .../core/genome/gene/GOGroupValueObject.java | 1 - .../gene/SessionBoundGeneSetValueObject.java | 12 +- .../core/image/ABALinkOutValueObject.java | 4 + ...ysisResultSetVisualizationValueObject.java | 11 +- ...lExpressionGenesConditionsValueObject.java | 3 +- .../util/StrictBeanDefinitionValidator.java | 121 ++++++++ .../ubic/gemma/model/BaseValueObject.java | 6 +- .../gemma/model/IdentifiableValueObject.java | 23 +- .../java/ubic/gemma/model/ValueObject.java | 13 + .../AnalysisResultSetValueObject.java | 6 +- .../analysis/AnalysisResultValueObject.java | 3 + .../model/analysis/AnalysisValueObject.java | 2 +- .../coexpression/IdArrayValueObject.java | 8 +- .../diff/ContrastResultValueObject.java | 16 +- .../expression/diff/ContrastsValueObject.java | 12 +- .../DiffExResultSetSummaryValueObject.java | 7 +- ...xpressionAnalysisResultSetValueObject.java | 20 +- ...alExpressionAnalysisResultValueObject.java | 18 +- .../DifferentialExpressionValueObject.java | 13 +- ...GeneCoexpressionNodeDegreeValueObject.java | 15 +- .../AuditEventValueObject.java | 5 +- .../AbstractCuratableValueObject.java | 17 +- .../description/AnnotationValueObject.java | 4 + .../BibliographicReferenceValueObject.java | 7 +- .../description/CitationValueObject.java | 3 +- .../description/DatabaseEntryValueObject.java | 8 +- .../ExternalDatabaseValueObject.java | 2 +- .../measurement/MeasurementValueObject.java | 23 +- .../QuantitationTypeValueObject.java | 8 +- .../expression/BlacklistedValueObject.java | 11 +- .../arrayDesign/ArrayDesignValueObject.java | 6 +- .../bioAssay/BioAssayValueObject.java | 5 +- .../BioAssayDimensionValueObject.java | 18 +- .../BooleanVectorValueObject.java | 10 +- .../bioAssayData/DataVectorValueObject.java | 21 +- .../bioAssayData/DoubleVectorValueObject.java | 7 +- ...ExperimentExpressionLevelsValueObject.java | 279 +++++++++--------- .../biomaterial/BioMaterialValueObject.java | 5 +- .../CompositeSequenceValueObject.java | 5 +- .../ExperimentalFactorValueObject.java | 5 +- ...xpressionExperimentDetailsValueObject.java | 1 + .../ExpressionExperimentSetValueObject.java | 1 + ...ExpressionExperimentSubsetValueObject.java | 10 +- .../ExpressionExperimentValueObject.java | 5 +- .../FactorValueBasicValueObject.java | 5 +- .../experiment/FactorValueValueObject.java | 7 +- .../experiment/GeeqAdminValueObject.java | 1 + .../experiment/GeeqValueObject.java | 3 +- ...undExpressionExperimentSetValueObject.java | 1 + .../genome/GeneOntologyTermValueObject.java | 41 +-- .../genome/PhysicalLocationValueObject.java | 29 ++ .../gemma/model/genome/TaxonValueObject.java | 4 +- .../genome/biosequence/SequenceType.java | 3 - .../DatabaseBackedGeneSetValueObject.java | 9 +- .../genome/gene/GeneProductValueObject.java | 5 +- .../model/genome/gene/GeneSetValueObject.java | 6 + .../model/genome/gene/GeneValueObject.java | 5 +- .../BibliographicPhenotypesValueObject.java | 3 +- .../CharacteristicBasicValueObject.java | 24 +- .../CharacteristicValueObject.java | 3 +- .../DiffExpressionEvidenceValueObject.java | 1 + .../valueObject/DumpsValueObject.java | 4 +- .../EvidenceSecurityValueObject.java | 4 +- .../EvidenceSourceValueObject.java | 4 + .../valueObject/EvidenceValueObject.java | 7 +- .../ExperimentalEvidenceValueObject.java | 1 + ...ExternalDatabaseStatisticsValueObject.java | 3 +- .../valueObject/GeneEvidenceValueObject.java | 1 + .../GenericEvidenceValueObject.java | 1 + .../LiteratureEvidenceValueObject.java | 1 + .../PhenotypeAssPubValueObject.java | 6 +- .../valueObject/PhenotypeValueObject.java | 10 +- .../valueObject/ScoreValueObject.java | 6 +- .../valueObject/SimpleTreeValueObject.java | 7 +- .../TreeCharacteristicValueObject.java | 1 + .../ValidateEvidenceValueObject.java | 3 +- .../BioSequenceValueObject.java | 9 +- .../BlatResultValueObject.java | 1 + .../SequenceTypeValueObject.java | 32 ++ .../CoexpressionCacheValueObject.java | 12 +- .../coexpression/CoexpressionValueObject.java | 13 +- .../CompositeSequenceServiceImpl.java | 3 +- .../ExpressionExperimentServiceImpl.java | 16 +- .../service/genome/gene/GeneSetDaoImpl.java | 5 +- .../search/SearchServiceVoConversionTest.java | 7 +- .../StrictBeanDefinitionValidatorTest.java | 93 ++++++ 95 files changed, 1160 insertions(+), 662 deletions(-) create mode 100644 gemma-core/src/main/java/ubic/gemma/core/analysis/preprocess/batcheffects/BatchConfoundUtils.java delete mode 100644 gemma-core/src/main/java/ubic/gemma/core/analysis/preprocess/batcheffects/BatchConfoundValueObject.java create mode 100644 gemma-core/src/main/java/ubic/gemma/core/util/StrictBeanDefinitionValidator.java create mode 100644 gemma-core/src/main/java/ubic/gemma/model/ValueObject.java create mode 100644 gemma-core/src/main/java/ubic/gemma/model/genome/sequenceAnalysis/SequenceTypeValueObject.java create mode 100644 gemma-core/src/test/java/ubic/gemma/core/util/StrictBeanDefinitionValidatorTest.java diff --git a/gemma-core/src/main/java/ubic/gemma/core/analysis/expression/coexpression/CoexpressionMetaValueObject.java b/gemma-core/src/main/java/ubic/gemma/core/analysis/expression/coexpression/CoexpressionMetaValueObject.java index f925adabfd..71c5e630af 100644 --- a/gemma-core/src/main/java/ubic/gemma/core/analysis/expression/coexpression/CoexpressionMetaValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/core/analysis/expression/coexpression/CoexpressionMetaValueObject.java @@ -23,13 +23,14 @@ import ubic.gemma.model.genome.gene.GeneValueObject; import ubic.gemma.persistence.util.Settings; +import java.io.Serializable; import java.util.*; /** * @author luke */ @SuppressWarnings({ "unused", "WeakerAccess" }) // Frontend use -public class CoexpressionMetaValueObject { +public class CoexpressionMetaValueObject implements Serializable { /** * The default maximum number of edges to send to the client. diff --git a/gemma-core/src/main/java/ubic/gemma/core/analysis/expression/coexpression/CoexpressionSummaryValueObject.java b/gemma-core/src/main/java/ubic/gemma/core/analysis/expression/coexpression/CoexpressionSummaryValueObject.java index 3ff1de9aee..7995c1908b 100644 --- a/gemma-core/src/main/java/ubic/gemma/core/analysis/expression/coexpression/CoexpressionSummaryValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/core/analysis/expression/coexpression/CoexpressionSummaryValueObject.java @@ -19,20 +19,27 @@ package ubic.gemma.core.analysis.expression.coexpression; import ubic.gemma.model.association.coexpression.GeneCoexpressionNodeDegreeValueObject; +import ubic.gemma.persistence.service.association.coexpression.CoexpressionValueObject; + +import java.io.Serializable; /** * @author luke */ @SuppressWarnings({ "unused", "WeakerAccess" }) // Used in frontend -public class CoexpressionSummaryValueObject { +public class CoexpressionSummaryValueObject implements Serializable { - private final long geneId; + private long geneId; // node degree info for this gene, genome wide. private GeneCoexpressionNodeDegreeValueObject coexpNodeDegree = null; private int datasetsAvailable; private int datasetsTested; private int linksFound; + public CoexpressionSummaryValueObject() { + super(); + } + public CoexpressionSummaryValueObject( Long geneId ) { this.geneId = geneId; } @@ -71,6 +78,10 @@ public long getGeneId() { return geneId; } + public void setGeneId( long geneId ) { + this.geneId = geneId; + } + public int getLinksFound() { return linksFound; } diff --git a/gemma-core/src/main/java/ubic/gemma/core/analysis/expression/diff/DifferentialExpressionMetaAnalysisValueObject.java b/gemma-core/src/main/java/ubic/gemma/core/analysis/expression/diff/DifferentialExpressionMetaAnalysisValueObject.java index 9949e83f03..8641059452 100644 --- a/gemma-core/src/main/java/ubic/gemma/core/analysis/expression/diff/DifferentialExpressionMetaAnalysisValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/core/analysis/expression/diff/DifferentialExpressionMetaAnalysisValueObject.java @@ -18,6 +18,7 @@ import ubic.gemma.model.expression.experiment.BioAssaySet; import ubic.gemma.model.genome.gene.GeneValueObject; +import java.io.Serializable; import java.util.Collection; /** @@ -26,7 +27,7 @@ * @author keshav */ @SuppressWarnings({ "WeakerAccess", "unused" }) // Frontend use -public class DifferentialExpressionMetaAnalysisValueObject { +public class DifferentialExpressionMetaAnalysisValueObject implements Serializable { private GeneValueObject gene = null; diff --git a/gemma-core/src/main/java/ubic/gemma/core/analysis/preprocess/batcheffects/BatchConfound.java b/gemma-core/src/main/java/ubic/gemma/core/analysis/preprocess/batcheffects/BatchConfound.java index 9bfd11fca9..27fd8c18a1 100644 --- a/gemma-core/src/main/java/ubic/gemma/core/analysis/preprocess/batcheffects/BatchConfound.java +++ b/gemma-core/src/main/java/ubic/gemma/core/analysis/preprocess/batcheffects/BatchConfound.java @@ -14,244 +14,77 @@ */ package ubic.gemma.core.analysis.preprocess.batcheffects; -import cern.colt.list.DoubleArrayList; -import cern.colt.list.IntArrayList; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.apache.commons.math3.distribution.ChiSquaredDistribution; -import org.apache.commons.math3.stat.inference.ChiSquareTest; -import org.geneontology.util.CollectionUtil; -import ubic.basecode.math.KruskalWallis; -import ubic.gemma.core.analysis.preprocess.svd.SVDServiceHelperImpl; -import ubic.gemma.core.analysis.util.ExperimentalDesignUtils; -import ubic.gemma.model.expression.bioAssay.BioAssay; -import ubic.gemma.model.expression.biomaterial.BioMaterial; import ubic.gemma.model.expression.experiment.BioAssaySet; import ubic.gemma.model.expression.experiment.ExperimentalFactor; -import ubic.gemma.model.expression.experiment.FactorValue; +import ubic.gemma.model.expression.experiment.ExpressionExperiment; +import ubic.gemma.model.expression.experiment.ExpressionExperimentSubSet; -import java.util.*; +import java.io.Serializable; /** - * Test if an experimental design is confounded with batches. + * Represents a summary of a batch effect confound. * * @author paul */ -public class BatchConfound { +@SuppressWarnings({ "unused", "WeakerAccess" }) // Used in frontend +public class BatchConfound implements Serializable { - private static final Log log = LogFactory.getLog( BatchConfound.class.getName() ); + private double chiSquare; + private int df; + private BioAssaySet ee; + private ExperimentalFactor ef; + private double p; + private int numBatches; - /** - * - * @param ee experiment or experiment subset - * @return collection of confounds (one for each confounded factor) - */ - public static Collection test( BioAssaySet ee ) { - Map> bioMaterialFactorMap = getBioMaterialFactorMap( ee ); - return factorBatchConfoundTest( ee, bioMaterialFactorMap ); - } - - /** - * - * @param ee experiment or experiment subset - * @return map of factors to map of factor -> bioassay -> factorvalue indicator - */ - private static Map> getBioMaterialFactorMap( BioAssaySet ee ) { - Map> bioMaterialFactorMap = new HashMap<>(); + public BatchConfound() { - for ( BioAssay bioAssay : ee.getBioAssays() ) { - BioMaterial bm = bioAssay.getSampleUsed(); - SVDServiceHelperImpl.populateBMFMap( bioMaterialFactorMap, bm ); - } - return bioMaterialFactorMap; } - /** - * - * @param ee experiment or subset - * @param bioMaterialFactorMap as per getBioMaterialFactorMap() - * @return collection of BatchConfoundValueObjects - */ - private static Collection factorBatchConfoundTest( BioAssaySet ee, - Map> bioMaterialFactorMap ) throws IllegalArgumentException { - - Map batchMembership = new HashMap<>(); - ExperimentalFactor batchFactor = null; - Map batchIndexes = new HashMap<>(); - Collection usedBatches = new HashSet<>(); // track batches these samples actually occupy - for ( ExperimentalFactor ef : bioMaterialFactorMap.keySet() ) { - if ( ExperimentalDesignUtils.isBatch( ef ) ) { - batchFactor = ef; - - Map bmToFv = bioMaterialFactorMap.get( batchFactor ); - - if ( bmToFv == null ) { - log.warn( "No biomaterial --> factor value map for batch factor: " + batchFactor ); - continue; - } - - int index = 0; - for ( FactorValue fv : batchFactor.getFactorValues() ) { - batchIndexes.put( fv.getId(), index++ ); - } - - for ( Long bmId : bmToFv.keySet() ) { - batchMembership.put( bmId, bmToFv.get( bmId ).longValue() ); // not perfectly safe cast - usedBatches.add( bmToFv.get( bmId ).longValue() ); - } - break; - } - } - - Set result = new HashSet<>(); - - // note that a batch can be "used" but irrelevant in a subset for some factors if they are only applied to some samples - // so we have to do more checking later. - if ( batchFactor == null || usedBatches.size() < 2 ) { - return result; // there can be no confound if there is no batch info or only one batch - } - - /* - * Compare other factors to batches to look for confounds. - */ - - for ( ExperimentalFactor ef : bioMaterialFactorMap.keySet() ) { - - if ( ef.equals( batchFactor ) ) - continue; - - // ignore factors that we add with the aim of resolving confounds. - if ( ef.getCategory() != null && ef.getCategory().getValue().equalsIgnoreCase( "collection of material" ) ) - continue; - - Map bmToFv = bioMaterialFactorMap.get( ef ); - Collection usedFactorValues = new HashSet<>( bmToFv.values() ); - int numBioMaterials = bmToFv.keySet().size(); - - assert numBioMaterials > 0 : "No biomaterials for " + ef; - - double p = Double.NaN; - double chiSquare; - int df; - - int numBatches = batchFactor.getFactorValues().size(); - if ( ExperimentalDesignUtils.isContinuous( ef ) ) { - - DoubleArrayList factorValues = new DoubleArrayList( numBioMaterials ); - factorValues.setSize( numBioMaterials ); - - IntArrayList batches = new IntArrayList( numBioMaterials ); - batches.setSize( numBioMaterials ); - - int j = 0; - for ( Long bmId : bmToFv.keySet() ) { - - assert factorValues.size() > 0 : "Biomaterial to factorValue is empty for " + ef; - - factorValues.set( j, bmToFv.get( bmId ) ); // ensures we only look at actually used factorvalues. - long batch = batchMembership.get( bmId ); - batches.set( j, batchIndexes.get( batch ) ); - j++; - } - - p = KruskalWallis.test( factorValues, batches ); - df = KruskalWallis.dof( factorValues, batches ); - chiSquare = KruskalWallis.kwStatistic( factorValues, batches ); - -// log.debug( "KWallis\t" + ee.getId() + "\t" + ee.getShortName() + "\t" + ef.getId() + "\t" + ef.getName() -// + "\t" + String.format( "%.2f", chiSquare ) + "\t" + df + "\t" + String.format( "%.2g", p ) -// + "\t" + numBatches ); - } else { - - Map factorValueIndexes = new HashMap<>(); - int index = 0; - for ( FactorValue fv : ef.getFactorValues() ) { - // only use the used factorvalues - if ( !usedFactorValues.contains( fv.getId().doubleValue() ) ) { - continue; - } - - factorValueIndexes.put( fv.getId(), index++ ); - } - Map factorValueMembership = new HashMap<>(); - - for ( Long bmId : bmToFv.keySet() ) { - factorValueMembership.put( bmId, bmToFv.get( bmId ).longValue() ); - } - - // numbatches could still be incorrect, so we have to clean this up later. - long[][] counts = new long[numBatches][usedFactorValues.size()]; - - for ( int i = 0; i < batchIndexes.size(); i++ ) { - for ( int j = 0; j < factorValueIndexes.size(); j++ ) { - counts[i][j] = 0; - } - } - - for ( Long bm : bmToFv.keySet() ) { - long fv = factorValueMembership.get( bm ); - Long batch = batchMembership.get( bm ); - if ( batch == null ) { - log.warn( "No batch membership for : " + bm ); - continue; - } - int batchIndex = batchIndexes.get( batch ); - int factorIndex = factorValueIndexes.get( fv ); - counts[batchIndex][factorIndex]++; - } - - // check for unused batches - List usedBatchesForFactor = new ArrayList<>(); - int i = 0; - for ( long[] c : counts ) { - long total = 0; - for ( long f : c ) { - total += f; - } - if ( total == 0 ) { - log.debug( "Batch " + i + " not used by " + ef + " in " + ee ); - } else { - usedBatchesForFactor.add( i ); - } - i++; - } - - // trim down again - long[][] finalCounts = new long[usedBatchesForFactor.size()][]; - int j = 0; - for ( int b : usedBatchesForFactor ) { - finalCounts[j++] = counts[b]; - } - if ( finalCounts.length < 2 ) { - continue; // to the next factor - } + public BatchConfound( BioAssaySet ee, ExperimentalFactor ef, double chiSquare, int df, double p, + int numBatches ) { + this.ee = ee; + this.ef = ef; + this.chiSquare = chiSquare; + this.df = df; + this.p = p; + this.numBatches = numBatches; + } - ChiSquareTest cst = new ChiSquareTest(); + public double getChiSquare() { + return chiSquare; + } - try { - chiSquare = cst.chiSquare( finalCounts ); - } catch ( IllegalArgumentException e ) { - log.warn( "IllegalArgumentException exception computing ChiSq for : " + ef + "; Error was: " + e - .getMessage() ); - chiSquare = Double.NaN; - } + public int getDf() { + return df; + } - df = ( finalCounts.length - 1 ) * ( finalCounts[0].length - 1 ); - ChiSquaredDistribution distribution = new ChiSquaredDistribution( df ); + public BioAssaySet getEe() { + return ee; + } - if ( !Double.isNaN( chiSquare ) ) { - p = 1.0 - distribution.cumulativeProbability( chiSquare ); - } + public ExperimentalFactor getEf() { + return ef; + } -// log.debug( "ChiSq\t" + ee.getId() + "\t" + ee.getShortName() + "\t" + ef.getId() + "\t" + ef.getName() -// + "\t" + String.format( "%.2f", chiSquare ) + "\t" + df + "\t" + String.format( "%.2g", p ) -// + "\t" + numBatches ); - } + public int getNumBatches() { + return numBatches; + } - BatchConfoundValueObject summary = new BatchConfoundValueObject( ee, ef, chiSquare, df, p, numBatches ); + public double getP() { + return p; + } - result.add( summary ); + @Override + public String toString() { + String name = null; + if ( ee instanceof ExpressionExperimentSubSet ) { + name = ( ( ExpressionExperimentSubSet ) ee ).getSourceExperiment().getShortName(); + } else { + name = " Subset " + ee.getName() + " of " + ( ( ExpressionExperiment ) ee ).getShortName(); } - return result; + return ee.getId() + "\t" + name + "\t" + ef.getId() + "\t" + ( ef.getCategory() != null ? ef.getCategory().getCategory() : ef.getName() ) + "\t" + + String.format( "%.2f", chiSquare ) + "\t" + df + "\t" + String.format( "%.2g", p ) + "\t" + + numBatches; } + } diff --git a/gemma-core/src/main/java/ubic/gemma/core/analysis/preprocess/batcheffects/BatchConfoundUtils.java b/gemma-core/src/main/java/ubic/gemma/core/analysis/preprocess/batcheffects/BatchConfoundUtils.java new file mode 100644 index 0000000000..28c0d8dfe7 --- /dev/null +++ b/gemma-core/src/main/java/ubic/gemma/core/analysis/preprocess/batcheffects/BatchConfoundUtils.java @@ -0,0 +1,259 @@ +/* + * The Gemma project + * + * Copyright (c) 2011 University of British Columbia + * + * 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 ubic.gemma.core.analysis.preprocess.batcheffects; + +import cern.colt.list.DoubleArrayList; +import cern.colt.list.IntArrayList; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.commons.math3.distribution.ChiSquaredDistribution; +import org.apache.commons.math3.stat.inference.ChiSquareTest; +import org.springframework.stereotype.Service; +import ubic.basecode.math.KruskalWallis; +import ubic.gemma.core.analysis.preprocess.svd.SVDServiceHelperImpl; +import ubic.gemma.core.analysis.util.ExperimentalDesignUtils; +import ubic.gemma.model.expression.bioAssay.BioAssay; +import ubic.gemma.model.expression.biomaterial.BioMaterial; +import ubic.gemma.model.expression.experiment.BioAssaySet; +import ubic.gemma.model.expression.experiment.ExperimentalFactor; +import ubic.gemma.model.expression.experiment.FactorValue; + +import java.util.*; + +/** + * Test if an experimental design is confounded with batches. + * + * @author paul + * @see BatchConfound + */ +@Service +public class BatchConfoundUtils { + + private static final Log log = LogFactory.getLog( BatchConfoundUtils.class.getName() ); + + /** + * + * @param ee experiment or experiment subset + * @return collection of confounds (one for each confounded factor) + */ + public static Collection test( BioAssaySet ee ) { + Map> bioMaterialFactorMap = getBioMaterialFactorMap( ee ); + return factorBatchConfoundTest( ee, bioMaterialFactorMap ); + } + + /** + * + * @param ee experiment or experiment subset + * @return map of factors to map of factor -> bioassay -> factorvalue indicator + */ + private static Map> getBioMaterialFactorMap( BioAssaySet ee ) { + Map> bioMaterialFactorMap = new HashMap<>(); + + for ( BioAssay bioAssay : ee.getBioAssays() ) { + BioMaterial bm = bioAssay.getSampleUsed(); + SVDServiceHelperImpl.populateBMFMap( bioMaterialFactorMap, bm ); + } + return bioMaterialFactorMap; + } + + /** + * + * @param ee experiment or subset + * @param bioMaterialFactorMap as per getBioMaterialFactorMap() + * @return collection of BatchConfoundValueObjects + */ + private static Collection factorBatchConfoundTest( BioAssaySet ee, + Map> bioMaterialFactorMap ) throws IllegalArgumentException { + + Map batchMembership = new HashMap<>(); + ExperimentalFactor batchFactor = null; + Map batchIndexes = new HashMap<>(); + Collection usedBatches = new HashSet<>(); // track batches these samples actually occupy + for ( ExperimentalFactor ef : bioMaterialFactorMap.keySet() ) { + if ( ExperimentalDesignUtils.isBatch( ef ) ) { + batchFactor = ef; + + Map bmToFv = bioMaterialFactorMap.get( batchFactor ); + + if ( bmToFv == null ) { + log.warn( "No biomaterial --> factor value map for batch factor: " + batchFactor ); + continue; + } + + int index = 0; + for ( FactorValue fv : batchFactor.getFactorValues() ) { + batchIndexes.put( fv.getId(), index++ ); + } + + for ( Long bmId : bmToFv.keySet() ) { + batchMembership.put( bmId, bmToFv.get( bmId ).longValue() ); // not perfectly safe cast + usedBatches.add( bmToFv.get( bmId ).longValue() ); + } + break; + } + } + + Set result = new HashSet<>(); + + // note that a batch can be "used" but irrelevant in a subset for some factors if they are only applied to some samples + // so we have to do more checking later. + if ( batchFactor == null || usedBatches.size() < 2 ) { + return result; // there can be no confound if there is no batch info or only one batch + } + + /* + * Compare other factors to batches to look for confounds. + */ + + for ( ExperimentalFactor ef : bioMaterialFactorMap.keySet() ) { + + if ( ef.equals( batchFactor ) ) + continue; + + // ignore factors that we add with the aim of resolving confounds. + if ( ef.getCategory() != null && ef.getCategory().getValue().equalsIgnoreCase( "collection of material" ) ) + continue; + + Map bmToFv = bioMaterialFactorMap.get( ef ); + Collection usedFactorValues = new HashSet<>( bmToFv.values() ); + int numBioMaterials = bmToFv.keySet().size(); + + assert numBioMaterials > 0 : "No biomaterials for " + ef; + + double p = Double.NaN; + double chiSquare; + int df; + + int numBatches = batchFactor.getFactorValues().size(); + if ( ExperimentalDesignUtils.isContinuous( ef ) ) { + + DoubleArrayList factorValues = new DoubleArrayList( numBioMaterials ); + factorValues.setSize( numBioMaterials ); + + IntArrayList batches = new IntArrayList( numBioMaterials ); + batches.setSize( numBioMaterials ); + + int j = 0; + for ( Long bmId : bmToFv.keySet() ) { + + assert factorValues.size() > 0 : "Biomaterial to factorValue is empty for " + ef; + + factorValues.set( j, bmToFv.get( bmId ) ); // ensures we only look at actually used factorvalues. + long batch = batchMembership.get( bmId ); + batches.set( j, batchIndexes.get( batch ) ); + j++; + } + + p = KruskalWallis.test( factorValues, batches ); + df = KruskalWallis.dof( factorValues, batches ); + chiSquare = KruskalWallis.kwStatistic( factorValues, batches ); + +// log.debug( "KWallis\t" + ee.getId() + "\t" + ee.getShortName() + "\t" + ef.getId() + "\t" + ef.getName() +// + "\t" + String.format( "%.2f", chiSquare ) + "\t" + df + "\t" + String.format( "%.2g", p ) +// + "\t" + numBatches ); + } else { + + Map factorValueIndexes = new HashMap<>(); + int index = 0; + for ( FactorValue fv : ef.getFactorValues() ) { + // only use the used factorvalues + if ( !usedFactorValues.contains( fv.getId().doubleValue() ) ) { + continue; + } + + factorValueIndexes.put( fv.getId(), index++ ); + } + Map factorValueMembership = new HashMap<>(); + + for ( Long bmId : bmToFv.keySet() ) { + factorValueMembership.put( bmId, bmToFv.get( bmId ).longValue() ); + } + + // numbatches could still be incorrect, so we have to clean this up later. + long[][] counts = new long[numBatches][usedFactorValues.size()]; + + for ( int i = 0; i < batchIndexes.size(); i++ ) { + for ( int j = 0; j < factorValueIndexes.size(); j++ ) { + counts[i][j] = 0; + } + } + + for ( Long bm : bmToFv.keySet() ) { + long fv = factorValueMembership.get( bm ); + Long batch = batchMembership.get( bm ); + if ( batch == null ) { + log.warn( "No batch membership for : " + bm ); + continue; + } + int batchIndex = batchIndexes.get( batch ); + int factorIndex = factorValueIndexes.get( fv ); + counts[batchIndex][factorIndex]++; + } + + // check for unused batches + List usedBatchesForFactor = new ArrayList<>(); + int i = 0; + for ( long[] c : counts ) { + long total = 0; + for ( long f : c ) { + total += f; + } + if ( total == 0 ) { + log.debug( "Batch " + i + " not used by " + ef + " in " + ee ); + } else { + usedBatchesForFactor.add( i ); + } + i++; + } + + // trim down again + long[][] finalCounts = new long[usedBatchesForFactor.size()][]; + int j = 0; + for ( int b : usedBatchesForFactor ) { + finalCounts[j++] = counts[b]; + } + if ( finalCounts.length < 2 ) { + continue; // to the next factor + } + + ChiSquareTest cst = new ChiSquareTest(); + + try { + chiSquare = cst.chiSquare( finalCounts ); + } catch ( IllegalArgumentException e ) { + log.warn( "IllegalArgumentException exception computing ChiSq for : " + ef + "; Error was: " + e + .getMessage() ); + chiSquare = Double.NaN; + } + + df = ( finalCounts.length - 1 ) * ( finalCounts[0].length - 1 ); + ChiSquaredDistribution distribution = new ChiSquaredDistribution( df ); + + if ( !Double.isNaN( chiSquare ) ) { + p = 1.0 - distribution.cumulativeProbability( chiSquare ); + } + +// log.debug( "ChiSq\t" + ee.getId() + "\t" + ee.getShortName() + "\t" + ef.getId() + "\t" + ef.getName() +// + "\t" + String.format( "%.2f", chiSquare ) + "\t" + df + "\t" + String.format( "%.2g", p ) +// + "\t" + numBatches ); + } + + BatchConfound summary = new BatchConfound( ee, ef, chiSquare, df, p, numBatches ); + + result.add( summary ); + } + return result; + } +} diff --git a/gemma-core/src/main/java/ubic/gemma/core/analysis/preprocess/batcheffects/BatchConfoundValueObject.java b/gemma-core/src/main/java/ubic/gemma/core/analysis/preprocess/batcheffects/BatchConfoundValueObject.java deleted file mode 100644 index 906528cbed..0000000000 --- a/gemma-core/src/main/java/ubic/gemma/core/analysis/preprocess/batcheffects/BatchConfoundValueObject.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * The Gemma project - * - * Copyright (c) 2011 University of British Columbia - * - * 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 ubic.gemma.core.analysis.preprocess.batcheffects; - -import ubic.gemma.model.expression.experiment.BioAssaySet; -import ubic.gemma.model.expression.experiment.ExperimentalFactor; -import ubic.gemma.model.expression.experiment.ExpressionExperiment; -import ubic.gemma.model.expression.experiment.ExpressionExperimentSubSet; - -/** - * Represents a summary of a batch effect confound. - * - * @author paul - */ -@SuppressWarnings({ "unused", "WeakerAccess" }) // Used in frontend -public class BatchConfoundValueObject { - - private final double chiSquare; - private final int df; - private final BioAssaySet ee; - private final ExperimentalFactor ef; - private final double p; - private final int numBatches; - - public BatchConfoundValueObject( BioAssaySet ee, ExperimentalFactor ef, double chiSquare, int df, double p, - int numBatches ) { - this.ee = ee; - this.ef = ef; - this.chiSquare = chiSquare; - this.df = df; - this.p = p; - this.numBatches = numBatches; - } - - public double getChiSquare() { - return chiSquare; - } - - public int getDf() { - return df; - } - - public BioAssaySet getEe() { - return ee; - } - - public ExperimentalFactor getEf() { - return ef; - } - - public int getNumBatches() { - return numBatches; - } - - public double getP() { - return p; - } - - @Override - public String toString() { - String name = null; - if ( ee instanceof ExpressionExperimentSubSet ) { - name = ( ( ExpressionExperimentSubSet ) ee ).getSourceExperiment().getShortName(); - } else { - name = " Subset " + ee.getName() + " of " + ( ( ExpressionExperiment ) ee ).getShortName(); - } - return ee.getId() + "\t" + name + "\t" + ef.getId() + "\t" + ( ef.getCategory() != null ? ef.getCategory().getCategory() : ef.getName() ) + "\t" - + String.format( "%.2f", chiSquare ) + "\t" + df + "\t" + String.format( "%.2g", p ) + "\t" - + numBatches; - } - -} diff --git a/gemma-core/src/main/java/ubic/gemma/core/analysis/preprocess/svd/SVDValueObject.java b/gemma-core/src/main/java/ubic/gemma/core/analysis/preprocess/svd/SVDValueObject.java index 78db41d08e..647a9e14d4 100644 --- a/gemma-core/src/main/java/ubic/gemma/core/analysis/preprocess/svd/SVDValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/core/analysis/preprocess/svd/SVDValueObject.java @@ -70,6 +70,10 @@ public class SVDValueObject implements Serializable { private double[] variances; private DoubleMatrix vMatrix; + public SVDValueObject() { + + } + public SVDValueObject( Long id, List bioMaterialIds, double[] variances, DoubleMatrix vMatrix ) { super(); diff --git a/gemma-core/src/main/java/ubic/gemma/core/analysis/sequence/CompositeSequenceMapValueObject.java b/gemma-core/src/main/java/ubic/gemma/core/analysis/sequence/CompositeSequenceMapValueObject.java index 005b23c066..6bf82617de 100644 --- a/gemma-core/src/main/java/ubic/gemma/core/analysis/sequence/CompositeSequenceMapValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/core/analysis/sequence/CompositeSequenceMapValueObject.java @@ -22,6 +22,7 @@ import ubic.gemma.model.genome.gene.GeneProductValueObject; import ubic.gemma.model.genome.gene.GeneValueObject; +import java.io.Serializable; import java.util.HashMap; import java.util.Map; @@ -29,7 +30,7 @@ * @author jsantos */ @SuppressWarnings({ "WeakerAccess", "unused" }) // Frontend use -public class CompositeSequenceMapValueObject implements Comparable { +public class CompositeSequenceMapValueObject implements Comparable, Serializable { private Long arrayDesignId = null; private String arrayDesignName = null; @@ -45,6 +46,7 @@ public class CompositeSequenceMapValueObject implements Comparable getAbaGeneImageUrl() { + return abaGeneImageUrls; + } + public void setAbaGeneImageUrl( Collection abaGeneImageUrls ) { this.abaGeneImageUrls = abaGeneImageUrls; } diff --git a/gemma-core/src/main/java/ubic/gemma/core/tasks/visualization/DifferentialExpressionAnalysisResultSetVisualizationValueObject.java b/gemma-core/src/main/java/ubic/gemma/core/tasks/visualization/DifferentialExpressionAnalysisResultSetVisualizationValueObject.java index 48b09b03d5..c726c6f9f0 100644 --- a/gemma-core/src/main/java/ubic/gemma/core/tasks/visualization/DifferentialExpressionAnalysisResultSetVisualizationValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/core/tasks/visualization/DifferentialExpressionAnalysisResultSetVisualizationValueObject.java @@ -1,5 +1,9 @@ package ubic.gemma.core.tasks.visualization; +import lombok.Value; +import ubic.gemma.model.ValueObject; + +import java.io.Serializable; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.HashMap; @@ -10,7 +14,8 @@ * This class contains data for a column in metaheatmap visualization. */ @SuppressWarnings("unused") // Used in frontend -public class DifferentialExpressionAnalysisResultSetVisualizationValueObject { +@ValueObject +public class DifferentialExpressionAnalysisResultSetVisualizationValueObject implements Serializable { private String datasetName; private String datasetShortName; @@ -46,6 +51,10 @@ public class DifferentialExpressionAnalysisResultSetVisualizationValueObject { private String baselineFactorValue; private Long baselineFactorValueId; + public DifferentialExpressionAnalysisResultSetVisualizationValueObject() { + super(); + } + public DifferentialExpressionAnalysisResultSetVisualizationValueObject( int[] geneGroupSizes ) { int numberOfGeneGroups = geneGroupSizes.length; diff --git a/gemma-core/src/main/java/ubic/gemma/core/tasks/visualization/DifferentialExpressionGenesConditionsValueObject.java b/gemma-core/src/main/java/ubic/gemma/core/tasks/visualization/DifferentialExpressionGenesConditionsValueObject.java index 3b61bea61b..61abcc16d7 100644 --- a/gemma-core/src/main/java/ubic/gemma/core/tasks/visualization/DifferentialExpressionGenesConditionsValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/core/tasks/visualization/DifferentialExpressionGenesConditionsValueObject.java @@ -23,6 +23,7 @@ import ubic.gemma.model.expression.experiment.ExpressionExperimentValueObject; import ubic.gemma.model.expression.experiment.FactorValueValueObject; +import java.io.Serializable; import java.util.*; /** @@ -31,7 +32,7 @@ * * @author anton */ -public class DifferentialExpressionGenesConditionsValueObject { +public class DifferentialExpressionGenesConditionsValueObject implements Serializable { /** * Map of Condition IDs to map of Genes to the Cell holding the information for the results for that Gene x * Condition combination. diff --git a/gemma-core/src/main/java/ubic/gemma/core/util/StrictBeanDefinitionValidator.java b/gemma-core/src/main/java/ubic/gemma/core/util/StrictBeanDefinitionValidator.java new file mode 100644 index 0000000000..29d30044fc --- /dev/null +++ b/gemma-core/src/main/java/ubic/gemma/core/util/StrictBeanDefinitionValidator.java @@ -0,0 +1,121 @@ +package ubic.gemma.core.util; + +import lombok.SneakyThrows; +import org.apache.commons.lang3.ClassUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.validation.Errors; +import org.springframework.validation.Validator; + +import java.beans.PropertyDescriptor; +import java.io.Serializable; +import java.lang.reflect.Modifier; +import java.net.URI; +import java.net.URL; +import java.util.*; + +/** + * Strictly validate a {@link BeanDefinition} against the JavaBeans contract. + * @author poirigui + */ +class StrictBeanDefinitionValidator implements Validator { + + /** + * These are mostly low-level standard Java class that cannot be made to comply with the JavaBeans specification. + */ + private static final Class[] IGNORED_PROPERTY_TYPES = { Collection.class, Iterator.class, Map.class, + URL.class, URI.class, Date.class, Boolean.class }; + + private final boolean allowImmutableProperties; + + /** + * Create a new bean definition validator. + */ + StrictBeanDefinitionValidator() { + this( false ); + } + + /** + * Create a new bean definition validator. + * + * @param allowImmutableProperties allow properties lacking a setter, which is not in compliance with the JavaBeans + * contract, but very common practice + */ + StrictBeanDefinitionValidator( boolean allowImmutableProperties ) { + this.allowImmutableProperties = allowImmutableProperties; + } + + @Override + public boolean supports( Class clazz ) { + return BeanDefinition.class.isAssignableFrom( clazz ); + } + + @SneakyThrows + @Override + public void validate( Object target, Errors errors ) { + BeanDefinition beanDefinition = ( BeanDefinition ) target; + Class clazz = Class.forName( beanDefinition.getBeanClassName() ); + checkSerializable( clazz, errors ); + checkZeroArgumentConstructor( clazz, errors ); + checkFields( clazz, errors ); + } + + private void checkSerializable( Class clazz, Errors errors ) throws IllegalArgumentException { + // implements serializable + if ( !Serializable.class.isAssignableFrom( clazz ) ) { + errors.rejectValue( null, "BeanDefinition.notSerializable", "is not serializable" ); + } + } + + private void checkZeroArgumentConstructor( Class clazz, Errors errors ) throws IllegalArgumentException { + // default public constructor + if ( Arrays.stream( clazz.getDeclaredConstructors() ) + .noneMatch( c -> Modifier.isPublic( c.getModifiers() ) && c.getParameterCount() == 0 ) ) { + errors.rejectValue( null, "BeanDefinition.noZeroArgPublicConstructor", "lacks a public zero-argument constructor" ); + } + } + + private void checkFields( Class clazz, Errors errors ) throws IllegalArgumentException { + checkFieldsInternal( clazz, new HashSet<>(), errors ); + } + + private void checkFieldsInternal( Class clazz, Set> seen, Errors errors ) { + if ( seen.contains( clazz ) ) { + return; + } + seen.add( clazz ); + for ( PropertyDescriptor pd : BeanUtils.getPropertyDescriptors( clazz ) ) { + if ( pd.getPropertyType() == null || pd.getPropertyType().equals( Class.class ) ) { + continue; + } + if ( pd.getReadMethod() == null ) { + errors.rejectValue( pd.getName(), "StrictBeanDefinitionValidator.noGetterForField", "lacks a getter" ); + } + if ( !allowImmutableProperties && pd.getWriteMethod() == null ) { + errors.rejectValue( pd.getName(), "StrictBeanDefinitionValidator.noSetterForField", "lacks a setter" ); + } + // further checks for non-primitive types + if ( !isPropertyTypeIgnored( pd.getPropertyType() ) ) { + try { + errors.pushNestedPath( pd.getName() ); + checkSerializable( pd.getPropertyType(), errors ); + checkZeroArgumentConstructor( pd.getPropertyType(), errors ); + checkFieldsInternal( pd.getPropertyType(), seen, errors ); + } finally { + errors.popNestedPath(); + } + } + } + } + + /** + * Tell if a property type should be validated. + * + * TODO: check collection types, array types, map types etc. + */ + private boolean isPropertyTypeIgnored( Class propertyType ) { + return ClassUtils.isPrimitiveOrWrapper( propertyType ) + || propertyType.isArray() + || Arrays.stream( IGNORED_PROPERTY_TYPES ).anyMatch( t -> t.isAssignableFrom( propertyType ) ); + } +} diff --git a/gemma-core/src/main/java/ubic/gemma/model/BaseValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/BaseValueObject.java index 34cc7b6576..2a1464440b 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/BaseValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/BaseValueObject.java @@ -32,7 +32,7 @@ public class BaseValueObject implements Serializable { */ private static final long serialVersionUID = -5290562301261202171L; - private Object valueObject; + private Serializable valueObject; private boolean errorFound; @@ -40,11 +40,11 @@ public class BaseValueObject implements Serializable { private boolean userNotLoggedIn; private boolean objectAlreadyRemoved; - public Object getValueObject() { + public Serializable getValueObject() { return this.valueObject; } - public void setValueObject( Object valueObject ) { + public void setValueObject( Serializable valueObject ) { this.valueObject = valueObject; } diff --git a/gemma-core/src/main/java/ubic/gemma/model/IdentifiableValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/IdentifiableValueObject.java index 1b6db758a3..8994270fe5 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/IdentifiableValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/IdentifiableValueObject.java @@ -7,19 +7,24 @@ import java.util.Objects; /** + * Base implementations for value objects representing persistent objects + *

* Created by tesarst on 31/05/17. - * Interface for value objects representing persistent objects + * + * @author tesarst + * @author poirigui */ -@SuppressWarnings({ "unused", "WeakerAccess" }) // Frontend use +@ValueObject @EqualsAndHashCode(of = { "id" }) -public abstract class IdentifiableValueObject implements Identifiable { +public abstract class IdentifiableValueObject implements Identifiable, Serializable { protected Long id = null; /** - * Required when using the implementing classes as a spring beans. + * Default empty constructor for bean-style initialization. */ - public IdentifiableValueObject() { + protected IdentifiableValueObject() { + super(); } /** @@ -31,11 +36,17 @@ protected IdentifiableValueObject( Long id ) { this.id = id; } + /** + * Constructor for a given entity. + */ protected IdentifiableValueObject( O identifiable ) { this( identifiable.getId() ); } - protected IdentifiableValueObject( IdentifiableValueObject vo ) { + /** + * Copy constructor. + */ + protected IdentifiableValueObject( IdentifiableValueObject vo ) { this( vo.getId() ); } diff --git a/gemma-core/src/main/java/ubic/gemma/model/ValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/ValueObject.java new file mode 100644 index 0000000000..d863bb212c --- /dev/null +++ b/gemma-core/src/main/java/ubic/gemma/model/ValueObject.java @@ -0,0 +1,13 @@ +package ubic.gemma.model; + +import java.lang.annotation.*; + +/** + * Annotate class representing value objects. + * @author poirigui + */ +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +@Inherited +public @interface ValueObject { +} diff --git a/gemma-core/src/main/java/ubic/gemma/model/analysis/AnalysisResultSetValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/analysis/AnalysisResultSetValueObject.java index 425b974dc0..03fea30c2d 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/analysis/AnalysisResultSetValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/analysis/AnalysisResultSetValueObject.java @@ -31,8 +31,12 @@ */ public abstract class AnalysisResultSetValueObject> extends IdentifiableValueObject { + protected AnalysisResultSetValueObject() { + super(); + } + protected AnalysisResultSetValueObject( R analysisResultSet ) { - super( analysisResultSet.getId() ); + super( analysisResultSet ); } /** diff --git a/gemma-core/src/main/java/ubic/gemma/model/analysis/AnalysisResultValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/analysis/AnalysisResultValueObject.java index 128890d14a..79dcc94d06 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/analysis/AnalysisResultValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/analysis/AnalysisResultValueObject.java @@ -27,6 +27,9 @@ */ public abstract class AnalysisResultValueObject extends IdentifiableValueObject { + protected AnalysisResultValueObject() { + } + protected AnalysisResultValueObject( A entity ) { super( entity ); } diff --git a/gemma-core/src/main/java/ubic/gemma/model/analysis/AnalysisValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/analysis/AnalysisValueObject.java index d6a89d8c0c..41dc9bac31 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/analysis/AnalysisValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/analysis/AnalysisValueObject.java @@ -9,6 +9,6 @@ protected AnalysisValueObject() { } protected AnalysisValueObject( T analysis ) { - super( analysis.getId() ); + super( analysis ); } } diff --git a/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/coexpression/IdArrayValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/coexpression/IdArrayValueObject.java index 0aa7da8b01..0791d5d95c 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/coexpression/IdArrayValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/coexpression/IdArrayValueObject.java @@ -1,8 +1,8 @@ /* * The gemma project - * + * * Copyright (c) 2014 University of British Columbia - * + * * 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 @@ -26,6 +26,10 @@ public class IdArrayValueObject extends IdArray { private static final long serialVersionUID = 3449107398932831708L; + public IdArrayValueObject() { + super(); + } + public IdArrayValueObject( byte[] data ) { this.setBytes( data ); } diff --git a/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/diff/ContrastResultValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/diff/ContrastResultValueObject.java index 036ec21c0a..55844786e7 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/diff/ContrastResultValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/diff/ContrastResultValueObject.java @@ -13,12 +13,16 @@ @ToString public class ContrastResultValueObject extends IdentifiableValueObject { - private final Double pvalue; - private final Double tStat; - private final Double coefficient; - private final Double logFoldChange; - private final FactorValueBasicValueObject factorValue; - private final FactorValueBasicValueObject secondFactorValue; + private Double pvalue; + private Double tStat; + private Double coefficient; + private Double logFoldChange; + private FactorValueBasicValueObject factorValue; + private FactorValueBasicValueObject secondFactorValue; + + public ContrastResultValueObject() { + super(); + } /** * Create a contrast value object from a given {@link ContrastResult}. diff --git a/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/diff/ContrastsValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/diff/ContrastsValueObject.java index b5863bcba2..524ee260cb 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/diff/ContrastsValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/diff/ContrastsValueObject.java @@ -14,6 +14,7 @@ */ package ubic.gemma.model.analysis.expression.diff; +import java.io.Serializable; import java.util.List; import java.util.Vector; @@ -22,11 +23,15 @@ * * @author Paul */ -public class ContrastsValueObject { +public class ContrastsValueObject implements Serializable { private final List contrasts = new Vector<>( 2 ); // commonly only have one. - private final Long resultId; + private Long resultId; + + public ContrastsValueObject() { + super(); + } public ContrastsValueObject( Long resultId ) { this.resultId = resultId; @@ -45,4 +50,7 @@ public Long getResultId() { return resultId; } + public void setResultId( Long resultId ) { + this.resultId = resultId; + } } \ No newline at end of file diff --git a/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/diff/DiffExResultSetSummaryValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/diff/DiffExResultSetSummaryValueObject.java index 5601193fee..47b20a8e28 100755 --- a/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/diff/DiffExResultSetSummaryValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/diff/DiffExResultSetSummaryValueObject.java @@ -27,6 +27,7 @@ import ubic.gemma.model.expression.experiment.FactorValueValueObject; import ubic.gemma.persistence.util.EntityUtils; +import java.io.Serializable; import java.util.Collection; import java.util.HashSet; @@ -39,7 +40,7 @@ @SuppressWarnings({ "unused", "WeakerAccess" }) // Used in frontend @Data @EqualsAndHashCode(of = { "id" }) -public class DiffExResultSetSummaryValueObject implements java.io.Serializable { +public class DiffExResultSetSummaryValueObject implements Serializable { private static final long serialVersionUID = 2063274043081170625L; @@ -96,6 +97,10 @@ public class DiffExResultSetSummaryValueObject implements java.io.Serializable { */ private Integer downregulatedCount; + public DiffExResultSetSummaryValueObject() { + super(); + } + public DiffExResultSetSummaryValueObject( ExpressionAnalysisResultSet resultSet ) { this.setId( resultSet.getId() ); this.setFactorIds( EntityUtils.getIds( resultSet.getExperimentalFactors() ) ); diff --git a/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/diff/DifferentialExpressionAnalysisResultSetValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/diff/DifferentialExpressionAnalysisResultSetValueObject.java index a241935d2d..c689707b24 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/diff/DifferentialExpressionAnalysisResultSetValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/diff/DifferentialExpressionAnalysisResultSetValueObject.java @@ -16,8 +16,8 @@ */ public class DifferentialExpressionAnalysisResultSetValueObject extends AnalysisResultSetValueObject { - private final DifferentialExpressionAnalysisValueObject analysis; - private final Collection experimentalFactors; + private DifferentialExpressionAnalysisValueObject analysis; + private Collection experimentalFactors; /** * Related analysis results. @@ -27,6 +27,10 @@ public class DifferentialExpressionAnalysisResultSetValueObject extends Analysis @JsonInclude(JsonInclude.Include.NON_NULL) private Collection results; + public DifferentialExpressionAnalysisResultSetValueObject() { + super(); + } + /** * Create a simple analysis results set VO with limited data. */ @@ -58,12 +62,24 @@ public DifferentialExpressionAnalysisValueObject getAnalysis() { return analysis; } + public void setAnalysis( DifferentialExpressionAnalysisValueObject analysis ) { + this.analysis = analysis; + } + public Collection getExperimentalFactors() { return experimentalFactors; } + public void setExperimentalFactors( Collection experimentalFactors ) { + this.experimentalFactors = experimentalFactors; + } + @Override public Collection getResults() { return results; } + + public void setResults( Collection results ) { + this.results = results; + } } diff --git a/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/diff/DifferentialExpressionAnalysisResultValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/diff/DifferentialExpressionAnalysisResultValueObject.java index 70c55fb27d..b7c273719f 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/diff/DifferentialExpressionAnalysisResultValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/diff/DifferentialExpressionAnalysisResultValueObject.java @@ -31,13 +31,17 @@ @EqualsAndHashCode(of = { "probeId" }, callSuper = true) public class DifferentialExpressionAnalysisResultValueObject extends AnalysisResultValueObject { - private final Long probeId; - private final String probeName; - private final List genes; - private final Double pValue; - private final Double correctedPvalue; - private final Double rank; - private final List contrasts; + private Long probeId; + private String probeName; + private List genes; + private Double pValue; + private Double correctedPvalue; + private Double rank; + private List contrasts; + + public DifferentialExpressionAnalysisResultValueObject() { + super(); + } public DifferentialExpressionAnalysisResultValueObject( DifferentialExpressionAnalysisResult result, List genes ) { super( result ); diff --git a/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/diff/DifferentialExpressionValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/diff/DifferentialExpressionValueObject.java index 8ad2e16ad5..de3bbb7c94 100755 --- a/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/diff/DifferentialExpressionValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/analysis/expression/diff/DifferentialExpressionValueObject.java @@ -23,6 +23,7 @@ import ubic.gemma.model.expression.experiment.ExpressionExperimentValueObject; import ubic.gemma.model.genome.gene.GeneValueObject; +import java.io.Serializable; import java.util.Collection; import java.util.HashSet; @@ -32,9 +33,9 @@ * @author keshav */ @SuppressWarnings({ "unused", "WeakerAccess" }) // Used in frontend -public class DifferentialExpressionValueObject { +public class DifferentialExpressionValueObject implements Serializable { - private final ContrastsValueObject contrasts; + private ContrastsValueObject contrasts; private Double corrP; private Direction direction; private Collection experimentalFactors = new HashSet<>(); @@ -49,6 +50,10 @@ public class DifferentialExpressionValueObject { private Long resultSetId = null; private String sortKey; + public DifferentialExpressionValueObject() { + super(); + } + public DifferentialExpressionValueObject( DifferentialExpressionAnalysisResult o ) { this.p = o.getPvalue(); this.corrP = o.getCorrectedPvalue(); @@ -84,6 +89,10 @@ public ContrastsValueObject getContrasts() { return contrasts; } + public void setContrasts( ContrastsValueObject contrasts ) { + this.contrasts = contrasts; + } + public Double getCorrP() { return corrP; } diff --git a/gemma-core/src/main/java/ubic/gemma/model/association/coexpression/GeneCoexpressionNodeDegreeValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/association/coexpression/GeneCoexpressionNodeDegreeValueObject.java index 13497cd4f8..1980b2796e 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/association/coexpression/GeneCoexpressionNodeDegreeValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/association/coexpression/GeneCoexpressionNodeDegreeValueObject.java @@ -25,6 +25,7 @@ import org.apache.commons.lang3.StringUtils; import ubic.basecode.io.ByteArrayConverter; +import java.io.Serializable; import java.util.List; import java.util.TreeMap; @@ -33,15 +34,19 @@ * * @author Paul */ -public class GeneCoexpressionNodeDegreeValueObject { +public class GeneCoexpressionNodeDegreeValueObject implements Serializable { private static final ByteArrayConverter bac = new ByteArrayConverter(); - private final Long geneId; + private Long geneId; private TreeMap nodeDegreesNeg = new TreeMap<>(); private TreeMap nodeDegreesPos = new TreeMap<>(); private TreeMap relDegreesNeg = new TreeMap<>(); private TreeMap relDegreesPos = new TreeMap<>(); + public GeneCoexpressionNodeDegreeValueObject() { + super(); + } + public GeneCoexpressionNodeDegreeValueObject( GeneCoexpressionNodeDegree entity ) { this.geneId = entity.getGeneId(); this.initLinkCounts( entity.getLinkCountsPositive(), true ); @@ -79,7 +84,7 @@ public Long getGeneId() { /** * @param support value * @param positive positive - * @return how many links have this much support (specifically). + * @return how many links have this much support (specifically). */ public Integer getLinksWithExactSupport( Integer support, boolean positive ) { if ( positive ) { @@ -91,7 +96,7 @@ public Integer getLinksWithExactSupport( Integer support, boolean positive ) { /** * @param i support - * @return total number of links (this is just the total of positive and negative; if some of those are with the + * @return total number of links (this is just the total of positive and negative; if some of those are with the * same genes it's a double count, sorry) */ public Integer getLinksWithMinimumSupport( int i ) { @@ -101,7 +106,7 @@ public Integer getLinksWithMinimumSupport( int i ) { /** * @param support threshold * @param positive positive - * @return how many links have at least this much support (cumulative) + * @return how many links have at least this much support (cumulative) */ public Integer getLinksWithMinimumSupport( Integer support, boolean positive ) { assert support >= 0; diff --git a/gemma-core/src/main/java/ubic/gemma/model/common/auditAndSecurity/AuditEventValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/common/auditAndSecurity/AuditEventValueObject.java index f46e204059..c95f8fa32a 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/common/auditAndSecurity/AuditEventValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/common/auditAndSecurity/AuditEventValueObject.java @@ -33,7 +33,7 @@ * @author klc (orginally generated by model) */ @SuppressWarnings("unused") // Used in frontend -public class AuditEventValueObject extends IdentifiableValueObject implements Serializable { +public class AuditEventValueObject extends IdentifiableValueObject { private static final long serialVersionUID = 1L; @@ -51,6 +51,7 @@ public class AuditEventValueObject extends IdentifiableValueObject i * Required when using the class as a spring bean. */ public AuditEventValueObject() { + super(); } public AuditEventValueObject( Long id ) { @@ -58,7 +59,7 @@ public AuditEventValueObject( Long id ) { } public AuditEventValueObject( AuditEvent ae ) { - super( ae.getId() ); + super( ae ); if ( ae.getPerformer() != null ) this.setPerformer( ae.getPerformer().getUserName() ); if ( ae.getAction() != null ) diff --git a/gemma-core/src/main/java/ubic/gemma/model/common/auditAndSecurity/curation/AbstractCuratableValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/common/auditAndSecurity/curation/AbstractCuratableValueObject.java index 3865265cc6..119d90de19 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/common/auditAndSecurity/curation/AbstractCuratableValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/common/auditAndSecurity/curation/AbstractCuratableValueObject.java @@ -19,18 +19,19 @@ public abstract class AbstractCuratableValueObject extends private static final String TROUBLE_DETAILS_NONE = "No trouble details provided."; - protected Date lastUpdated; - protected Boolean troubled = false; - protected AuditEventValueObject lastTroubledEvent; - protected Boolean needsAttention = false; - protected AuditEventValueObject lastNeedsAttentionEvent; - protected String curationNote; - protected AuditEventValueObject lastNoteUpdateEvent; + private Date lastUpdated; + private Boolean troubled = false; + private AuditEventValueObject lastTroubledEvent; + private Boolean needsAttention = false; + private AuditEventValueObject lastNeedsAttentionEvent; + private String curationNote; + private AuditEventValueObject lastNoteUpdateEvent; /** * Required when using the implementing classes as a spring beans. */ - public AbstractCuratableValueObject() { + protected AbstractCuratableValueObject() { + super(); } protected AbstractCuratableValueObject( Long id ) { diff --git a/gemma-core/src/main/java/ubic/gemma/model/common/description/AnnotationValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/common/description/AnnotationValueObject.java index 3d75b936b1..9a1cad51a7 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/common/description/AnnotationValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/common/description/AnnotationValueObject.java @@ -51,6 +51,10 @@ public class AnnotationValueObject extends IdentifiableValueObject { +public class CitationValueObject implements Comparable, Serializable { // for constructing pubmedURLs @SuppressWarnings("WeakerAccess") // Might be accessed in the front end diff --git a/gemma-core/src/main/java/ubic/gemma/model/common/description/DatabaseEntryValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/common/description/DatabaseEntryValueObject.java index 31aaa061e7..76bd9277e9 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/common/description/DatabaseEntryValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/common/description/DatabaseEntryValueObject.java @@ -29,14 +29,18 @@ @SuppressWarnings("WeakerAccess") // Used in frontend @Data @EqualsAndHashCode(of = { "accession", "externalDatabase" }, callSuper = false) -public class DatabaseEntryValueObject extends IdentifiableValueObject implements Serializable { +public class DatabaseEntryValueObject extends IdentifiableValueObject { private static final long serialVersionUID = -527323410580090L; private String accession; private ExternalDatabaseValueObject externalDatabase; + public DatabaseEntryValueObject() { + super(); + } + public DatabaseEntryValueObject( DatabaseEntry de ) { - super( de.getId() ); + super( de ); this.accession = de.getAccession(); this.externalDatabase = de.getExternalDatabase() != null ? new ExternalDatabaseValueObject( de.getExternalDatabase() ) : null; diff --git a/gemma-core/src/main/java/ubic/gemma/model/common/description/ExternalDatabaseValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/common/description/ExternalDatabaseValueObject.java index d806a4c56c..27dfc2548b 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/common/description/ExternalDatabaseValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/common/description/ExternalDatabaseValueObject.java @@ -33,7 +33,7 @@ @SuppressWarnings({ "unused", "WeakerAccess" }) // Possible external use @Data @EqualsAndHashCode(of = { "name" }, callSuper = false) -public class ExternalDatabaseValueObject extends IdentifiableValueObject implements Serializable, Comparable, Versioned { +public class ExternalDatabaseValueObject extends IdentifiableValueObject implements Comparable, Versioned { private static final long serialVersionUID = -1714429166594162374L; private String name; diff --git a/gemma-core/src/main/java/ubic/gemma/model/common/measurement/MeasurementValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/common/measurement/MeasurementValueObject.java index f74a485897..2202414b41 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/common/measurement/MeasurementValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/common/measurement/MeasurementValueObject.java @@ -15,10 +15,11 @@ public class MeasurementValueObject extends IdentifiableValueObject { private String representation; public MeasurementValueObject() { + super(); } public MeasurementValueObject( Measurement measurement ) { - super( measurement.getId() ); + super( measurement ); this.value = measurement.getValue(); if ( measurement.getUnit() != null ) { this.unit = measurement.getUnit().getUnitNameCV(); @@ -48,4 +49,24 @@ public String getType() { public String getRepresentation() { return representation; } + + public void setValue( String value ) { + this.value = value; + } + + public void setUnit( String unit ) { + this.unit = unit; + } + + public void setUnitId( Long unitId ) { + this.unitId = unitId; + } + + public void setType( String type ) { + this.type = type; + } + + public void setRepresentation( String representation ) { + this.representation = representation; + } } diff --git a/gemma-core/src/main/java/ubic/gemma/model/common/quantitationtype/QuantitationTypeValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/common/quantitationtype/QuantitationTypeValueObject.java index bee65daad2..9a29d3edc3 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/common/quantitationtype/QuantitationTypeValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/common/quantitationtype/QuantitationTypeValueObject.java @@ -42,7 +42,7 @@ @Data @EqualsAndHashCode(of = { "expressionExperimentId" }, callSuper = true) @ToString(of = { "name" }, callSuper = true) -public class QuantitationTypeValueObject extends IdentifiableValueObject implements Serializable { +public class QuantitationTypeValueObject extends IdentifiableValueObject { private static final long serialVersionUID = 7537853492100102404L; private String description; @@ -77,8 +77,12 @@ public class QuantitationTypeValueObject extends IdentifiableValueObject implements Serializable { +public class BlacklistedValueObject extends IdentifiableValueObject { private static final long serialVersionUID = -4817418347388923905L; public static BlacklistedValueObject fromEntity( BlacklistedEntity e ) { @@ -41,7 +41,7 @@ public static BlacklistedValueObject fromEntity( BlacklistedEntity e ) { result.setType( e.getClass().getSimpleName() ); return result; } - + private String accession; private ExternalDatabaseValueObject externalDatabase; private String name; @@ -53,6 +53,7 @@ public static BlacklistedValueObject fromEntity( BlacklistedEntity e ) { * Required when using the class as a spring bean. */ public BlacklistedValueObject() { + super(); } @SuppressWarnings("unused") diff --git a/gemma-core/src/main/java/ubic/gemma/model/expression/arrayDesign/ArrayDesignValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/expression/arrayDesign/ArrayDesignValueObject.java index 75baa5a775..3fe37a139a 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/expression/arrayDesign/ArrayDesignValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/expression/arrayDesign/ArrayDesignValueObject.java @@ -49,7 +49,7 @@ @Data @EqualsAndHashCode(of = { "shortName" }, callSuper = true) @CommonsLog -public class ArrayDesignValueObject extends AbstractCuratableValueObject implements Serializable, Versioned { +public class ArrayDesignValueObject extends AbstractCuratableValueObject implements Versioned { /** * The serial version UID of this class. Needed for serialization. */ @@ -147,6 +147,10 @@ public static Collection create( Collection */ private Set externalReferences; + public ArrayDesignValueObject() { + super(); + } + public ArrayDesignValueObject( Long id ) { super( id ); } diff --git a/gemma-core/src/main/java/ubic/gemma/model/expression/bioAssay/BioAssayValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/expression/bioAssay/BioAssayValueObject.java index 8545b5536d..0ea1540fa7 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/expression/bioAssay/BioAssayValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/expression/bioAssay/BioAssayValueObject.java @@ -33,7 +33,7 @@ * @author Paul */ @SuppressWarnings("unused") // ValueObject accessed from JS -public class BioAssayValueObject extends IdentifiableValueObject implements Serializable { +public class BioAssayValueObject extends IdentifiableValueObject { private static final long serialVersionUID = 9164284536309673585L; @@ -71,6 +71,7 @@ public static Collection convert2ValueObjects( Collection arrayDesignValueObjectsById, boolean basic ) { - super( bioAssay.getId() ); + super( bioAssay ); this.name = bioAssay.getName(); this.description = bioAssay.getDescription(); diff --git a/gemma-core/src/main/java/ubic/gemma/model/expression/bioAssayData/BioAssayDimensionValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/expression/bioAssayData/BioAssayDimensionValueObject.java index af4104e956..0006e1b8a6 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/expression/bioAssayData/BioAssayDimensionValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/expression/bioAssayData/BioAssayDimensionValueObject.java @@ -27,18 +27,17 @@ import ubic.gemma.model.expression.experiment.FactorValue; import ubic.gemma.model.expression.experiment.FactorValueValueObject; -import java.io.Serializable; import java.util.*; /** * @author Paul */ @SuppressWarnings({ "unused", "WeakerAccess" }) // Used in frontend -public class BioAssayDimensionValueObject extends IdentifiableValueObject implements Serializable { +public class BioAssayDimensionValueObject extends IdentifiableValueObject { private static final long serialVersionUID = -8686807689616396835L; private final List bioAssays = new LinkedList<>(); - private BioAssayDimension bioAssayDimension = null; + private transient BioAssayDimension bioAssayDimension = null; private String description; private String name; private boolean isReordered = false; @@ -53,6 +52,7 @@ public class BioAssayDimensionValueObject extends IdentifiableValueObject bvos ) { this.bioAssays.addAll( bvos ); } - public void setBioAssayDimension( BioAssayDimension bioAssayDimension ) { - this.bioAssayDimension = bioAssayDimension; - } - public void setSubset( boolean subset ) { isSubset = subset; } @@ -119,7 +115,7 @@ public void setDescription( String description ) { * then the return will be a "fake" entity that has minimal information stored. This is a kludge to avoid * having to make the DataMatrix code use ValueObjects. */ - public BioAssayDimension getEntity() { + BioAssayDimension getBioAssayDimension() { if ( this.bioAssayDimension == null ) { if ( !isSubset ) throw new IllegalStateException( "Entity was not set, not allowed unless isSubset=true" ); diff --git a/gemma-core/src/main/java/ubic/gemma/model/expression/bioAssayData/BooleanVectorValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/expression/bioAssayData/BooleanVectorValueObject.java index 6afaa72140..70fc19501d 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/expression/bioAssayData/BooleanVectorValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/expression/bioAssayData/BooleanVectorValueObject.java @@ -1,8 +1,8 @@ /* * The Gemma project - * + * * Copyright (c) 2008 University of British Columbia - * + * * 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 @@ -22,7 +22,7 @@ /** * This is used to represent missing value data. - * + * * @author paul * */ @@ -30,6 +30,10 @@ public class BooleanVectorValueObject extends DataVectorValueObject { private static final long serialVersionUID = 1L; private boolean[] data; + public BooleanVectorValueObject() { + super(); + } + public BooleanVectorValueObject( DesignElementDataVector dedv, BioAssayDimensionValueObject badvo ) { super( dedv, badvo ); if ( !dedv.getQuantitationType().getRepresentation().equals( PrimitiveType.BOOLEAN ) ) { diff --git a/gemma-core/src/main/java/ubic/gemma/model/expression/bioAssayData/DataVectorValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/expression/bioAssayData/DataVectorValueObject.java index d572005282..38c4a6c1f9 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/expression/bioAssayData/DataVectorValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/expression/bioAssayData/DataVectorValueObject.java @@ -33,17 +33,13 @@ * @author paul */ @SuppressWarnings({ "unused", "WeakerAccess" }) // Used in frontend -public abstract class DataVectorValueObject extends IdentifiableValueObject implements Serializable { +public abstract class DataVectorValueObject extends IdentifiableValueObject { private static final long serialVersionUID = 4291090102921066018L; - static ByteArrayConverter byteArrayConverter; + protected static final ByteArrayConverter byteArrayConverter = new ByteArrayConverter(); - static { - DataVectorValueObject.byteArrayConverter = new ByteArrayConverter(); - } - - ExpressionExperimentValueObject expressionExperiment; + private ExpressionExperimentValueObject expressionExperiment; private CompositeSequenceValueObject designElement; private QuantitationTypeValueObject quantitationType; private Collection genes; @@ -52,15 +48,16 @@ public abstract class DataVectorValueObject extends IdentifiableValueObject genes, + protected DataVectorValueObject( DesignElementDataVector dedv, Collection genes, BioAssayDimensionValueObject badvo ) { this( dedv, badvo ); this.genes = genes; diff --git a/gemma-core/src/main/java/ubic/gemma/model/expression/bioAssayData/DoubleVectorValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/expression/bioAssayData/DoubleVectorValueObject.java index 9707c9c0c4..c867d06b34 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/expression/bioAssayData/DoubleVectorValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/expression/bioAssayData/DoubleVectorValueObject.java @@ -60,6 +60,7 @@ public class DoubleVectorValueObject extends DataVectorValueObject { * Required when using the class as a spring bean. */ public DoubleVectorValueObject() { + super(); } /** @@ -83,9 +84,9 @@ public DoubleVectorValueObject( ExpressionExperimentSubSet bioassaySet, DoubleVe this.setDesignElement( vec.getDesignElement() ); if ( !bioassaySet.getId().equals( vec.getExpressionExperiment().getId() ) ) { - this.expressionExperiment = new ExpressionExperimentSubsetValueObject( bioassaySet ); + this.setExpressionExperiment( new ExpressionExperimentSubsetValueObject( bioassaySet ) ); } else { - this.expressionExperiment = vec.getExpressionExperiment(); + this.setExpressionExperiment( vec.getExpressionExperiment() ); } this.setQuantitationType( vec.getQuantitationType() ); @@ -276,7 +277,7 @@ public DesignElementDataVector toDesignElementDataVector( ExpressionExperiment e } result.setExpressionExperiment( ee ); - result.setBioAssayDimension( this.getBioAssayDimension().getEntity() ); + result.setBioAssayDimension( this.getBioAssayDimension().getBioAssayDimension() ); assert this.getBioAssays().size() > 0; result.setQuantitationType( updatedQuantitationType ); diff --git a/gemma-core/src/main/java/ubic/gemma/model/expression/bioAssayData/ExperimentExpressionLevelsValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/expression/bioAssayData/ExperimentExpressionLevelsValueObject.java index ed4e853bec..d185467f4f 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/expression/bioAssayData/ExperimentExpressionLevelsValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/expression/bioAssayData/ExperimentExpressionLevelsValueObject.java @@ -4,6 +4,7 @@ import ubic.gemma.model.expression.bioAssay.BioAssayValueObject; import ubic.gemma.model.genome.Gene; +import java.io.Serializable; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -12,7 +13,7 @@ import static ubic.gemma.model.expression.bioAssayData.ExperimentExpressionLevelsValueObject.*; @SuppressWarnings("unused") // Used in rest api -public class ExperimentExpressionLevelsValueObject { +public class ExperimentExpressionLevelsValueObject implements Serializable { public static final String OPT_PICK_MAX = "pickmax"; public static final String OPT_PICK_VAR = "pickvar"; public static final String OPT_AVG = "average"; @@ -22,6 +23,10 @@ public class ExperimentExpressionLevelsValueObject { private long datasetId; private LinkedList geneExpressionLevels = new LinkedList<>(); + public ExperimentExpressionLevelsValueObject() { + super(); + } + public ExperimentExpressionLevelsValueObject( long datasetId, Map> vectorsPerGene, boolean keepGeneNonSpecific, String conslidationMode ) { @@ -43,181 +48,189 @@ public long getDatasetId() { public LinkedList getGeneExpressionLevels() { return geneExpressionLevels; } -} - -// Used in rest api -@SuppressWarnings("unused") -class GeneElementExpressionsValueObject { - private static final String AVG_PREFIX = "Averaged from"; - private static final String MSG_ERR_VECS_MAX = "Can not compute max from null or 1 element vector collection"; - private static final String MSG_ERR_VECS_VAR = "Can not compute var from null or 1 element vector collection"; - private String geneOfficialSymbol; - private Integer geneNcbiId; - private List elements = new LinkedList<>(); - GeneElementExpressionsValueObject( String geneOfficialSymbol, Integer geneNcbiId, - List vectors, boolean keepGeneNonSpecific, String mode ) { - this.geneOfficialSymbol = geneOfficialSymbol; - this.geneNcbiId = geneNcbiId; + // Used in rest api + @SuppressWarnings("unused") + public static class GeneElementExpressionsValueObject implements Serializable { + private static final String AVG_PREFIX = "Averaged from"; + private static final String MSG_ERR_VECS_MAX = "Can not compute max from null or 1 element vector collection"; + private static final String MSG_ERR_VECS_VAR = "Can not compute var from null or 1 element vector collection"; + private String geneOfficialSymbol; + private Integer geneNcbiId; + private List elements = new LinkedList<>(); - if ( vectors == null ) { - return; + public GeneElementExpressionsValueObject() { + super(); } - if ( !keepGeneNonSpecific ) { // Pre process - List processed = new LinkedList<>(); - for ( DoubleVectorValueObject vo : vectors ) { - if ( vo.getGenes().size() == 1 ) { // Only including gene-nonspecific vectors - processed.add( vo ); - } + public GeneElementExpressionsValueObject( String geneOfficialSymbol, Integer geneNcbiId, + List vectors, boolean keepGeneNonSpecific, String mode ) { + this.geneOfficialSymbol = geneOfficialSymbol; + this.geneNcbiId = geneNcbiId; + + if ( vectors == null ) { + return; } - vectors = processed; - } - - if ( vectors.size() > 1 && !Strings.isNullOrEmpty( mode ) ) { // Consolidation requested - switch ( mode ) { - case ( OPT_PICK_MAX ): - elements.add( this.pickMax( vectors ) ); - break; - case ( OPT_PICK_VAR ): - elements.add( this.pickVar( vectors ) ); - break; - case ( OPT_AVG ): - elements.add( this.average( vectors ) ); - break; + + if ( !keepGeneNonSpecific ) { // Pre process + List processed = new LinkedList<>(); + for ( DoubleVectorValueObject vo : vectors ) { + if ( vo.getGenes().size() == 1 ) { // Only including gene-nonspecific vectors + processed.add( vo ); + } + } + vectors = processed; } - } else { // Add all vectors - for ( DoubleVectorValueObject vector : vectors ) { - elements.add( new VectorElementValueObject( vector ) ); + + if ( vectors.size() > 1 && !Strings.isNullOrEmpty( mode ) ) { // Consolidation requested + switch ( mode ) { + case ( OPT_PICK_MAX ): + elements.add( this.pickMax( vectors ) ); + break; + case ( OPT_PICK_VAR ): + elements.add( this.pickVar( vectors ) ); + break; + case ( OPT_AVG ): + elements.add( this.average( vectors ) ); + break; + } + } else { // Add all vectors + for ( DoubleVectorValueObject vector : vectors ) { + elements.add( new VectorElementValueObject( vector ) ); + } } } - } - public String getGeneOfficialSymbol() { - return geneOfficialSymbol; - } + public String getGeneOfficialSymbol() { + return geneOfficialSymbol; + } - public Integer getGeneNcbiId() { - return geneNcbiId; - } + public Integer getGeneNcbiId() { + return geneNcbiId; + } - public List getVectors() { - return elements; - } + public List getVectors() { + return elements; + } - private VectorElementValueObject pickMax( List vectors ) { - if ( vectors == null || vectors.size() <= 1 ) { - throw new IllegalArgumentException( GeneElementExpressionsValueObject.MSG_ERR_VECS_MAX ); - } - DoubleVectorValueObject max = null; - Double avgMax = null; - for ( DoubleVectorValueObject v : vectors ) { - double avg = this.getMean( v.getData() ); - if ( max == null || avg > avgMax ) { - avgMax = avg; - max = v; + private VectorElementValueObject pickMax( List vectors ) { + if ( vectors == null || vectors.size() <= 1 ) { + throw new IllegalArgumentException( GeneElementExpressionsValueObject.MSG_ERR_VECS_MAX ); + } + DoubleVectorValueObject max = null; + Double avgMax = null; + for ( DoubleVectorValueObject v : vectors ) { + double avg = this.getMean( v.getData() ); + if ( max == null || avg > avgMax ) { + avgMax = avg; + max = v; + } } + return new VectorElementValueObject( max ); } - return new VectorElementValueObject( max ); - } - private VectorElementValueObject pickVar( List vectors ) { - if ( vectors == null || vectors.size() <= 1 ) { - throw new IllegalArgumentException( GeneElementExpressionsValueObject.MSG_ERR_VECS_VAR ); - } - DoubleVectorValueObject max = null; - Double varMax = null; - for ( DoubleVectorValueObject v : vectors ) { - double avg = this.getVariance( v.getData() ); - if ( max == null || avg > varMax ) { - varMax = avg; - max = v; + private VectorElementValueObject pickVar( List vectors ) { + if ( vectors == null || vectors.size() <= 1 ) { + throw new IllegalArgumentException( GeneElementExpressionsValueObject.MSG_ERR_VECS_VAR ); + } + DoubleVectorValueObject max = null; + Double varMax = null; + for ( DoubleVectorValueObject v : vectors ) { + double avg = this.getVariance( v.getData() ); + if ( max == null || avg > varMax ) { + varMax = avg; + max = v; + } } + return new VectorElementValueObject( max ); } - return new VectorElementValueObject( max ); - } - private VectorElementValueObject average( List vectors ) { - StringBuilder name = new StringBuilder( GeneElementExpressionsValueObject.AVG_PREFIX ); - Map bioAssayValues = new HashMap<>(); + private VectorElementValueObject average( List vectors ) { + StringBuilder name = new StringBuilder( GeneElementExpressionsValueObject.AVG_PREFIX ); + Map bioAssayValues = new HashMap<>(); - for ( DoubleVectorValueObject vo : vectors ) { + for ( DoubleVectorValueObject vo : vectors ) { - for ( int i = 0; i < vo.getBioAssays().size(); i++ ) { - BioAssayValueObject bvo = vo.getBioAssays().get( i ); + for ( int i = 0; i < vo.getBioAssays().size(); i++ ) { + BioAssayValueObject bvo = vo.getBioAssays().get( i ); - if ( bioAssayValues.containsKey( bvo.getName() ) ) { - bioAssayValues.put( bvo.getName(), bioAssayValues.get( bvo.getName() ) + vo.getData()[i] ); - } else { - bioAssayValues.put( bvo.getName(), vo.getData()[i] ); + if ( bioAssayValues.containsKey( bvo.getName() ) ) { + bioAssayValues.put( bvo.getName(), bioAssayValues.get( bvo.getName() ) + vo.getData()[i] ); + } else { + bioAssayValues.put( bvo.getName(), vo.getData()[i] ); + } } + + name.append( " " ); + name.append( vo.getDesignElement().getName() ); } - name.append( " " ); - name.append( vo.getDesignElement().getName() ); - } + for ( Map.Entry entry : bioAssayValues.entrySet() ) { + entry.setValue( entry.getValue() / vectors.size() ); + } - for ( Map.Entry entry : bioAssayValues.entrySet() ) { - entry.setValue( entry.getValue() / vectors.size() ); + return new VectorElementValueObject( name.toString(), bioAssayValues ); } - return new VectorElementValueObject( name.toString(), bioAssayValues ); - } + private double getVariance( double[] arr ) { + double mean = this.getMean( arr ); + double sum = 0; - private double getVariance( double[] arr ) { - double mean = this.getMean( arr ); - double sum = 0; + for ( double d : arr ) { + sum += ( d - mean ) * ( d - mean ); + } - for ( double d : arr ) { - sum += ( d - mean ) * ( d - mean ); + return sum / ( arr.length - 1 ); } - return sum / ( arr.length - 1 ); - } + private double getMean( double[] arr ) { + double sum = 0; - private double getMean( double[] arr ) { - double sum = 0; + for ( double d : arr ) { + sum += d; + } - for ( double d : arr ) { - sum += d; + return sum / arr.length; } - - return sum / arr.length; } -} -@SuppressWarnings("unused") - // Used in rest api -class VectorElementValueObject { - private String designElementName; - private Map bioAssayExpressionLevels = new HashMap<>(); + @SuppressWarnings("unused") + // Used in rest api + public static class VectorElementValueObject implements Serializable { + private String designElementName; + private Map bioAssayExpressionLevels = new HashMap<>(); - VectorElementValueObject( DoubleVectorValueObject vector ) { - this.designElementName = vector.getDesignElement().getName(); - this.extractProbeLevels( vector ); - } + public VectorElementValueObject() { + super(); + } - VectorElementValueObject( String designElementName, Map bioAssayValues ) { - this.designElementName = designElementName; - for ( Map.Entry entry : bioAssayValues.entrySet() ) { - bioAssayExpressionLevels.put( entry.getKey(), entry.getValue() ); + public VectorElementValueObject( DoubleVectorValueObject vector ) { + this.designElementName = vector.getDesignElement().getName(); + this.extractProbeLevels( vector ); } - } - public String getDesignElementName() { - return designElementName; - } + public VectorElementValueObject( String designElementName, Map bioAssayValues ) { + this.designElementName = designElementName; + for ( Map.Entry entry : bioAssayValues.entrySet() ) { + bioAssayExpressionLevels.put( entry.getKey(), entry.getValue() ); + } + } - public Map getBioAssayExpressionLevels() { - return bioAssayExpressionLevels; - } + public String getDesignElementName() { + return designElementName; + } - private void extractProbeLevels( DoubleVectorValueObject vector ) { + public Map getBioAssayExpressionLevels() { + return bioAssayExpressionLevels; + } - int i; - for ( i = 0; i < vector.getData().length; i++ ) { - double value = vector.getData()[i]; - bioAssayExpressionLevels.put( vector.getBioAssays().get( i ).getName(), value ); + private void extractProbeLevels( DoubleVectorValueObject vector ) { + + int i; + for ( i = 0; i < vector.getData().length; i++ ) { + double value = vector.getData()[i]; + bioAssayExpressionLevels.put( vector.getBioAssays().get( i ).getName(), value ); + } } } } \ No newline at end of file diff --git a/gemma-core/src/main/java/ubic/gemma/model/expression/biomaterial/BioMaterialValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/expression/biomaterial/BioMaterialValueObject.java index ae33efa200..20b882f2cd 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/expression/biomaterial/BioMaterialValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/expression/biomaterial/BioMaterialValueObject.java @@ -43,7 +43,7 @@ @SuppressWarnings({ "unused", "WeakerAccess" }) // Used in frontend @Data @EqualsAndHashCode(of = { "name" }, callSuper = true) -public class BioMaterialValueObject extends IdentifiableValueObject implements Serializable { +public class BioMaterialValueObject extends IdentifiableValueObject { private static final String CHARACTERISTIC_DELIMITER = "::::"; private static final long serialVersionUID = -145137827948521045L; @@ -102,6 +102,7 @@ public class BioMaterialValueObject extends IdentifiableValueObject * Required when using the class as a spring bean. */ public BioMaterialValueObject() { + super(); } public BioMaterialValueObject( Long id ) { @@ -113,7 +114,7 @@ public BioMaterialValueObject( BioMaterial bm ) { } public BioMaterialValueObject( BioMaterial bm, boolean basic ) { - super( bm.getId() ); + super( bm ); this.name = bm.getName(); this.description = bm.getDescription(); diff --git a/gemma-core/src/main/java/ubic/gemma/model/expression/designElement/CompositeSequenceValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/expression/designElement/CompositeSequenceValueObject.java index 40c545415b..edd426d5a5 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/expression/designElement/CompositeSequenceValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/expression/designElement/CompositeSequenceValueObject.java @@ -31,7 +31,7 @@ * @author anton */ @SuppressWarnings({ "unused", "WeakerAccess" }) // Used in frontend -public class CompositeSequenceValueObject extends IdentifiableValueObject implements Serializable { +public class CompositeSequenceValueObject extends IdentifiableValueObject { private static final long serialVersionUID = 4915680501039784666L; @@ -45,6 +45,7 @@ public class CompositeSequenceValueObject extends IdentifiableValueObject implements Serializable { +public class ExperimentalFactorValueObject extends IdentifiableValueObject { private static final long serialVersionUID = -2615804031123874251L; @@ -55,6 +55,7 @@ public class ExperimentalFactorValueObject extends IdentifiableValueObject getSecurableClass() { public Long getSourceExperiment() { return sourceExperiment; } + + public void setSourceExperiment( Long sourceExperiment ) { + this.sourceExperiment = sourceExperiment; + } } diff --git a/gemma-core/src/main/java/ubic/gemma/model/expression/experiment/ExpressionExperimentValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/expression/experiment/ExpressionExperimentValueObject.java index ff863c8c06..3dc4b79dc5 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/expression/experiment/ExpressionExperimentValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/expression/experiment/ExpressionExperimentValueObject.java @@ -68,10 +68,11 @@ public class ExpressionExperimentValueObject extends AbstractCuratableValueObjec /** * Required when using the class as a spring bean. */ - protected ExpressionExperimentValueObject() { + public ExpressionExperimentValueObject() { + super(); } - protected ExpressionExperimentValueObject( Long id ) { + public ExpressionExperimentValueObject( Long id ) { super( id ); } diff --git a/gemma-core/src/main/java/ubic/gemma/model/expression/experiment/FactorValueBasicValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/expression/experiment/FactorValueBasicValueObject.java index 0210b424ae..888c5dae20 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/expression/experiment/FactorValueBasicValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/expression/experiment/FactorValueBasicValueObject.java @@ -31,7 +31,7 @@ @SuppressWarnings("unused") // Used in json serialization @Data @EqualsAndHashCode(of = { "characteristics" }, callSuper = true) -public class FactorValueBasicValueObject extends IdentifiableValueObject implements Serializable { +public class FactorValueBasicValueObject extends IdentifiableValueObject { private static final long serialVersionUID = 3378801249808036785L; @@ -48,6 +48,7 @@ public class FactorValueBasicValueObject extends IdentifiableValueObject implements Serializable { +public class FactorValueValueObject extends IdentifiableValueObject { private static final long serialVersionUID = 3378801249808036785L; @@ -50,6 +50,7 @@ public class FactorValueValueObject extends IdentifiableValueObject * Required when using the class as a spring bean. */ public FactorValueValueObject() { + super(); } public FactorValueValueObject( Long id ) { @@ -57,7 +58,7 @@ public FactorValueValueObject( Long id ) { } public FactorValueValueObject( FactorValue fv ) { - super( fv.getId() ); + super( fv ); if ( fv.getCharacteristics().size() == 1 ) { this.init( fv, fv.getCharacteristics().iterator().next() ); } else if ( fv.getCharacteristics().size() > 1 ) { @@ -79,7 +80,7 @@ public FactorValueValueObject( FactorValue fv ) { * @param value value */ public FactorValueValueObject( FactorValue value, @Nullable Characteristic c ) { - super( value.getId() ); + super( value ); this.init( value, c ); } diff --git a/gemma-core/src/main/java/ubic/gemma/model/expression/experiment/GeeqAdminValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/expression/experiment/GeeqAdminValueObject.java index 1037abba57..875b3e269b 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/expression/experiment/GeeqAdminValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/expression/experiment/GeeqAdminValueObject.java @@ -55,6 +55,7 @@ public class GeeqAdminValueObject extends GeeqValueObject { * Required when using the class as a spring bean */ public GeeqAdminValueObject() { + super(); } public GeeqAdminValueObject( Geeq g ) { diff --git a/gemma-core/src/main/java/ubic/gemma/model/expression/experiment/GeeqValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/expression/experiment/GeeqValueObject.java index c0391b23b8..21b43d881d 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/expression/experiment/GeeqValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/expression/experiment/GeeqValueObject.java @@ -96,10 +96,11 @@ public class GeeqValueObject extends IdentifiableValueObject { */ @SuppressWarnings("WeakerAccess") //Spring needs it to be public public GeeqValueObject() { + super(); } public GeeqValueObject( Geeq g ) { - super( g.getId() ); + super( g ); this.setPublicQualityScore( g.getDetectedQualityScore(), g.getManualQualityScore(), g.isManualQualityOverride() ); this.setPublicSuitabilityScore( g.getDetectedSuitabilityScore(), g.getManualSuitabilityScore(), diff --git a/gemma-core/src/main/java/ubic/gemma/model/expression/experiment/SessionBoundExpressionExperimentSetValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/expression/experiment/SessionBoundExpressionExperimentSetValueObject.java index 84d45ef074..98e4a627be 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/expression/experiment/SessionBoundExpressionExperimentSetValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/expression/experiment/SessionBoundExpressionExperimentSetValueObject.java @@ -53,6 +53,7 @@ public class SessionBoundExpressionExperimentSetValueObject extends ExpressionEx */ @SuppressWarnings("WeakerAccess") // Required by Spring public SessionBoundExpressionExperimentSetValueObject() { + super(); } /** diff --git a/gemma-core/src/main/java/ubic/gemma/model/genome/GeneOntologyTermValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/genome/GeneOntologyTermValueObject.java index 172aa0dcf5..9ec36d4400 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/genome/GeneOntologyTermValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/genome/GeneOntologyTermValueObject.java @@ -1,9 +1,14 @@ package ubic.gemma.model.genome; +import lombok.Getter; +import lombok.Setter; import ubic.basecode.ontology.model.OntologyTerm; -@SuppressWarnings("unused") // Getters used by RS serializer -public class GeneOntologyTermValueObject { +import java.io.Serializable; + +@Getter +@Setter +public class GeneOntologyTermValueObject implements Serializable { private String goId; private String label; private String uri; @@ -12,6 +17,10 @@ public class GeneOntologyTermValueObject { private String term; private boolean isObsolete; + public GeneOntologyTermValueObject() { + super(); + } + public GeneOntologyTermValueObject( String goId, OntologyTerm term ) { this.goId = goId; this.label = term.getLabel(); @@ -21,32 +30,4 @@ public GeneOntologyTermValueObject( String goId, OntologyTerm term ) { this.term = term.getTerm(); this.isObsolete = term.isTermObsolete(); } - - public String getGoId() { - return goId; - } - - public String getLabel() { - return label; - } - - public String getUri() { - return uri; - } - - public String getComment() { - return comment; - } - - public String getLocalName() { - return localName; - } - - public String getTerm() { - return term; - } - - public boolean isObsolete() { - return isObsolete; - } } diff --git a/gemma-core/src/main/java/ubic/gemma/model/genome/PhysicalLocationValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/genome/PhysicalLocationValueObject.java index d8536bf57f..9b721a32a5 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/genome/PhysicalLocationValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/genome/PhysicalLocationValueObject.java @@ -18,7 +18,12 @@ public class PhysicalLocationValueObject extends IdentifiableValueObject implements Serializable { +public class TaxonValueObject extends IdentifiableValueObject { private String scientificName; private String commonName; @@ -40,7 +40,7 @@ public TaxonValueObject() { } public TaxonValueObject( Taxon taxon ) { - super( taxon.getId() ); + super( taxon ); this.setScientificName( taxon.getScientificName() ); this.setCommonName( taxon.getCommonName() ); diff --git a/gemma-core/src/main/java/ubic/gemma/model/genome/biosequence/SequenceType.java b/gemma-core/src/main/java/ubic/gemma/model/genome/biosequence/SequenceType.java index 65ae833752..e751e25cf0 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/genome/biosequence/SequenceType.java +++ b/gemma-core/src/main/java/ubic/gemma/model/genome/biosequence/SequenceType.java @@ -1,7 +1,5 @@ package ubic.gemma.model.genome.biosequence; -import com.fasterxml.jackson.annotation.JsonValue; - import java.util.*; @SuppressWarnings({ "unused", "WeakerAccess" }) // Possible external use @@ -171,7 +169,6 @@ public int compareTo( SequenceType that ) { * @return the underlying value. */ @SuppressWarnings({ "unused", "WeakerAccess" }) // Possible external use - @JsonValue public String getValue() { return this.value; } diff --git a/gemma-core/src/main/java/ubic/gemma/model/genome/gene/DatabaseBackedGeneSetValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/genome/gene/DatabaseBackedGeneSetValueObject.java index 4bcbaa4249..dcc13f30c2 100755 --- a/gemma-core/src/main/java/ubic/gemma/model/genome/gene/DatabaseBackedGeneSetValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/genome/gene/DatabaseBackedGeneSetValueObject.java @@ -44,11 +44,14 @@ public class DatabaseBackedGeneSetValueObject extends GeneSetValueObject { private static final long serialVersionUID = -1360523793656012770L; - /** - * default constructor to satisfy java bean contract - */ public DatabaseBackedGeneSetValueObject() { super(); } + /** + * default constructor to satisfy java bean contract + */ + public DatabaseBackedGeneSetValueObject( GeneSet geneSet ) { + super( geneSet ); + } } diff --git a/gemma-core/src/main/java/ubic/gemma/model/genome/gene/GeneProductValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/genome/gene/GeneProductValueObject.java index eb6c583c47..15dc193c77 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/genome/gene/GeneProductValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/genome/gene/GeneProductValueObject.java @@ -20,7 +20,7 @@ * @author paul */ @SuppressWarnings({ "unused", "WeakerAccess" }) // Used in frontend -public class GeneProductValueObject extends IdentifiableValueObject implements java.io.Serializable { +public class GeneProductValueObject extends IdentifiableValueObject { /** * The serial version UID of this class. Needed for serialization. */ @@ -40,6 +40,7 @@ public class GeneProductValueObject extends IdentifiableValueObject * Required when using the class as a spring bean. */ public GeneProductValueObject() { + super(); } public GeneProductValueObject( Long id ) { @@ -53,7 +54,7 @@ public GeneProductValueObject( Long id ) { * @param entity the GeneProduct to load the values from. */ public GeneProductValueObject( GeneProduct entity ) { - super( entity.getId() ); + super( entity ); this.name = entity.getName(); this.ncbiId = entity.getNcbiGi(); if ( entity.getPhysicalLocation() != null ) { diff --git a/gemma-core/src/main/java/ubic/gemma/model/genome/gene/GeneSetValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/genome/gene/GeneSetValueObject.java index cdd24e6bac..08cb7c21ab 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/genome/gene/GeneSetValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/genome/gene/GeneSetValueObject.java @@ -93,6 +93,12 @@ public GeneSetValueObject( Long id ) { super( id ); } + public GeneSetValueObject( GeneSet geneSet ) { + super( geneSet ); + setName( geneSet.getName() ); + setDescription( geneSet.getDescription() ); + } + @GemmaWebOnly public Long getTaxonId() { return this.taxon != null ? this.taxon.getId() : null; diff --git a/gemma-core/src/main/java/ubic/gemma/model/genome/gene/GeneValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/genome/gene/GeneValueObject.java index 10c61642a2..66e61cb035 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/genome/gene/GeneValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/genome/gene/GeneValueObject.java @@ -108,6 +108,7 @@ public class GeneValueObject extends IdentifiableValueObject implements Se * Required when using the class as a spring bean. */ public GeneValueObject() { + super(); } public GeneValueObject( Long id ) { @@ -120,7 +121,7 @@ public GeneValueObject( Long id ) { * @param gene gene */ public GeneValueObject( Gene gene ) { - super( gene.getId() ); + super( gene ); this.ncbiId = gene.getNcbiGeneId(); this.officialName = gene.getOfficialName(); this.officialSymbol = gene.getOfficialSymbol(); @@ -153,7 +154,7 @@ public GeneValueObject( Gene gene ) { */ @SuppressWarnings("CopyConstructorMissesField") // Only copying constructor argument fields public GeneValueObject( GeneValueObject otherBean ) { - super( otherBean.id ); + super( otherBean ); this.name = otherBean.name; this.ncbiId = otherBean.ncbiId; this.officialSymbol = otherBean.officialSymbol; diff --git a/gemma-core/src/main/java/ubic/gemma/model/genome/gene/phenotype/valueObject/BibliographicPhenotypesValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/genome/gene/phenotype/valueObject/BibliographicPhenotypesValueObject.java index 304ddcb928..97fd14ccec 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/genome/gene/phenotype/valueObject/BibliographicPhenotypesValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/genome/gene/phenotype/valueObject/BibliographicPhenotypesValueObject.java @@ -17,6 +17,7 @@ import ubic.gemma.model.association.phenotype.PhenotypeAssociation; import ubic.gemma.model.common.description.Characteristic; +import java.io.Serializable; import java.util.Collection; import java.util.HashSet; import java.util.Set; @@ -26,7 +27,7 @@ * @author Nicolas */ @SuppressWarnings({ "unused", "WeakerAccess" }) // Used in frontend -public class BibliographicPhenotypesValueObject implements Comparable { +public class BibliographicPhenotypesValueObject implements Comparable, Serializable { private Integer geneNCBI = 0; private String geneName = ""; diff --git a/gemma-core/src/main/java/ubic/gemma/model/genome/gene/phenotype/valueObject/CharacteristicBasicValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/genome/gene/phenotype/valueObject/CharacteristicBasicValueObject.java index d24f17a050..08b2b64689 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/genome/gene/phenotype/valueObject/CharacteristicBasicValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/genome/gene/phenotype/valueObject/CharacteristicBasicValueObject.java @@ -1,9 +1,12 @@ package ubic.gemma.model.genome.gene.phenotype.valueObject; +import lombok.Getter; +import lombok.Setter; import ubic.gemma.model.IdentifiableValueObject; import ubic.gemma.model.common.description.Characteristic; -@SuppressWarnings({ "unused", "WeakerAccess" }) // Used in frontend +@Getter +@Setter public class CharacteristicBasicValueObject extends IdentifiableValueObject { protected String value; protected String valueUri; @@ -14,6 +17,7 @@ public class CharacteristicBasicValueObject extends IdentifiableValueObject extends Identif * Required when using the class as a spring bean. */ public EvidenceValueObject() { + super(); } public EvidenceValueObject( Long id ) { @@ -93,8 +94,8 @@ protected EvidenceValueObject( Long id, Integer geneNCBI, Set { +public class ExternalDatabaseStatisticsValueObject implements Comparable, Serializable { private String name = ""; private String description = ""; diff --git a/gemma-core/src/main/java/ubic/gemma/model/genome/gene/phenotype/valueObject/GeneEvidenceValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/genome/gene/phenotype/valueObject/GeneEvidenceValueObject.java index 7e3d421481..3f1bdf8577 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/genome/gene/phenotype/valueObject/GeneEvidenceValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/genome/gene/phenotype/valueObject/GeneEvidenceValueObject.java @@ -45,6 +45,7 @@ public class GeneEvidenceValueObject extends GeneValueObject { * Required when using the class as a spring bean. */ public GeneEvidenceValueObject() { + super(); } public GeneEvidenceValueObject( Long id ) { diff --git a/gemma-core/src/main/java/ubic/gemma/model/genome/gene/phenotype/valueObject/GenericEvidenceValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/genome/gene/phenotype/valueObject/GenericEvidenceValueObject.java index b7bf674c39..fc4b6555c5 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/genome/gene/phenotype/valueObject/GenericEvidenceValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/genome/gene/phenotype/valueObject/GenericEvidenceValueObject.java @@ -31,6 +31,7 @@ public class GenericEvidenceValueObject extends EvidenceValueObject { +public class PhenotypeAssPubValueObject implements Comparable, Serializable { public static final String PRIMARY = "Primary"; public static final String RELEVANT = "Relevant"; @@ -13,7 +15,7 @@ public class PhenotypeAssPubValueObject implements Comparable { +public class SimpleTreeValueObject implements Comparable, Serializable { // private String _id = ""; private String _parent; @@ -34,6 +35,10 @@ public class SimpleTreeValueObject implements Comparable private boolean dbPhenotype; private List children = new Vector<>(); + public SimpleTreeValueObject() { + super(); + } + /** * @param treeCharacteristicValueObject tree characteristic VO * @param parent the unique ID of the parent (get_id()) diff --git a/gemma-core/src/main/java/ubic/gemma/model/genome/gene/phenotype/valueObject/TreeCharacteristicValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/genome/gene/phenotype/valueObject/TreeCharacteristicValueObject.java index cb33db5138..c3d1a1764f 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/genome/gene/phenotype/valueObject/TreeCharacteristicValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/genome/gene/phenotype/valueObject/TreeCharacteristicValueObject.java @@ -44,6 +44,7 @@ public class TreeCharacteristicValueObject extends CharacteristicValueObject { * Required when using the class as a spring bean. */ public TreeCharacteristicValueObject() { + super(); } public TreeCharacteristicValueObject( Long id, String value, String valueUri ) { diff --git a/gemma-core/src/main/java/ubic/gemma/model/genome/gene/phenotype/valueObject/ValidateEvidenceValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/genome/gene/phenotype/valueObject/ValidateEvidenceValueObject.java index f776713b23..29e1fea338 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/genome/gene/phenotype/valueObject/ValidateEvidenceValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/genome/gene/phenotype/valueObject/ValidateEvidenceValueObject.java @@ -1,10 +1,11 @@ package ubic.gemma.model.genome.gene.phenotype.valueObject; +import java.io.Serializable; import java.util.HashSet; import java.util.Set; @SuppressWarnings({ "unused", "WeakerAccess" }) // Used in frontend -public class ValidateEvidenceValueObject { +public class ValidateEvidenceValueObject implements Serializable { private boolean sameGeneAnnotated = false; private boolean lastUpdateDifferent = false; diff --git a/gemma-core/src/main/java/ubic/gemma/model/genome/sequenceAnalysis/BioSequenceValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/genome/sequenceAnalysis/BioSequenceValueObject.java index b7dc2b2e2b..2288f0e3a6 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/genome/sequenceAnalysis/BioSequenceValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/genome/sequenceAnalysis/BioSequenceValueObject.java @@ -18,12 +18,13 @@ public class BioSequenceValueObject extends IdentifiableValueObject private String sequence; private DatabaseEntryValueObject sequenceDatabaseEntry; private TaxonValueObject taxon; - private ubic.gemma.model.genome.biosequence.SequenceType type; + private SequenceTypeValueObject type; /** * Required when using the class as a spring bean. */ public BioSequenceValueObject() { + super(); } private BioSequenceValueObject( Long id ) { @@ -47,7 +48,7 @@ public static BioSequenceValueObject fromEntity( BioSequence bs ) { vo.setSequenceDatabaseEntry( new DatabaseEntryValueObject( bs.getSequenceDatabaseEntry() ) ); } vo.setLength( bs.getLength() ); - vo.setType( bs.getType() ); + vo.setType( new SequenceTypeValueObject( bs.getType() ) ); vo.setFractionRepeats( bs.getFractionRepeats() ); // FIXME: BioSequence returned by the SearchService might have a null taxon if ( bs.getTaxon() != null ) { @@ -145,11 +146,11 @@ public void setTaxon( TaxonValueObject taxon ) { this.taxon = taxon; } - public ubic.gemma.model.genome.biosequence.SequenceType getType() { + public SequenceTypeValueObject getType() { return this.type; } - public void setType( ubic.gemma.model.genome.biosequence.SequenceType type ) { + public void setType( SequenceTypeValueObject type ) { this.type = type; } diff --git a/gemma-core/src/main/java/ubic/gemma/model/genome/sequenceAnalysis/BlatResultValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/genome/sequenceAnalysis/BlatResultValueObject.java index 000adcc643..80b2c9c024 100644 --- a/gemma-core/src/main/java/ubic/gemma/model/genome/sequenceAnalysis/BlatResultValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/model/genome/sequenceAnalysis/BlatResultValueObject.java @@ -56,6 +56,7 @@ public class BlatResultValueObject extends IdentifiableValueObject { * Required when using the class as a spring bean. */ public BlatResultValueObject() { + super(); } public BlatResultValueObject( Long id ) { diff --git a/gemma-core/src/main/java/ubic/gemma/model/genome/sequenceAnalysis/SequenceTypeValueObject.java b/gemma-core/src/main/java/ubic/gemma/model/genome/sequenceAnalysis/SequenceTypeValueObject.java new file mode 100644 index 0000000000..ee6392d6ca --- /dev/null +++ b/gemma-core/src/main/java/ubic/gemma/model/genome/sequenceAnalysis/SequenceTypeValueObject.java @@ -0,0 +1,32 @@ +package ubic.gemma.model.genome.sequenceAnalysis; + +import com.fasterxml.jackson.annotation.JsonValue; +import lombok.Data; +import ubic.gemma.model.genome.biosequence.SequenceType; + +import java.io.Serializable; + +/** + * @see SequenceType + */ +public class SequenceTypeValueObject implements Serializable { + + private String value; + + public SequenceTypeValueObject() { + + } + + public SequenceTypeValueObject( SequenceType sequenceType ) { + this.value = sequenceType.getValue(); + } + + @JsonValue + public String getValue() { + return this.value; + } + + public void setValue( String value ) { + this.value = value; + } +} diff --git a/gemma-core/src/main/java/ubic/gemma/persistence/service/association/coexpression/CoexpressionCacheValueObject.java b/gemma-core/src/main/java/ubic/gemma/persistence/service/association/coexpression/CoexpressionCacheValueObject.java index a1a0316bb9..f16452437f 100644 --- a/gemma-core/src/main/java/ubic/gemma/persistence/service/association/coexpression/CoexpressionCacheValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/persistence/service/association/coexpression/CoexpressionCacheValueObject.java @@ -26,16 +26,20 @@ public class CoexpressionCacheValueObject implements Serializable { private static final long serialVersionUID = 184287422449009209L; - private final Long queryGene; - private final Long coexpGene; - private final int support; - private final boolean positiveCorrelation; + private Long queryGene; + private Long coexpGene; + private int support; + private boolean positiveCorrelation; private String coexGeneSymbol; // possibly don't store here? private String queryGeneSymbol; // possibly don't store here? private Long supportDetailsId; private Collection supportingDatasets; private CompressedLongSet testedInDatasets; + public CoexpressionCacheValueObject() { + super(); + } + /** * @param vo coexpression VO */ diff --git a/gemma-core/src/main/java/ubic/gemma/persistence/service/association/coexpression/CoexpressionValueObject.java b/gemma-core/src/main/java/ubic/gemma/persistence/service/association/coexpression/CoexpressionValueObject.java index e1425ad7e0..563206cb0c 100644 --- a/gemma-core/src/main/java/ubic/gemma/persistence/service/association/coexpression/CoexpressionValueObject.java +++ b/gemma-core/src/main/java/ubic/gemma/persistence/service/association/coexpression/CoexpressionValueObject.java @@ -22,6 +22,7 @@ import org.apache.commons.lang3.StringUtils; import ubic.gemma.model.association.coexpression.Gene2GeneCoexpression; +import java.io.Serializable; import java.util.Collection; import java.util.Set; @@ -35,11 +36,11 @@ * @author Paul */ @SuppressWarnings({ "unused", "WeakerAccess" }) // Used in frontend -public class CoexpressionValueObject implements Comparable { +public class CoexpressionValueObject implements Comparable, Serializable { - private final Long coexGeneId; - private final boolean positiveCorrelation; - private final Long queryGeneId; + private Long coexGeneId; + private boolean positiveCorrelation; + private Long queryGeneId; private String coexGeneSymbol; /** * If true, this means the results were trimmed to a subset. @@ -80,6 +81,10 @@ public class CoexpressionValueObject implements Comparable testedInDatasets = null; + public CoexpressionValueObject() { + super(); + } + /** * Construct a value object. The "tested-in" component is not filled in, it must be done later. * diff --git a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/designElement/CompositeSequenceServiceImpl.java b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/designElement/CompositeSequenceServiceImpl.java index e3ff0d3c81..b95447b64f 100644 --- a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/designElement/CompositeSequenceServiceImpl.java +++ b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/designElement/CompositeSequenceServiceImpl.java @@ -215,9 +215,8 @@ public Collection getGeneMappingSummary( BioSequence biologi /* * Make a dummy blat result */ - blatResult = new BlatResultValueObject(); + blatResult = new BlatResultValueObject( biologicalCharacteristic.getId() ); blatResult.setQuerySequence( BioSequenceValueObject.fromEntity( biologicalCharacteristic ) ); - blatResult.setId( biologicalCharacteristic.getId() ); } if ( blatResult == null ) { diff --git a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentServiceImpl.java b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentServiceImpl.java index cefc29617d..808446adf2 100755 --- a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentServiceImpl.java +++ b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentServiceImpl.java @@ -24,8 +24,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import ubic.gemma.core.analysis.preprocess.batcheffects.BatchConfoundUtils; import ubic.gemma.core.analysis.preprocess.batcheffects.BatchConfound; -import ubic.gemma.core.analysis.preprocess.batcheffects.BatchConfoundValueObject; import ubic.gemma.core.analysis.preprocess.batcheffects.BatchEffectDetails; import ubic.gemma.core.analysis.preprocess.batcheffects.BatchInfoPopulationServiceImpl; import ubic.gemma.core.analysis.preprocess.svd.SVDService; @@ -509,9 +509,9 @@ public String getBatchConfound( ExpressionExperiment ee ) { return null; } - Collection confounds; + Collection confounds; try { - confounds = BatchConfound.test( ee ); + confounds = BatchConfoundUtils.test( ee ); } catch ( NotStrictlyPositiveException e ) { AbstractService.log.error( "Batch confound test threw a NonStrictlyPositiveException! Returning null." ); return null; @@ -519,10 +519,10 @@ public String getBatchConfound( ExpressionExperiment ee ) { StringBuilder result = new StringBuilder(); // Confounds have to be sorted in order to always get the same string - List listConfounds = new ArrayList<>( confounds ); - listConfounds.sort( Comparator.comparing( BatchConfoundValueObject::toString ) ); + List listConfounds = new ArrayList<>( confounds ); + listConfounds.sort( Comparator.comparing( BatchConfound::toString ) ); - for ( BatchConfoundValueObject c : listConfounds ) { + for ( BatchConfound c : listConfounds ) { if ( c.getP() < ExpressionExperimentServiceImpl.BATCH_CONFOUND_THRESHOLD ) { String factorName = c.getEf().getName(); if ( result.toString().isEmpty() ) { @@ -542,8 +542,8 @@ public String getBatchConfound( ExpressionExperiment ee ) { if ( !subSets.isEmpty() ) { for ( ExpressionExperimentSubSet subset : subSets ) { try { - confounds = BatchConfound.test( subset ); - for ( BatchConfoundValueObject c : confounds ) { + confounds = BatchConfoundUtils.test( subset ); + for ( BatchConfound c : confounds ) { if ( c.getP() < ExpressionExperimentServiceImpl.BATCH_CONFOUND_THRESHOLD ) { result.append( "

Confound still exists for " + c.getEf().getName() + " in " + subset ); } diff --git a/gemma-core/src/main/java/ubic/gemma/persistence/service/genome/gene/GeneSetDaoImpl.java b/gemma-core/src/main/java/ubic/gemma/persistence/service/genome/gene/GeneSetDaoImpl.java index 4e6357490f..b080cfd11b 100644 --- a/gemma-core/src/main/java/ubic/gemma/persistence/service/genome/gene/GeneSetDaoImpl.java +++ b/gemma-core/src/main/java/ubic/gemma/persistence/service/genome/gene/GeneSetDaoImpl.java @@ -239,11 +239,8 @@ public void thaw( final GeneSet geneSet ) { } private DatabaseBackedGeneSetValueObject fillValueObject( GeneSet geneSet, Taxon taxon, Long membersCount ) { - DatabaseBackedGeneSetValueObject dvo = new DatabaseBackedGeneSetValueObject(); + DatabaseBackedGeneSetValueObject dvo = new DatabaseBackedGeneSetValueObject( geneSet ); dvo.setSize( membersCount.intValue() ); - dvo.setId( geneSet.getId() ); - dvo.setName( geneSet.getName() ); - dvo.setDescription( geneSet.getDescription() ); if ( taxon != null ) { dvo.setTaxon( new TaxonValueObject( taxon ) ); } else { diff --git a/gemma-core/src/test/java/ubic/gemma/core/search/SearchServiceVoConversionTest.java b/gemma-core/src/test/java/ubic/gemma/core/search/SearchServiceVoConversionTest.java index a67fd2c37e..291f7385f7 100644 --- a/gemma-core/src/test/java/ubic/gemma/core/search/SearchServiceVoConversionTest.java +++ b/gemma-core/src/test/java/ubic/gemma/core/search/SearchServiceVoConversionTest.java @@ -56,15 +56,12 @@ public void setUp() { ee.setId( 12L ); gs = new GeneSet(); gs.setId( 13L ); - phenotypeAssociation = new CharacteristicValueObject(); - phenotypeAssociation.setId( 14L ); + phenotypeAssociation = new CharacteristicValueObject( 14L ); when( arrayDesignService.loadValueObject( any( ArrayDesign.class ) ) ).thenAnswer( a -> new ArrayDesignValueObject( a.getArgument( 0, ArrayDesign.class ) ) ); when( expressionExperimentService.loadValueObject( any( ExpressionExperiment.class ) ) ).thenAnswer( a -> new ExpressionExperimentValueObject( a.getArgument( 0, ExpressionExperiment.class ) ) ); when( geneSetService.loadValueObject( any( GeneSet.class ) ) ).thenAnswer( a -> { GeneSet geneSet = a.getArgument( 0, GeneSet.class ); - DatabaseBackedGeneSetValueObject dbgsvo = new DatabaseBackedGeneSetValueObject(); - dbgsvo.setId( geneSet.getId() ); - return dbgsvo; + return new DatabaseBackedGeneSetValueObject( geneSet ); } ); } diff --git a/gemma-core/src/test/java/ubic/gemma/core/util/StrictBeanDefinitionValidatorTest.java b/gemma-core/src/test/java/ubic/gemma/core/util/StrictBeanDefinitionValidatorTest.java new file mode 100644 index 0000000000..363990f31a --- /dev/null +++ b/gemma-core/src/test/java/ubic/gemma/core/util/StrictBeanDefinitionValidatorTest.java @@ -0,0 +1,93 @@ +package ubic.gemma.core.util; + +import org.junit.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.context.MessageSource; +import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider; +import org.springframework.core.type.filter.AnnotationTypeFilter; +import org.springframework.core.type.filter.RegexPatternTypeFilter; +import org.springframework.validation.AbstractBindingResult; +import org.springframework.validation.BeanPropertyBindingResult; +import org.springframework.validation.Errors; +import ubic.gemma.core.util.test.BaseSpringContextTest; +import ubic.gemma.model.ValueObject; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assumptions.assumeThat; + +public class StrictBeanDefinitionValidatorTest extends BaseSpringContextTest { + + @ValueObject + public static class TestAnnotatedVo implements Serializable { + + } + + public static class TestImplicitValueObject implements Serializable { + + } + + @Autowired + private MessageSource messageSource; + + @Test + public void test() throws Exception { + ClassPathScanningCandidateComponentProvider valueObjectProvider = new ClassPathScanningCandidateComponentProvider( false ); + valueObjectProvider.addIncludeFilter( new RegexPatternTypeFilter( Pattern.compile( ".+ValueObject$" ) ) ); + valueObjectProvider.addIncludeFilter( new AnnotationTypeFilter( ValueObject.class ) ); + Set beanDefinitions = valueObjectProvider.findCandidateComponents( "ubic.gemma" ); + assertThat( beanDefinitions ) + .extracting( "beanClassName" ) + .contains( TestAnnotatedVo.class.getName(), TestImplicitValueObject.class.getName() ); + Map invalidBeans = new HashMap<>(); + StrictBeanDefinitionValidator validator = new StrictBeanDefinitionValidator( true ); + for ( BeanDefinition beanDefinition : beanDefinitions ) { + Errors errors = new BeanDefinitionBindingResult( beanDefinition ); + validator.validate( beanDefinition, errors ); + if ( errors.hasErrors() ) { + invalidBeans.put( beanDefinition, errors ); + } + } + String invalidBeansSummary = invalidBeans.entrySet().stream() + .map( e -> String.format( "\t%s: %s\n\t\t%s", e.getKey().getBeanClassName(), + e.getValue().getGlobalErrors().stream() + .map( f -> messageSource.getMessage( f, Locale.getDefault() ) ) + .collect( Collectors.joining( ", " ) ), + e.getValue().getFieldErrors().stream() + .map( f -> f.getField() + " " + messageSource.getMessage( f, Locale.getDefault() ) ) + .collect( Collectors.joining( "\n\t\t" ) ) ) ) + .collect( Collectors.joining( "\n\n" ) ); + assumeThat( invalidBeans ) + .withFailMessage( String.format( "The following %d value object beans are invalid:\n\n%s", invalidBeans.size(), invalidBeansSummary ) ) + .isEmpty(); + } + + /** + * Similar to {@link BeanPropertyBindingResult}, but applies to the bean structure instead of content. + * @author poirigui + */ + private static class BeanDefinitionBindingResult extends AbstractBindingResult { + + public BeanDefinitionBindingResult( BeanDefinition beanDefinition ) { + super( beanDefinition.getBeanClassName() ); + } + + @Override + public Object getTarget() { + return null; + } + + @Override + protected Object getActualFieldValue( String field ) { + return null; + } + } +} \ No newline at end of file From 9dd95a8d8a16e2d0b55e0700190e867b7a128df6 Mon Sep 17 00:00:00 2001 From: Guillaume Poirier-Morency Date: Mon, 12 Dec 2022 10:54:22 -0500 Subject: [PATCH 11/12] Fix timezone in AffyScanDateExtractorTest --- .../preprocess/batcheffects/AffyScanDateExtractorTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gemma-core/src/test/java/ubic/gemma/core/analysis/preprocess/batcheffects/AffyScanDateExtractorTest.java b/gemma-core/src/test/java/ubic/gemma/core/analysis/preprocess/batcheffects/AffyScanDateExtractorTest.java index 1f8610a205..7123b96e80 100644 --- a/gemma-core/src/test/java/ubic/gemma/core/analysis/preprocess/batcheffects/AffyScanDateExtractorTest.java +++ b/gemma-core/src/test/java/ubic/gemma/core/analysis/preprocess/batcheffects/AffyScanDateExtractorTest.java @@ -21,6 +21,7 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; +import java.util.TimeZone; import java.util.zip.GZIPInputStream; import static org.junit.Assert.assertEquals; @@ -39,6 +40,7 @@ public void testExtractInputStreamGCOS() throws Exception { Date actual = extractor.extract( is ); DateFormat formatter = new SimpleDateFormat( "MM/dd/yy hh:mm:ss", Locale.ENGLISH ); + formatter.setTimeZone( TimeZone.getTimeZone( "America/Vancouver" ) ); Date expected = formatter.parse( "08/15/08 7:15:36" ); assertEquals( expected, actual ); From 3ce66c55d0d1eb4464cf1f1159436e78fab9ecd3 Mon Sep 17 00:00:00 2001 From: Guillaume Poirier-Morency Date: Mon, 12 Dec 2022 11:05:23 -0500 Subject: [PATCH 12/12] Fix resolution of subproperties in getObjectFilter() --- .../persistence/service/AbstractFilteringVoEnabledService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/gemma-core/src/main/java/ubic/gemma/persistence/service/AbstractFilteringVoEnabledService.java b/gemma-core/src/main/java/ubic/gemma/persistence/service/AbstractFilteringVoEnabledService.java index 0e31d8d672..3be4b1c337 100644 --- a/gemma-core/src/main/java/ubic/gemma/persistence/service/AbstractFilteringVoEnabledService.java +++ b/gemma-core/src/main/java/ubic/gemma/persistence/service/AbstractFilteringVoEnabledService.java @@ -84,7 +84,6 @@ protected static class ObjectFilterPropertyMeta { * @see #getSort(String, Sort.Direction) */ protected ObjectFilterPropertyMeta getObjectFilterPropertyMeta( String propertyName ) throws NoSuchFieldException { - EntityUtils.getDeclaredField( voDao.getElementClass(), propertyName ); return new ObjectFilterPropertyMeta( voDao.getObjectAlias(), propertyName, EntityUtils.getDeclaredFieldType( propertyName, voDao.getElementClass() ) ); } }