bioAssays );
+
void thawLite( BioAssayDimension bioAssayDimension );
void thaw( BioAssayDimension bioAssayDimension );
diff --git a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/bioAssayData/BioAssayDimensionDaoImpl.java b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/bioAssayData/BioAssayDimensionDaoImpl.java
index 248cf01b42..b3b2d72a0b 100644
--- a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/bioAssayData/BioAssayDimensionDaoImpl.java
+++ b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/bioAssayData/BioAssayDimensionDaoImpl.java
@@ -27,20 +27,19 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.util.Assert;
-import ubic.gemma.model.common.quantitationtype.QuantitationType;
import ubic.gemma.model.expression.bioAssay.BioAssay;
import ubic.gemma.model.expression.bioAssayData.BioAssayDimension;
import ubic.gemma.model.expression.bioAssayData.BioAssayDimensionValueObject;
-import ubic.gemma.model.expression.experiment.ExpressionExperiment;
import ubic.gemma.model.expression.experiment.FactorValue;
import ubic.gemma.persistence.service.AbstractVoEnabledDao;
-import javax.annotation.Nullable;
import java.util.Collection;
+import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import static ubic.gemma.persistence.service.expression.biomaterial.BioMaterialUtils.visitBioMaterials;
+import static ubic.gemma.persistence.util.QueryUtils.optimizeIdentifiableParameterList;
/**
*
@@ -107,6 +106,19 @@ public BioAssayDimension find( BioAssayDimension bioAssayDimension ) {
return null;
}
+ @Override
+ public Collection findByBioAssayContainsAll( Collection bioAssays ) {
+ if ( bioAssays.isEmpty() ) {
+ return Collections.emptySet();
+ }
+ //noinspection unchecked
+ return getSessionFactory().getCurrentSession()
+ .createQuery( "select bad from BioAssayDimension bad join bad.bioAssays ba where ba in :bas group by bad having count(ba) = :numBas" )
+ .setParameterList( "bas", optimizeIdentifiableParameterList( bioAssays ) )
+ .setParameter( "numBas", bioAssays.stream().distinct().count() )
+ .list();
+ }
+
@Override
public void thawLite( final BioAssayDimension bioAssayDimension ) {
Hibernate.initialize( bioAssayDimension );
diff --git a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/bioAssayData/BioAssayDimensionService.java b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/bioAssayData/BioAssayDimensionService.java
index 1a244e9351..4984a2eb71 100644
--- a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/bioAssayData/BioAssayDimensionService.java
+++ b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/bioAssayData/BioAssayDimensionService.java
@@ -19,13 +19,14 @@
package ubic.gemma.persistence.service.expression.bioAssayData;
import org.springframework.security.access.annotation.Secured;
-import ubic.gemma.model.common.quantitationtype.QuantitationType;
+import ubic.gemma.model.expression.bioAssay.BioAssay;
import ubic.gemma.model.expression.bioAssayData.BioAssayDimension;
import ubic.gemma.model.expression.bioAssayData.BioAssayDimensionValueObject;
-import ubic.gemma.model.expression.experiment.ExpressionExperiment;
import ubic.gemma.persistence.service.BaseImmutableService;
import ubic.gemma.persistence.service.BaseVoEnabledService;
+import java.util.Collection;
+
/**
* @author Paul
*/
@@ -40,6 +41,9 @@ public interface BioAssayDimensionService
@Secured({ "IS_AUTHENTICATED_ANONYMOUSLY" })
BioAssayDimension create( BioAssayDimension bioAssayDimension );
+ @Secured({ "IS_AUTHENTICATED_ANONYMOUSLY" })
+ Collection findByBioAssayContainsAll( Collection bioAssays );
+
@Override
@Secured({ "GROUP_USER" })
void remove( BioAssayDimension bioAssayDimension );
diff --git a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/bioAssayData/BioAssayDimensionServiceImpl.java b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/bioAssayData/BioAssayDimensionServiceImpl.java
index cab7c006c8..9d20a91314 100644
--- a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/bioAssayData/BioAssayDimensionServiceImpl.java
+++ b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/bioAssayData/BioAssayDimensionServiceImpl.java
@@ -21,12 +21,13 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
-import ubic.gemma.model.common.quantitationtype.QuantitationType;
+import ubic.gemma.model.expression.bioAssay.BioAssay;
import ubic.gemma.model.expression.bioAssayData.BioAssayDimension;
import ubic.gemma.model.expression.bioAssayData.BioAssayDimensionValueObject;
-import ubic.gemma.model.expression.experiment.ExpressionExperiment;
import ubic.gemma.persistence.service.AbstractVoEnabledService;
+import java.util.Collection;
+
/**
*
* Spring Service base class for BioAssayDimensionService
, provides access to all services and entities
@@ -48,6 +49,12 @@ public BioAssayDimensionServiceImpl( BioAssayDimensionDao bioAssayDimensionDao )
this.bioAssayDimensionDao = bioAssayDimensionDao;
}
+ @Override
+ @Transactional(readOnly = true)
+ public Collection findByBioAssayContainsAll( Collection bioAssays) {
+ return bioAssayDimensionDao.findByBioAssayContainsAll( bioAssays );
+ }
+
@Override
@Transactional(readOnly = true)
public BioAssayDimension thawLite( BioAssayDimension bioAssayDimension ) {
diff --git a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/biomaterial/BioMaterialDao.java b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/biomaterial/BioMaterialDao.java
index eff66cd0d3..55bf2f6eb0 100644
--- a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/biomaterial/BioMaterialDao.java
+++ b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/biomaterial/BioMaterialDao.java
@@ -18,6 +18,7 @@
*/
package ubic.gemma.persistence.service.expression.biomaterial;
+import ubic.gemma.model.expression.bioAssay.BioAssay;
import ubic.gemma.model.expression.biomaterial.BioMaterial;
import ubic.gemma.model.expression.biomaterial.BioMaterialValueObject;
import ubic.gemma.model.expression.experiment.ExperimentalFactor;
@@ -26,6 +27,7 @@
import java.util.Collection;
import java.util.List;
+import java.util.Map;
/**
* @see BioMaterial
@@ -36,22 +38,29 @@ public interface BioMaterialDao extends BaseVoEnabledDao
- * All the sub-biomaterials are visited recursively.
+ * @param direct if true, only direct sub-biomaterials are retained, otherwise the entire hierarchy is visited
+ * recursively.
*/
- List findSubBioMaterials( BioMaterial bioMaterial );
+ List findSubBioMaterials( BioMaterial bioMaterial, boolean direct );
- List findSubBioMaterials( Collection bioMaterial );
+ /**
+ * Find all the sub-biomaterials for a given biomaterial related by {@link BioMaterial#getSourceBioMaterial()}.
+ * @param bioMaterials a collection of biomaterials to visit
+ * @param direct if true, only direct sub-biomaterials are retained, otherwise the entire hierarchy is visited
+ * recursively.
+ */
+ List findSubBioMaterials( Collection bioMaterials, boolean direct );
Collection findByExperiment( ExpressionExperiment experiment );
Collection findByFactor( ExperimentalFactor experimentalFactor );
/**
- * @param bioMaterialId biomaterial id
- * @return the experiment the biomaterial appears in
+ * Obtain all the experiments a biomaterial is used in from its hierarchy.
+ *
+ * This also includes experiments that are using this via one of their parent?
*/
- ExpressionExperiment getExpressionExperiment( Long bioMaterialId );
+ Map> getExpressionExperiments( BioMaterial bm );
/**
* Thaw the given BioMaterial.
diff --git a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/biomaterial/BioMaterialDaoImpl.java b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/biomaterial/BioMaterialDaoImpl.java
index 39e3281077..71204bdfba 100644
--- a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/biomaterial/BioMaterialDaoImpl.java
+++ b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/biomaterial/BioMaterialDaoImpl.java
@@ -25,6 +25,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.util.Assert;
+import ubic.gemma.model.expression.bioAssay.BioAssay;
import ubic.gemma.model.expression.biomaterial.BioMaterial;
import ubic.gemma.model.expression.biomaterial.BioMaterialValueObject;
import ubic.gemma.model.expression.experiment.ExperimentalFactor;
@@ -95,12 +96,12 @@ public BioMaterial find( BioMaterial bioMaterial ) {
}
@Override
- public List findSubBioMaterials( BioMaterial bioMaterial ) {
- return findSubBioMaterials( Collections.singleton( bioMaterial ) );
+ public List findSubBioMaterials( BioMaterial bioMaterial, boolean direct ) {
+ return findSubBioMaterials( Collections.singleton( bioMaterial ), direct );
}
@Override
- public List findSubBioMaterials( Collection bioMaterials ) {
+ public List findSubBioMaterials( Collection bioMaterials, boolean direct ) {
if ( bioMaterials.isEmpty() ) {
return Collections.emptyList();
}
@@ -121,6 +122,9 @@ public List findSubBioMaterials( Collection bioMateria
// drop already visited bioassays
Assert.state( !fringe.removeAll( visited ), "Circular biomaterial detected!" );
results.addAll( fringe );
+ if ( direct ) {
+ break;
+ }
}
return results;
}
@@ -160,10 +164,16 @@ public Collection findByFactor( ExperimentalFactor experimentalFact
}
@Override
- public ExpressionExperiment getExpressionExperiment( Long bioMaterialId ) {
- return ( ExpressionExperiment ) this.getSessionFactory().getCurrentSession().createQuery(
- "select distinct e from ExpressionExperiment e inner join e.bioAssays ba inner join ba.sampleUsed bm where bm.id =:bmid " )
- .setParameter( "bmid", bioMaterialId ).uniqueResult();
+ public Map> getExpressionExperiments( BioMaterial bm ) {
+ Set bms = new HashSet<>();
+ visitBioMaterials( bm, bms::add );
+ //noinspection unchecked
+ List results = ( List ) this.getSessionFactory().getCurrentSession()
+ .createQuery( "select bm, ba, e from ExpressionExperiment e join e.bioAssays ba join ba.sampleUsed bm where bm in :bms group by bm, ba, e" )
+ .setParameterList( "bms", bms )
+ .list();
+ return results.stream().collect( Collectors.groupingBy( row -> ( BioMaterial ) row[0],
+ Collectors.toMap( row -> ( BioAssay ) row[1], row -> ( ExpressionExperiment ) row[2] ) ) );
}
@Override
diff --git a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/biomaterial/BioMaterialService.java b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/biomaterial/BioMaterialService.java
index 31cfb77b16..19563ca8ea 100644
--- a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/biomaterial/BioMaterialService.java
+++ b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/biomaterial/BioMaterialService.java
@@ -20,6 +20,7 @@
import org.springframework.security.access.annotation.Secured;
import ubic.gemma.model.common.description.Characteristic;
+import ubic.gemma.model.expression.bioAssay.BioAssay;
import ubic.gemma.model.expression.biomaterial.BioMaterial;
import ubic.gemma.model.expression.biomaterial.BioMaterialValueObject;
import ubic.gemma.model.expression.experiment.ExperimentalFactor;
@@ -29,6 +30,7 @@
import ubic.gemma.persistence.service.BaseVoEnabledService;
import javax.annotation.CheckReturnValue;
+import javax.annotation.Nullable;
import java.util.Collection;
import java.util.Map;
@@ -47,10 +49,22 @@ public interface BioMaterialService extends BaseService, BaseVoEnab
@Secured({ "GROUP_USER", "ACL_SECURABLE_EDIT" })
BioMaterial copy( BioMaterial bioMaterial );
- @Secured({ "IS_AUTHENTICATED_ANONYMOUSLY", "ACL_SECURABLE__READ" })
+ /**
+ * @see BioMaterialDao#findSubBioMaterials(BioMaterial, boolean)
+ */
+ @Secured({ "IS_AUTHENTICATED_ANONYMOUSLY", "ACL_SECURABLE_READ" })
+ Collection findSubBioMaterials( BioMaterial bioMaterial, boolean direct );
+
+ /**
+ * Find the siblings of a given biomaterial.
+ */
+ @Secured({ "IS_AUTHENTICATED_ANONYMOUSLY", "ACL_SECURABLE_READ" })
+ Collection findSiblings( BioMaterial bioMaterial );
+
+ @Secured({ "IS_AUTHENTICATED_ANONYMOUSLY", "ACL_SECURABLE_READ" })
Collection findByExperiment( ExpressionExperiment experiment );
- @Secured({ "IS_AUTHENTICATED_ANONYMOUSLY", "ACL_SECURABLE__READ" })
+ @Secured({ "IS_AUTHENTICATED_ANONYMOUSLY", "ACL_SECURABLE_READ" })
Collection findByFactor( ExperimentalFactor experimentalFactor );
@Override
@@ -81,8 +95,9 @@ public interface BioMaterialService extends BaseService, BaseVoEnab
@Secured({ "GROUP_USER", "ACL_SECURABLE_EDIT" })
void update( BioMaterial bioMaterial );
- @Secured({ "IS_AUTHENTICATED_ANONYMOUSLY", "AFTER_ACL_READ" })
- ExpressionExperiment getExpressionExperiment( Long id );
+ @Nullable
+ @Secured({ "IS_AUTHENTICATED_ANONYMOUSLY", "AFTER_ACL_MAP_READ" })
+ Map> getExpressionExperiments( BioMaterial bm );
@CheckReturnValue
@Secured({ "IS_AUTHENTICATED_ANONYMOUSLY", "ACL_SECURABLE__READ" })
diff --git a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/biomaterial/BioMaterialServiceImpl.java b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/biomaterial/BioMaterialServiceImpl.java
index ee52438896..290a065b64 100644
--- a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/biomaterial/BioMaterialServiceImpl.java
+++ b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/biomaterial/BioMaterialServiceImpl.java
@@ -25,6 +25,7 @@
import ubic.gemma.model.common.measurement.MeasurementType;
import ubic.gemma.model.common.quantitationtype.PrimitiveType;
import ubic.gemma.model.expression.bioAssay.BioAssay;
+import ubic.gemma.model.expression.bioAssayData.BioAssayDimension;
import ubic.gemma.model.expression.biomaterial.BioMaterial;
import ubic.gemma.model.expression.biomaterial.BioMaterialValueObject;
import ubic.gemma.model.expression.experiment.ExperimentalFactor;
@@ -71,6 +72,23 @@ public BioMaterial copy( BioMaterial bioMaterial ) {
return this.bioMaterialDao.copy( bioMaterial );
}
+ @Override
+ @Transactional(readOnly = true)
+ public Collection findSubBioMaterials( BioMaterial bioMaterial, boolean direct ) {
+ return bioMaterialDao.findSubBioMaterials( bioMaterial, direct );
+ }
+
+ @Override
+ @Transactional(readOnly = true)
+ public Collection findSiblings( BioMaterial bioMaterial ) {
+ if ( bioMaterial.getSourceBioMaterial() == null ) {
+ return Collections.emptySet();
+ }
+ Collection siblings = findSubBioMaterials( bioMaterial.getSourceBioMaterial(), true );
+ siblings.remove( bioMaterial );
+ return siblings;
+ }
+
@Override
@Transactional(readOnly = true)
public Collection findByExperiment( ExpressionExperiment experiment ) {
@@ -85,8 +103,10 @@ public Collection findByFactor( ExperimentalFactor experimentalFact
@Override
@Transactional(readOnly = true)
- public ExpressionExperiment getExpressionExperiment( Long id ) {
- return this.bioMaterialDao.getExpressionExperiment( id );
+ public Map> getExpressionExperiments( BioMaterial bm ) {
+ // source biomaterials need to be visited, so this must be in the session
+ bm = ensureInSession( bm );
+ return this.bioMaterialDao.getExpressionExperiments( bm );
}
@Override
diff --git a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentDao.java b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentDao.java
index d2520ed4d8..2ff258401f 100644
--- a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentDao.java
+++ b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentDao.java
@@ -25,10 +25,7 @@
import ubic.gemma.persistence.util.Sort;
import javax.annotation.Nullable;
-import java.util.Collection;
-import java.util.Date;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
import java.util.stream.Stream;
/**
@@ -233,6 +230,8 @@ Map> getSampleRemovalEvents(
Collection getSubSets( ExpressionExperiment expressionExperiment );
+ Map> getSubSetsByDimension( ExpressionExperiment expressionExperiment );
+
Map getTaxa( Collection bioAssaySets );
/**
@@ -293,27 +292,48 @@ Map> getSampleRemovalEvents(
void thawProcessedVectors( ExpressionExperiment ee );
+ Collection getAnnotationsBySubSets( ExpressionExperiment ee );
+
+ /**
+ * Obtain sample-level annotations for an experiment.
+ */
Collection getAnnotationsByBioMaterials( ExpressionExperiment ee );
+ /**
+ * Obtain sample-level annotations for a given subset.
+ */
+ Collection getAnnotationsByBioMaterials( ExpressionExperimentSubSet subset );
+
+ /**
+ * Obtain all the statements in the experimental design of an experiment.
+ */
Collection getAnnotationsByFactorValues( ExpressionExperiment ee );
/**
* Obtain all annotations, grouped by applicable level.
+ *
+ * This uses the {@code EE2C} table under the hood.
*/
Map, List> getAllAnnotations( ExpressionExperiment expressionExperiment );
/**
* Obtain experiment-level annotations.
+ *
+ * This uses the {@code EE2C} table under the hood.
*/
List getExperimentAnnotations( ExpressionExperiment expressionExperiment );
/**
* Obtain sample-level annotations.
+ *
+ * This uses the {@code EE2C} table under the hood.
*/
List getBioMaterialAnnotations( ExpressionExperiment expressionExperiment );
/**
* Obtain experimental design-level annotations.
+ *
+ * This uses the {@code EE2C} table under the hood.
*/
List getExperimentalDesignAnnotations( ExpressionExperiment expressionExperiment );
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 79397e47c6..7e02a37223 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
@@ -436,26 +436,44 @@ public Map getAnnotationCounts( Collection ids ) {
return results;
}
+ @Override
+ public Collection getAnnotationsBySubSets( ExpressionExperiment ee ) {
+ //noinspection unchecked
+ return getSessionFactory().getCurrentSession()
+ .createQuery( "select distinct c from ExpressionExperimentSubSet subset "
+ + "join subset.characteristics c "
+ + "where subset.sourceExperiment = :ee" )
+ .setParameter( "ee", ee )
+ .list();
+ }
+
@Override
public Collection getAnnotationsByBioMaterials( ExpressionExperiment ee ) {
- /*
- * Note we're not using 'distinct' here but the 'equals' for AnnotationValueObject should aggregate these. More
- * work to do.
- */
//noinspection unchecked
return this.getSessionFactory().getCurrentSession()
- .createQuery( "select c from ExpressionExperiment e "
+ .createQuery( "select distinct c from ExpressionExperiment e "
+ "join e.bioAssays ba join ba.sampleUsed bm "
+ "join bm.characteristics c where e = :ee" )
.setParameter( "ee", ee )
.list();
}
+ @Override
+ public Collection getAnnotationsByBioMaterials( ExpressionExperimentSubSet subset ) {
+ //noinspection unchecked
+ return this.getSessionFactory().getCurrentSession()
+ .createQuery( "select distinct c from ExpressionExperimentSubSet subset "
+ + "join subset.bioAssays ba join ba.sampleUsed bm "
+ + "join bm.characteristics c where subset = :subset" )
+ .setParameter( "subset", subset )
+ .list();
+ }
+
@Override
public Collection getAnnotationsByFactorValues( ExpressionExperiment ee ) {
//noinspection unchecked
return this.getSessionFactory().getCurrentSession()
- .createQuery( "select c from ExpressionExperiment e "
+ .createQuery( "select distinct c from ExpressionExperiment e "
+ "join e.experimentalDesign ed join ed.experimentalFactors ef join ef.factorValues fv "
+ "join fv.characteristics c where e = :ee" )
.setParameter( "ee", ee )
@@ -485,7 +503,7 @@ public Map, List> getAllAnnotation
@Override
public List getExperimentAnnotations( ExpressionExperiment expressionExperiment ) {
- return getAnnotationsByLevel( expressionExperiment, BioMaterial.class );
+ return getAnnotationsByLevel( expressionExperiment, ExpressionExperiment.class );
}
@Override
@@ -1350,6 +1368,22 @@ public Collection getSubSets( ExpressionExperiment e
.list();
}
+ @Override
+ public Map> getSubSetsByDimension( ExpressionExperiment expressionExperiment ) {
+ //noinspection unchecked
+ List results = getSessionFactory().getCurrentSession()
+ .createQuery( "select eess, bad from ExpressionExperimentSubSet eess join eess.bioAssays ba, "
+ + "BioAssayDimension bad join bad.bioAssays ba2 "
+ + "where eess.sourceExperiment = :ee and ba = ba2 "
+ + "group by eess, bad "
+ // require all the subset's assays to be matched
+ + "having size(eess.bioAssays) = count(ba)" )
+ .setParameter( "ee", expressionExperiment )
+ .list();
+ return results.stream()
+ .collect( Collectors.groupingBy( row -> ( BioAssayDimension ) row[1], Collectors.mapping( row -> ( ExpressionExperimentSubSet ) row[0], Collectors.toSet() ) ) );
+ }
+
@Override
public Map getTaxa( Collection bioAssaySets ) {
if ( bioAssaySets.isEmpty() )
diff --git a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentService.java b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentService.java
index edff145351..00c96cbf3c 100644
--- a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentService.java
+++ b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentService.java
@@ -357,10 +357,31 @@ public interface ExpressionExperimentService extends SecurableBaseService
+ * The following are included:
+ *
+ * Experiment-level tags
+ * Experimental design tags
+ * Sample-level tags
+ *
*/
@Secured({ "IS_AUTHENTICATED_ANONYMOUSLY", "ACL_SECURABLE_READ" })
Set getAnnotations( ExpressionExperiment ee );
+ /**
+ * Retrieve annotations for a given experiment subset.
+ *
+ * The following are included:
+ *
+ * Experiment-level tags
+ * Subset-level tags
+ * Experimental design tags minus the subset factor
+ * Sample-level tags for the samples within the subset
+ *
+ */
+ @Secured({ "IS_AUTHENTICATED_ANONYMOUSLY", "ACL_SECURABLE_READ" })
+ Set getAnnotations( ExpressionExperimentSubSet ee );
+
/**
* Apply ontological inference to augment a filter with additional terms.
*
@@ -621,6 +642,9 @@ Map> getSampleRemovalEvents(
@Secured({ "IS_AUTHENTICATED_ANONYMOUSLY", "AFTER_ACL_COLLECTION_READ" })
Collection getSubSets( ExpressionExperiment expressionExperiment );
+ @Secured({ "IS_AUTHENTICATED_ANONYMOUSLY", "AFTER_ACL_MAP_READ" })
+ Map> getSubSetsByDimension( ExpressionExperiment expressionExperiment );
+
/**
* Return the taxon for each of the given experiments (or subsets).
*/
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 ea18788425..be148110c9 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
@@ -585,20 +585,19 @@ public Set getAnnotations( ExpressionExperiment ee ) {
}
}
- /*
- * TODO If can be done without much slowdown, add: certain characteristics from factor values? (non-baseline,
- * non-batch, non-redundant with tags). This is tricky because they are so specific...
- */
+ for ( Characteristic c : expressionExperimentDao.getAnnotationsBySubSets( ee ) ) {
+ AnnotationValueObject annotationValue = new AnnotationValueObject( c, ExpressionExperimentSubSet.class );
+ if ( seenTerms.add( annotationValue.getTermName() ) ) {
+ annotations.add( annotationValue );
+ }
+ }
+
for ( AnnotationValueObject v : this.getAnnotationsByFactorValues( ee ) ) {
if ( seenTerms.add( v.getTermName() ) ) {
annotations.add( v );
}
}
- /*
- * TODO If can be done without much slowdown, add: certain selected (constant?) characteristics from
- * biomaterials? (non-redundant with tags)
- */
for ( AnnotationValueObject v : this.getAnnotationsByBioMaterials( ee ) ) {
if ( seenTerms.add( v.getTermName() ) ) {
annotations.add( v );
@@ -608,91 +607,145 @@ public Set getAnnotations( ExpressionExperiment ee ) {
return annotations;
}
- /**
- * URIs checked for validity Aug 2024
- * FIXME filtering here is going to have to be more elaborate for this to be useful.
- */
- private Collection extends AnnotationValueObject> getAnnotationsByFactorValues( ExpressionExperiment ee ) {
- Collection raw = this.expressionExperimentDao.getAnnotationsByFactorValues( ee );
+ @Override
+ @Transactional(readOnly = true)
+ public Set getAnnotations( ExpressionExperimentSubSet ee ) {
+ Set annotations = new HashSet<>();
+ Collection seenTerms = new TreeSet<>( String.CASE_INSENSITIVE_ORDER );
- Collection results = new HashSet<>();
- for ( Statement c : raw ) {
- // ignore baseline conditions
- if ( BaselineSelection.isBaselineCondition( c ) ) {
- continue;
+ // inherited from the EE
+ for ( Characteristic c : ee.getSourceExperiment().getCharacteristics() ) {
+ AnnotationValueObject annotationValue = new AnnotationValueObject( c, ExpressionExperiment.class );
+ if ( seenTerms.add( annotationValue.getTermName() ) ) {
+ annotations.add( annotationValue );
}
+ }
- // ignore batch factors
- if ( CharacteristicUtils.hasCategory( c, Categories.BLOCK ) ) {
- continue;
+ // specifically for the subset
+ for ( Characteristic c : ee.getCharacteristics() ) {
+ AnnotationValueObject annotationValue = new AnnotationValueObject( c, ExpressionExperimentSubSet.class );
+ if ( seenTerms.add( annotationValue.getTermName() ) ) {
+ annotations.add( annotationValue );
}
+ }
- // ignore timepoints
- if ( CharacteristicUtils.hasCategory( c, Categories.TIMEPOINT ) ) {
- continue;
+ for ( AnnotationValueObject v : this.getAnnotationsByFactorValues( ee.getSourceExperiment() ) ) {
+ // TODO: exclude annotations for the subset itself
+ if ( seenTerms.add( v.getTermName() ) ) {
+ annotations.add( v );
}
+ }
- // DE_include/exclude
- if ( "http://gemma.msl.ubc.ca/ont/TGEMO_00013".equals( c.getSubjectUri() ) )
- continue;
- if ( "http://gemma.msl.ubc.ca/ont/TGEMO_00014".equals( c.getSubjectUri() ) )
- continue;
-
- // ignore free text values
- if ( c.getSubjectUri() != null ) {
- results.add( new AnnotationValueObject( c, FactorValue.class ) );
+ for ( AnnotationValueObject v : this.getAnnotationsByBioMaterials( ee ) ) {
+ if ( seenTerms.add( v.getTermName() ) ) {
+ annotations.add( v );
}
+ }
- if ( c.getObject() != null && c.getObjectUri() != null ) {
- results.add( new AnnotationValueObject( c.getCategoryUri(), c.getCategory(), c.getObjectUri(), c.getObject(), FactorValue.class ) );
- }
+ return annotations;
+ }
- if ( c.getSecondObject() != null && c.getSecondObjectUri() != null ) {
- results.add( new AnnotationValueObject( c.getCategoryUri(), c.getCategory(), c.getSecondObjectUri(), c.getSecondObject(), FactorValue.class ) );
- }
- }
- return results;
+ /**
+ * TODO: If can be done without much slowdown, add: certain characteristics from factor values? (non-baseline,
+ * non-batch, non-redundant with tags). This is tricky because they are so specific...
+ */
+ private Collection extends AnnotationValueObject> getAnnotationsByFactorValues( ExpressionExperiment ee ) {
+ return this.expressionExperimentDao.getAnnotationsByFactorValues( ee ).stream()
+ .filter( this::filterFactorValueAnnotation )
+ .flatMap( c -> {
+ List results = new ArrayList<>( 3 );
+ // ignore free text values
+ if ( c.getSubjectUri() != null ) {
+ results.add( new AnnotationValueObject( c, FactorValue.class ) );
+ }
+
+ if ( c.getObject() != null && c.getObjectUri() != null ) {
+ results.add( new AnnotationValueObject( c.getCategoryUri(), c.getCategory(), c.getObjectUri(), c.getObject(), FactorValue.class ) );
+ }
+ if ( c.getSecondObject() != null && c.getSecondObjectUri() != null ) {
+ results.add( new AnnotationValueObject( c.getCategoryUri(), c.getCategory(), c.getSecondObjectUri(), c.getSecondObject(), FactorValue.class ) );
+ }
+ return results.stream();
+ } )
+ .collect( Collectors.toSet() );
}
- private Collection extends AnnotationValueObject> getAnnotationsByBioMaterials( ExpressionExperiment ee ) {
- Collection raw = this.expressionExperimentDao.getAnnotationsByBioMaterials( ee );
+ /**
+ * URIs checked for validity Aug 2024
+ * FIXME filtering here is going to have to be more elaborate for this to be useful.
+ */
+ private boolean filterFactorValueAnnotation( Statement c ) {
+ // ignore baseline conditions
+ if ( BaselineSelection.isBaselineCondition( c ) ) {
+ return false;
+ }
- Collection results = new HashSet<>();
- /*
- * TODO we need to filter these better; some criteria could be included in the query
- */
- for ( Characteristic c : raw ) {
+ // ignore batch factors
+ if ( CharacteristicUtils.hasCategory( c, Categories.BLOCK ) ) {
+ return false;
+ }
- // filter. Could include this in the query if it isn't too complicated.
- if ( isUncategorized( c ) || isFreeTextCategory( c ) ) {
- continue;
- }
+ // ignore timepoints
+ if ( CharacteristicUtils.hasCategory( c, Categories.TIMEPOINT ) ) {
+ return false;
+ }
- if ( isFreeText( c ) ) {
- continue;
- }
+ // DE_include/exclude
+ if ( "http://gemma.msl.ubc.ca/ont/TGEMO_00013".equals( c.getSubjectUri() ) )
+ return false;
+ if ( "http://gemma.msl.ubc.ca/ont/TGEMO_00014".equals( c.getSubjectUri() ) )
+ return false;
- if ( "MaterialType".equalsIgnoreCase( c.getCategory() )
- || "molecular entity".equalsIgnoreCase( c.getCategory() )
- || "LabelCompound".equalsIgnoreCase( c.getCategory() ) ) {
- continue;
- }
+ return true;
+ }
- if ( BaselineSelection.isBaselineCondition( c ) ) {
- continue;
- }
+ private Collection extends AnnotationValueObject> getAnnotationsByBioMaterials( ExpressionExperiment ee ) {
+ return expressionExperimentDao.getAnnotationsByBioMaterials( ee ).stream()
+ .filter( this::filterBioMaterialAnnotation )
+ .map( c -> new AnnotationValueObject( c, BioMaterial.class ) )
+ .collect( Collectors.toSet() );
+ }
- AnnotationValueObject annotationValue = new AnnotationValueObject( c, BioMaterial.class );
+ /**
+ * TODO: If can be done without much slowdown, add: certain selected (constant?) characteristics from
+ * biomaterials? (non-redundant with tags)
+ */
+ private Collection extends AnnotationValueObject> getAnnotationsByBioMaterials( ExpressionExperimentSubSet subset ) {
+ return expressionExperimentDao.getAnnotationsByBioMaterials( subset ).stream()
+ .filter( this::filterBioMaterialAnnotation )
+ .map( c -> new AnnotationValueObject( c, BioMaterial.class ) )
+ .collect( Collectors.toSet() );
+ }
- results.add( annotationValue );
+ /**
+ * TODO we need to filter these better; some criteria could be included in the query
+ */
+ private boolean filterBioMaterialAnnotation( Characteristic c ) {
+ // filter. Could include this in the query if it isn't too complicated.
+ if ( isUncategorized( c ) || isFreeTextCategory( c ) ) {
+ return false;
}
- return results;
+ if ( isFreeText( c ) ) {
+ return false;
+ }
+
+ if ( "MaterialType".equalsIgnoreCase( c.getCategory() )
+ || "molecular entity".equalsIgnoreCase( c.getCategory() )
+ || "LabelCompound".equalsIgnoreCase( c.getCategory() ) ) {
+ return false;
+ }
+
+ if ( BaselineSelection.isBaselineCondition( c ) ) {
+ return false;
+ }
+ return true;
}
+
/**
* Only the mention of these properties will result in inferred term expansion.
*
@@ -1260,6 +1313,12 @@ public Collection getSubSets( final ExpressionExperi
return this.expressionExperimentDao.getSubSets( expressionExperiment );
}
+ @Override
+ @Transactional(readOnly = true)
+ public Map> getSubSetsByDimension( ExpressionExperiment expressionExperiment ) {
+ return expressionExperimentDao.getSubSetsByDimension( expressionExperiment );
+ }
+
@Override
@Transactional(readOnly = true)
public Map getTaxa( Collection bioAssaySets ) {
diff --git a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentSubSetDao.java b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentSubSetDao.java
index b2084cffe0..3dbebfa987 100644
--- a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentSubSetDao.java
+++ b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentSubSetDao.java
@@ -18,11 +18,13 @@
*/
package ubic.gemma.persistence.service.expression.experiment;
+import ubic.gemma.model.expression.bioAssay.BioAssay;
import ubic.gemma.model.expression.experiment.ExperimentalFactor;
import ubic.gemma.model.expression.experiment.ExpressionExperimentSubSet;
import ubic.gemma.model.expression.experiment.FactorValue;
import ubic.gemma.persistence.service.BaseDao;
+import javax.annotation.Nullable;
import java.util.Collection;
/**
@@ -30,6 +32,11 @@
*/
public interface ExpressionExperimentSubSetDao extends BaseDao {
+ @Nullable
+ ExpressionExperimentSubSet loadWithBioAssays( Long id );
+
+ Collection findByBioAssayIn( Collection bioAssays );
+
/**
* Obtain the {@link FactorValue} used by the samples from this subset in the given factor.
*/
diff --git a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentSubSetDaoImpl.java b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentSubSetDaoImpl.java
index 2fa5450b6c..388d80c4f5 100644
--- a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentSubSetDaoImpl.java
+++ b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentSubSetDaoImpl.java
@@ -19,6 +19,7 @@
package ubic.gemma.persistence.service.expression.experiment;
import org.hibernate.Criteria;
+import org.hibernate.Hibernate;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
@@ -32,11 +33,13 @@
import ubic.gemma.persistence.service.AbstractDao;
import ubic.gemma.persistence.util.BusinessKey;
+import javax.annotation.Nullable;
import java.util.Collection;
import java.util.HashSet;
-import java.util.List;
import java.util.Set;
+import static ubic.gemma.persistence.util.QueryUtils.optimizeIdentifiableParameterList;
+
/**
*
* Base Spring DAO Class: is able to create, update, remove, load, and find objects of type
@@ -63,6 +66,30 @@ public ExpressionExperimentSubSet find( ExpressionExperimentSubSet entity ) {
return ( ExpressionExperimentSubSet ) queryObject.uniqueResult();
}
+ @Nullable
+ @Override
+ public ExpressionExperimentSubSet loadWithBioAssays( Long id ) {
+ ExpressionExperimentSubSet subSet = load( id );
+ if ( subSet != null ) {
+ Hibernate.initialize( subSet.getAccession() );
+ Hibernate.initialize( subSet.getBioAssays() );
+ Hibernate.initialize( subSet.getCharacteristics() );
+ Hibernate.initialize( subSet.getSourceExperiment().getAccession() );
+ Hibernate.initialize( subSet.getSourceExperiment().getCharacteristics() );
+ Hibernate.initialize( subSet.getSourceExperiment().getPrimaryPublication() );
+ }
+ return subSet;
+ }
+
+ @Override
+ public Collection findByBioAssayIn( Collection bioAssays ) {
+ //noinspection unchecked
+ return getSessionFactory().getCurrentSession()
+ .createQuery( "select distinct eess from ExpressionExperimentSubSet eess join eess.bioAssays ba where ba in :bas" )
+ .setParameterList( "bas", optimizeIdentifiableParameterList( bioAssays ) )
+ .list();
+ }
+
@Override
public Collection getFactorValuesUsed( ExpressionExperimentSubSet entity, ExperimentalFactor factor ) {
//noinspection unchecked
diff --git a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentSubSetService.java b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentSubSetService.java
index e7810bf285..c3663e1fc3 100644
--- a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentSubSetService.java
+++ b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentSubSetService.java
@@ -19,6 +19,7 @@
package ubic.gemma.persistence.service.expression.experiment;
import org.springframework.security.access.annotation.Secured;
+import ubic.gemma.model.expression.bioAssay.BioAssay;
import ubic.gemma.model.expression.experiment.ExperimentalFactor;
import ubic.gemma.model.expression.experiment.ExpressionExperimentSubSet;
import ubic.gemma.model.expression.experiment.FactorValue;
@@ -27,6 +28,7 @@
import javax.annotation.Nullable;
import java.util.Collection;
+import java.util.List;
/**
* @author kelsey
@@ -41,6 +43,9 @@ public interface ExpressionExperimentSubSetService extends BaseService findByBioAssayIn( Collection bioAssays );
+
@Override
@Secured({ "GROUP_USER" })
ExpressionExperimentSubSet create( ExpressionExperimentSubSet expressionExperimentSubSet );
@@ -49,6 +54,10 @@ public interface ExpressionExperimentSubSetService extends BaseService loadAll();
@@ -75,5 +84,4 @@ public interface ExpressionExperimentSubSetService extends BaseService getFactorValuesUsed( ExpressionExperimentSubSet entity, ExperimentalFactor factor );
Collection getFactorValuesUsed( Long subSetId, Long experimentalFactor );
-
}
diff --git a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentSubSetServiceImpl.java b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentSubSetServiceImpl.java
index 633ff1fd17..6fcd8294c1 100644
--- a/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentSubSetServiceImpl.java
+++ b/gemma-core/src/main/java/ubic/gemma/persistence/service/expression/experiment/ExpressionExperimentSubSetServiceImpl.java
@@ -17,6 +17,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
+import ubic.gemma.model.expression.bioAssay.BioAssay;
import ubic.gemma.model.expression.experiment.ExperimentalFactor;
import ubic.gemma.model.expression.experiment.ExpressionExperimentSubSet;
import ubic.gemma.model.expression.experiment.FactorValue;
@@ -46,6 +47,12 @@ public ExpressionExperimentSubSetServiceImpl( ExpressionExperimentSubSetDao expr
this.differentialExpressionAnalysisService = differentialExpressionAnalysisService;
}
+ @Override
+ @Transactional(readOnly = true)
+ public Collection findByBioAssayIn( Collection bioAssays ) {
+ return expressionExperimentSubSetDao.findByBioAssayIn( bioAssays );
+ }
+
@Override
@Transactional(readOnly = true)
public Collection getFactorValuesUsed( ExpressionExperimentSubSet entity, ExperimentalFactor factor ) {
@@ -63,6 +70,12 @@ public Collection getFactorValuesUsed( Long subSetId, Lo
return result;
}
+ @Override
+ @Transactional(readOnly = true)
+ public ExpressionExperimentSubSet loadWithBioAssays( Long id ) {
+ return expressionExperimentSubSetDao.loadWithBioAssays( id );
+ }
+
/**
* doesn't include removal of sample coexpression matrices, PCA, probe2probe coexpression links, or adjusting
* experiment set members
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 4d5709ff59..8010443794 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
@@ -91,7 +91,9 @@ public DatabaseBackedGeneSetValueObject loadValueObject( GeneSet geneSet ) {
@Override
public DatabaseBackedGeneSetValueObject loadValueObjectById( Long id ) {
DatabaseBackedGeneSetValueObject vo = loadValueObjectByIdLite( id );
- fillGeneIds( Collections.singletonList( vo ) );
+ if ( vo != null ) {
+ fillGeneIds( Collections.singletonList( vo ) );
+ }
return vo;
}
diff --git a/gemma-core/src/main/java/ubic/gemma/persistence/util/EntityUrlBuilder.java b/gemma-core/src/main/java/ubic/gemma/persistence/util/EntityUrlBuilder.java
index e235143be7..705fd634ef 100644
--- a/gemma-core/src/main/java/ubic/gemma/persistence/util/EntityUrlBuilder.java
+++ b/gemma-core/src/main/java/ubic/gemma/persistence/util/EntityUrlBuilder.java
@@ -196,6 +196,8 @@ private WebEntityUrl( String baseUrl, U entity ) {
this.entityPath = "/bioAssay/showBioAssay.html?id=";
} else if ( entity instanceof BioMaterial ) {
this.entityPath = "/bioMaterial/showBioMaterial.html?id=";
+ } else if ( entity instanceof Taxon ) {
+ this.entityPath = "/taxon/showTaxon.html?id=";
} else {
throw new UnsupportedOperationException( "Cannot generate a Web URL for entities of type " + entity.getClass() + "." );
}
diff --git a/gemma-core/src/main/resources/default.properties b/gemma-core/src/main/resources/default.properties
index 56aae87b4c..a16dc41c32 100755
--- a/gemma-core/src/main/resources/default.properties
+++ b/gemma-core/src/main/resources/default.properties
@@ -224,10 +224,11 @@ gemma.gemBrow.url=${gemma.hosturl}/browse
# You will likely need to create a virtualenv for Gemma dependencies
python.exe=python
############################################################
-# Static server
+# Static Asset Server
# Enable the static server for serving assets externally
-gemma.staticServer.enabled=false
+gemma.staticAssetServer.enabled=false
# Base URL relative to which static resources are served
# In a development setting, you can serve assets continuously by running 'npm run serve' from the gemma-web module
# directory
-gemma.staticServer.baseUrl=http://localhost:8082
\ No newline at end of file
+gemma.staticAssetServer.baseUrl=http://localhost:8082
+gemma.staticAssetServer.allowedDirs=/bundles/,/fonts/,/images/,/scripts/,/styles/
\ No newline at end of file
diff --git a/gemma-core/src/test/java/ubic/gemma/persistence/service/expression/biomaterial/BioMaterialDaoTest.java b/gemma-core/src/test/java/ubic/gemma/persistence/service/expression/biomaterial/BioMaterialDaoTest.java
index e43be265a4..3d5d30bb1c 100644
--- a/gemma-core/src/test/java/ubic/gemma/persistence/service/expression/biomaterial/BioMaterialDaoTest.java
+++ b/gemma-core/src/test/java/ubic/gemma/persistence/service/expression/biomaterial/BioMaterialDaoTest.java
@@ -55,7 +55,7 @@ public void findAllSubBioMaterials() {
bm4.setSourceTaxon( taxon );
bm4.setSourceBioMaterial( bm2 );
bm4 = bioMaterialDao.create( bm4 );
- assertThat( bioMaterialDao.findSubBioMaterials( bm1 ) )
+ assertThat( bioMaterialDao.findSubBioMaterials( bm1, false ) )
.containsExactlyInAnyOrder( bm2, bm3, bm4 );
}
diff --git a/gemma-rest/src/main/resources/restapidocs/index.jsp b/gemma-rest/src/main/resources/restapidocs/index.jsp
index 07ecd4d01a..a6cc5ff43d 100644
--- a/gemma-rest/src/main/resources/restapidocs/index.jsp
+++ b/gemma-rest/src/main/resources/restapidocs/index.jsp
@@ -1,4 +1,4 @@
-<%@ page contentType="text/html;charset=UTF-8" %>
+
diff --git a/gemma-web/node_modules/webpack/lib/dependencies/HarmonyTopLevelThisParserPlugin.js b/gemma-web/node_modules/webpack/lib/dependencies/HarmonyTopLevelThisParserPlugin.js
new file mode 100644
index 0000000000..b8ba184864
--- /dev/null
+++ b/gemma-web/node_modules/webpack/lib/dependencies/HarmonyTopLevelThisParserPlugin.js
@@ -0,0 +1,39 @@
+/*
+ MIT License http://www.opensource.org/licenses/mit-license.php
+ Author Florent Cailhol @ooflorent
+*/
+
+"use strict";
+
+const ConstDependency = require("./ConstDependency");
+const HarmonyExports = require("./HarmonyExports");
+
+/** @typedef {import("../Dependency").DependencyLocation} DependencyLocation */
+/** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
+/** @typedef {import("../javascript/JavascriptParser").Range} Range */
+
+class HarmonyTopLevelThisParserPlugin {
+ /**
+ * @param {JavascriptParser} parser the parser
+ * @returns {void}
+ */
+ apply(parser) {
+ parser.hooks.expression
+ .for("this")
+ .tap("HarmonyTopLevelThisParserPlugin", node => {
+ if (!parser.scope.topLevelScope) return;
+ if (HarmonyExports.isEnabled(parser.state)) {
+ const dep = new ConstDependency(
+ "undefined",
+ /** @type {Range} */ (node.range),
+ null
+ );
+ dep.loc = /** @type {DependencyLocation} */ (node.loc);
+ parser.state.module.addPresentationalDependency(dep);
+ return true;
+ }
+ });
+ }
+}
+
+module.exports = HarmonyTopLevelThisParserPlugin;
diff --git a/gemma-web/src/main/java/ubic/gemma/web/controller/common/description/bibref/BibliographicReferenceController.java b/gemma-web/src/main/java/ubic/gemma/web/controller/common/description/bibref/BibliographicReferenceController.java
index 9dff9e7d6d..b415fcc47b 100644
--- a/gemma-web/src/main/java/ubic/gemma/web/controller/common/description/bibref/BibliographicReferenceController.java
+++ b/gemma-web/src/main/java/ubic/gemma/web/controller/common/description/bibref/BibliographicReferenceController.java
@@ -21,10 +21,12 @@
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
+import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
+import org.springframework.web.servlet.view.RedirectView;
import ubic.gemma.core.loader.entrez.pubmed.PubMedXMLFetcher;
import ubic.gemma.core.search.SearchException;
import ubic.gemma.model.common.description.BibliographicReference;
@@ -67,36 +69,104 @@ public class BibliographicReferenceController extends BaseController {
@Autowired
private PubMedXMLFetcher pubMedXmlFetcher;
- @RequestMapping(value = "/bibRefAdd.html", method = RequestMethod.POST)
- public ModelAndView add( @RequestParam("accession") String pubMedId, HttpServletRequest request ) {
- // FIXME: allow use of the primary key as well.
+ @RequestMapping(value = "/showAllEeBibRefs.html", method = { RequestMethod.GET, RequestMethod.HEAD })
+ public ModelAndView showAllForExperiments() {
+ Map eeToBibRefs = bibliographicReferenceService
+ .getAllExperimentLinkedReferences();
- if ( StringUtils.isBlank( pubMedId ) ) {
- throw new IllegalArgumentException( "Must provide a PubMed Id" );
+ // map sorted in natural order of the keys
+ SortedMap> citationToEEs = new TreeMap<>();
+ for ( Entry entry : eeToBibRefs.entrySet() ) {
+ if ( entry.getValue().getTitle() == null || entry.getValue().getTitle().isEmpty()
+ || entry.getValue().getAuthorList() == null || entry.getValue().getAuthorList().isEmpty() ) {
+ continue;
+ }
+ CitationValueObject cvo = CitationValueObject.convert2CitationValueObject( entry.getValue() );
+ if ( !citationToEEs.containsKey( cvo ) ) {
+ citationToEEs.put( cvo, new ArrayList<>() );
+ }
+ citationToEEs.get( cvo ).add( new ExpressionExperimentValueObject( entry.getKey(), true, true ) );
}
- BibliographicReference bibRef = bibliographicReferenceService.findByExternalId( pubMedId );
- BibliographicReferenceValueObject vo;
+ return new ModelAndView( "bibRefAllExperiments" )
+ .addObject( "citationToEEs", citationToEEs );
+ }
+
+ @RequestMapping(value = "/searchBibRefs.html", method = { RequestMethod.GET, RequestMethod.HEAD })
+ public ModelAndView searchBibRefs() {
+ return new ModelAndView( "bibRefList" );
+ }
+
+ @RequestMapping(value = "/bibRefView.html", method = { RequestMethod.GET, RequestMethod.HEAD }, params = { "id" })
+ public ModelAndView showById( @RequestParam(value = "id") Long id ) {
+ BibliographicReference bibRef = bibliographicReferenceService.loadOrFail( id, EntityNotFoundException::new );
+ return new ModelAndView( "bibRefView" )
+ .addObject( "bibliographicReference", bibRef );
+ }
+
+ @RequestMapping(value = "/bibRefView.html", method = { RequestMethod.GET, RequestMethod.HEAD }, params = { "accession" })
+ public ModelAndView showByAccession( @RequestParam(value = "accession") String accession ) {
+ BibliographicReference bibRef = bibliographicReferenceService.findByExternalId( accession, ExternalDatabases.PUBMED );
if ( bibRef == null ) {
+ // attempt to fetch it from PubMed
try {
- bibRef = this.pubMedXmlFetcher.retrieveByHTTP( Integer.parseInt( pubMedId ) );
+ bibRef = this.pubMedXmlFetcher.retrieveByHTTP( Integer.parseInt( accession ) );
+ return new ModelAndView( "bibRefAdd" )
+ .addObject( "bibliographicReference", bibRef );
+ } catch ( NumberFormatException e ) {
+ // ignore, this will be treated as an EntityNotFoundException
} catch ( IOException e ) {
- throw new RuntimeException( "Failed to retrieve publication with PubMed ID: " + pubMedId, e );
+ throw new RuntimeException( "Failed to retrieve publication with PubMed ID: " + accession, e );
+ }
+ }
+ if ( bibRef == null ) {
+ throw new EntityNotFoundException( "Could not locate reference with PubMed ID " + accession + ", either in Gemma or by querying NCBI." );
+ }
+ return new ModelAndView( "bibRefView" )
+ .addObject( "bibliographicReference", bibRef );
+ }
+
+ private boolean isIncomplete( BibliographicReference bibRef ) {
+ return bibRef.getPublicationDate() == null;
+ }
+
+ @RequestMapping(value = "/bibRefAdd.html", method = RequestMethod.POST)
+ public RedirectView add( @RequestParam("accession") Integer pubMedId, @RequestParam(value = "refresh", required = false) Boolean refresh, HttpServletRequest request ) {
+ // FIXME: allow use of the primary key as well.
+ BibliographicReference bibRef = bibliographicReferenceService.findByExternalId( String.valueOf( pubMedId ), ExternalDatabases.PUBMED );
+ if ( bibRef == null ) {
+ try {
+ bibRef = this.pubMedXmlFetcher.retrieveByHTTP( pubMedId );
+ } catch ( IOException e ) {
+ throw new RuntimeException( "Failed to retrieve publication with PubMed ID " + pubMedId + ".", e );
}
if ( bibRef == null ) {
- throw new EntityNotFoundException( "Could not locate reference with pubmed id=" + pubMedId );
+ throw new EntityNotFoundException( "Could not locate reference with PubMed ID " + pubMedId + "." );
}
- vo = new BibliographicReferenceValueObject( ( BibliographicReference ) persisterHelper.persist( bibRef ) );
+ bibRef = ( BibliographicReference ) persisterHelper.persist( bibRef );
this.saveMessage( request, "Added " + pubMedId + " to the system." );
- } else if ( StringUtils.isNotBlank( request.getParameter( "refresh" ) ) ) {
- vo = this.update( pubMedId );
- this.saveMessage( request, "Updated record for pubmed id " + pubMedId );
+ } else if ( refresh != null && refresh ) {
+ bibRef = this.bibliographicReferenceService.refresh( String.valueOf( pubMedId ) );
+ this.saveMessage( request, "Updated record for PubMed ID " + pubMedId + "." );
} else {
- throw new IllegalArgumentException( "Action not understood" );
+ this.saveMessage( request, "There is already a bibliographic reference with PubMed ID " + pubMedId + "." );
}
+ return new RedirectView( "/bibRef/bibRefView.html?id=" + bibRef.getId(), true );
+ }
- return new ModelAndView( "bibRefView" ).addObject( "bibliographicReferenceId", vo.getId() )
- .addObject( "existsInSystem", Boolean.TRUE ).addObject( "bibliographicReference", vo );
+ @RequestMapping(value = "/deleteBibRef.html", method = RequestMethod.POST)
+ public ModelAndView delete( @RequestParam("acc") String pubMedId, HttpServletRequest request ) {
+ BibliographicReference bibRef = bibliographicReferenceService.findByExternalId( pubMedId );
+ if ( bibRef == null ) {
+ String message = "There is no reference with PubMed ID " + pubMedId + " in the system any more.";
+ this.saveMessage( request, message );
+ throw new EntityNotFoundException( message );
+ }
+ bibliographicReferenceService.remove( bibRef );
+ log.info( "Bibliographic reference with pubMedId: " + bibRef.getPubAccession().getAccession() + " deleted" );
+ this.addMessage( request, "object.deleted",
+ new Object[] { messagePrefix, bibRef.getPubAccession().getAccession() } );
+ return new ModelAndView( "bibRefView", "bibliographicReference", bibRef );
}
@SuppressWarnings("unused")
@@ -123,58 +193,21 @@ public JsonReaderResponse browse( ListBatchCo
return new JsonReaderResponse<>( valueObjects, ( int ) count );
}
- @RequestMapping(value = "/deleteBibRef.html", method = RequestMethod.POST)
- public ModelAndView delete( @RequestParam("acc") String pubMedId, HttpServletRequest request ) {
- BibliographicReference bibRef = bibliographicReferenceService.findByExternalId( pubMedId );
- if ( bibRef == null ) {
- String message = "There is no reference with PubMed ID " + pubMedId + " in the system any more.";
- this.saveMessage( request, message );
- throw new EntityNotFoundException( message );
- }
- bibliographicReferenceService.remove( bibRef );
- log.info( "Bibliographic reference with pubMedId: " + bibRef.getPubAccession().getAccession() + " deleted" );
- this.addMessage( request, "object.deleted",
- new Object[] { messagePrefix, bibRef.getPubAccession().getAccession() } );
- return new ModelAndView( "bibRefView", "bibliographicReference", bibRef );
- }
-
- public BibliographicReferenceValueObject load( Long id ) {
- if ( id == null ) {
- throw new IllegalArgumentException( "ID cannot be null" );
- }
- Collection ids = new ArrayList<>();
- ids.add( id );
- JsonReaderResponse returnVal = this.loadMultiple( ids );
- if ( returnVal.getRecords() != null && !returnVal.getRecords().isEmpty() ) {
- return returnVal.getRecords().iterator().next();
- }
- throw new EntityNotFoundException( "Error retrieving bibliographic reference for id = " + id );
-
- }
-
@SuppressWarnings("unused")
- public Collection loadAllForExperiments() {
- Map eeToBibRefs = bibliographicReferenceService
- .getAllExperimentLinkedReferences();
- Collection bibRefs = eeToBibRefs.values();
-
- return BibliographicReferenceValueObject.convert2ValueObjects( bibRefs );
+ public BibliographicReferenceValueObject load( Long id ) {
+ Assert.notNull( id, "ID cannot be null." );
+ BibliographicReference bss = bibliographicReferenceService.loadOrFail( id, EntityNotFoundException::new );
+ bss = bibliographicReferenceService.thaw( bss );
+ BibliographicReferenceValueObject bibRefs = bibliographicReferenceService.loadValueObject( bss );
+ return new JsonReaderResponse<>( Collections.singletonList( bibRefs ), 1 ).getRecords().iterator().next();
}
@SuppressWarnings("unused")
public BibliographicReferenceValueObject loadFromPubmedID( String pubMedID ) {
+ Assert.notNull( pubMedID, "PubMed ID cannot be null." );
return bibliographicReferenceService.findVOByExternalId( pubMedID );
}
- public JsonReaderResponse loadMultiple( Collection ids ) {
-
- Collection bss = bibliographicReferenceService.load( ids );
- bss = bibliographicReferenceService.thaw( bss );
- Collection bibRefs = bibliographicReferenceService.loadValueObjects( bss );
-
- return new JsonReaderResponse<>( new ArrayList<>( bibRefs ), bibRefs.size() );
- }
-
public JsonReaderResponse search( SearchSettingsValueObject settings ) {
try {
List vos = bibliographicReferenceService.search( settings );
@@ -184,84 +217,14 @@ public JsonReaderResponse search( SearchSetti
}
}
- @RequestMapping(value = "/searchBibRefs.html", method = { RequestMethod.GET, RequestMethod.HEAD })
- public ModelAndView searchBibRefs() {
- return new ModelAndView( "bibRefList" );
- }
-
- @RequestMapping(value = "/bibRefView.html", method = { RequestMethod.GET, RequestMethod.HEAD }, params = { "id" })
- public ModelAndView showById( @RequestParam(value = "id") Long id, HttpServletRequest request ) {
- BibliographicReference bibRef = bibliographicReferenceService.loadOrFail( id, EntityNotFoundException::new );
- return show( bibRef, request, true )
- .addObject( "byAccession", Boolean.FALSE );
- }
-
- @RequestMapping(value = "/bibRefView.html", method = { RequestMethod.GET, RequestMethod.HEAD }, params = { "accession" })
- public ModelAndView showByAccession( @RequestParam(value = "accession") String accession, HttpServletRequest request ) {
- BibliographicReference bibRef = bibliographicReferenceService.findByExternalId( accession, ExternalDatabases.PUBMED );
- boolean existsInSystem = bibRef != null;
- if ( bibRef == null ) {
- // attempt to fetch it from PubMed
- try {
- bibRef = this.pubMedXmlFetcher.retrieveByHTTP( Integer.parseInt( accession ) );
- } catch ( NumberFormatException e ) {
- // ignore, this will be treated as an EntityNotFoundException
- } catch ( IOException e ) {
- throw new RuntimeException( "Failed to retrieve publication with PubMed ID: " + accession, e );
- }
- }
- if ( bibRef == null ) {
- throw new EntityNotFoundException( "Could not locate reference with PubMwd ID " + accession + ", either in Gemma or by querying NCBI." );
- }
- return show( bibRef, request, existsInSystem )
- .addObject( "byAccession", Boolean.TRUE )
- .addObject( "accession", accession );
- }
-
- private ModelAndView show( BibliographicReference bibRef, HttpServletRequest request, boolean existsInSystem ) {
- this.addMessage( request, "object.found", new Object[] { messagePrefix, } );
- return new ModelAndView( "bibRefView" )
- .addObject( "bibliographicReferenceId", bibRef.getId() )
- .addObject( "existsInSystem", existsInSystem )
- .addObject( "incompleteEntry", bibRef.getPublicationDate() == null );
- }
-
- @RequestMapping(value = "/showAllEeBibRefs.html", method = { RequestMethod.GET, RequestMethod.HEAD })
- public ModelAndView showAllForExperiments() {
- Map eeToBibRefs = bibliographicReferenceService
- .getAllExperimentLinkedReferences();
-
- // map sorted in natural order of the keys
- SortedMap> citationToEEs = new TreeMap<>();
- for ( Entry entry : eeToBibRefs.entrySet() ) {
- if ( entry.getValue().getTitle() == null || entry.getValue().getTitle().isEmpty()
- || entry.getValue().getAuthorList() == null || entry.getValue().getAuthorList().isEmpty() ) {
- continue;
- }
- CitationValueObject cvo = CitationValueObject.convert2CitationValueObject( entry.getValue() );
- if ( !citationToEEs.containsKey( cvo ) ) {
- citationToEEs.put( cvo, new ArrayList<>() );
- }
- citationToEEs.get( cvo ).add( new ExpressionExperimentValueObject( entry.getKey(), true, true ) );
- }
-
- return new ModelAndView( "bibRefAllExperiments" ).addObject( "citationToEEs", citationToEEs );
- }
-
public BibliographicReferenceValueObject update( String pubMedId ) {
- BibliographicReference bibRef = bibliographicReferenceService.findByExternalId( pubMedId );
- if ( bibRef == null ) {
- throw new EntityNotFoundException( "Could not locate reference with that id" );
- }
- return new BibliographicReferenceValueObject( this.bibliographicReferenceService.refresh( pubMedId ) );
+ Assert.notNull( pubMedId, "PubMed ID cannot be null." );
+ return new BibliographicReferenceValueObject( bibliographicReferenceService.refresh( pubMedId ) );
}
private List getBatch( ListBatchCommand batch ) {
- List records;
if ( StringUtils.isNotBlank( batch.getSort() ) ) {
-
String o = batch.getSort();
-
String orderBy;
switch ( o ) {
case "title":
@@ -279,14 +242,11 @@ private List getBatch( ListBatchCommand batch ) {
default:
throw new IllegalArgumentException( "Unknown sort field: " + o );
}
-
boolean descending = batch.getDir() != null && batch.getDir().equalsIgnoreCase( "DESC" );
- records = bibliographicReferenceService.browse( batch.getStart(), batch.getLimit(), orderBy, descending );
+ return bibliographicReferenceService.browse( batch.getStart(), batch.getLimit(), orderBy, descending );
} else {
- records = bibliographicReferenceService.browse( batch.getStart(), batch.getLimit() );
+ return bibliographicReferenceService.browse( batch.getStart(), batch.getLimit() );
}
- return records;
}
-
}
diff --git a/gemma-web/src/main/java/ubic/gemma/web/controller/common/description/bibref/PubMedQueryController.java b/gemma-web/src/main/java/ubic/gemma/web/controller/common/description/bibref/PubMedQueryController.java
index ea94622fa6..5ae21fea74 100644
--- a/gemma-web/src/main/java/ubic/gemma/web/controller/common/description/bibref/PubMedQueryController.java
+++ b/gemma-web/src/main/java/ubic/gemma/web/controller/common/description/bibref/PubMedQueryController.java
@@ -107,7 +107,8 @@ public ModelAndView onSubmit( HttpServletRequest request, PubMedSearchCommand co
}
status.setComplete();
- return new ModelAndView( "bibRefView" ).addObject( "bibliographicReference", bibRefFound );
+ return new ModelAndView( "bibRefView" )
+ .addObject( "bibliographicReference", bibRefFound );
}
}
diff --git a/gemma-web/src/main/java/ubic/gemma/web/controller/expression/arrayDesign/ArrayDesignController.java b/gemma-web/src/main/java/ubic/gemma/web/controller/expression/arrayDesign/ArrayDesignController.java
index 8f0c783844..b39b5ba39d 100644
--- a/gemma-web/src/main/java/ubic/gemma/web/controller/expression/arrayDesign/ArrayDesignController.java
+++ b/gemma-web/src/main/java/ubic/gemma/web/controller/expression/arrayDesign/ArrayDesignController.java
@@ -495,9 +495,7 @@ public ModelAndView showArrayDesignByName( @RequestParam("name") String name ) {
private ModelAndView showArrayDesignInternal( ArrayDesign arrayDesign ) {
return new ModelAndView( "arrayDesign.detail" )
- .addObject( "arrayDesignId", arrayDesign.getId() )
- .addObject( "arrayDesignShortName", arrayDesign.getShortName() )
- .addObject( "arrayDesignName", arrayDesign.getName() );
+ .addObject( "arrayDesign", arrayDesign );
}
@RequestMapping(value = "/showCompositeSequenceSummary.html", method = { RequestMethod.GET, RequestMethod.HEAD })
diff --git a/gemma-web/src/main/java/ubic/gemma/web/controller/expression/bioAssay/BioAssayController.java b/gemma-web/src/main/java/ubic/gemma/web/controller/expression/bioAssay/BioAssayController.java
index 0b75b92fbd..50966b79ec 100644
--- a/gemma-web/src/main/java/ubic/gemma/web/controller/expression/bioAssay/BioAssayController.java
+++ b/gemma-web/src/main/java/ubic/gemma/web/controller/expression/bioAssay/BioAssayController.java
@@ -18,7 +18,6 @@
*/
package ubic.gemma.web.controller.expression.bioAssay;
-import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -33,15 +32,16 @@
import ubic.gemma.core.tasks.analysis.expression.BioAssayOutlierProcessingTaskCommand;
import ubic.gemma.model.expression.bioAssay.BioAssay;
import ubic.gemma.model.expression.bioAssay.BioAssayValueObject;
+import ubic.gemma.model.expression.bioAssayData.BioAssayDimension;
+import ubic.gemma.model.expression.experiment.BioAssaySet;
import ubic.gemma.model.expression.experiment.ExpressionExperiment;
import ubic.gemma.persistence.service.expression.bioAssay.BioAssayService;
+import ubic.gemma.persistence.service.expression.bioAssayData.BioAssayDimensionService;
import ubic.gemma.persistence.service.expression.experiment.ExpressionExperimentService;
import ubic.gemma.web.util.EntityNotFoundException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Map;
+import javax.annotation.Nullable;
+import java.util.*;
import java.util.stream.Collectors;
/**
@@ -66,6 +66,52 @@ public class BioAssayController {
@Autowired
private OutlierDetectionService outlierDetectionService;
+ @Autowired
+ private BioAssayDimensionService bioAssayDimensionService;
+
+ @RequestMapping(value = { "/showBioAssay.html", "/" }, method = { RequestMethod.GET, RequestMethod.HEAD })
+ public ModelAndView show( @RequestParam("id") Long id, @RequestParam(value = "dimension", required = false) Long dimensionId ) {
+ BioAssay bioAssay = bioAssayService.loadOrFail( id, EntityNotFoundException::new );
+ bioAssay = bioAssayService.thaw( bioAssay );
+ return new ModelAndView( "bioAssay.detail" )
+ .addObject( "bioAssay", bioAssay )
+ .addAllObjects( getBioAssayHierarchy( bioAssay, dimensionId ) )
+ .addObject( "bioAssaySets", bioAssayService.getBioAssaySets( bioAssay ).stream().sorted( Comparator.comparing( BioAssaySet::getName ) ).collect( Collectors.toList() ) );
+ }
+
+ private Map getBioAssayHierarchy( BioAssay bioAssay, @Nullable Long dimensionId ) {
+ if ( dimensionId == null ) {
+ return Collections.emptyMap();
+ }
+ List parents;
+ if ( bioAssay.getSampleUsed().getSourceBioMaterial() != null ) {
+ parents = bioAssay.getSampleUsed().getSourceBioMaterial().getBioAssaysUsedIn().stream()
+ .sorted( Comparator.comparing( BioAssay::getName ) )
+ .collect( Collectors.toList() );
+ } else {
+ parents = Collections.emptyList();
+ }
+ // only show siblings that share a common BAD
+ BioAssayDimension dim = bioAssayDimensionService.loadOrFail( dimensionId, EntityNotFoundException::new );
+ Set sharedBas = new HashSet<>( dim.getBioAssays() );
+ List siblings = bioAssayService.findSiblings( bioAssay ).stream()
+ .filter( sharedBas::contains )
+ .sorted( Comparator.comparing( BioAssay::getName ) )
+ .collect( Collectors.toList() );
+ List children = bioAssayService.findSubBioAssays( bioAssay, true ).stream()
+ .filter( sharedBas::contains )
+ .sorted( Comparator.comparing( BioAssay::getName ) )
+ .collect( Collectors.toList() );
+ Map result = new HashMap<>();
+ result.put( "dimension", dim );
+ result.put( "parents", parents );
+ result.put( "singleParent", parents.size() == 1 ? parents.iterator().next() : null );
+ result.put( "children", children );
+ result.put( "siblings", siblings );
+ return result;
+ }
+
+ @SuppressWarnings("unused") // Is used in EEManager.js
public Collection getBioAssays( Long eeId ) {
ExpressionExperiment ee = eeService.loadAndThawLiteOrFail( eeId,
EntityNotFoundException::new, "Could not load experiment with ID=" + eeId );
@@ -94,39 +140,4 @@ public String markOutlier( Collection ids ) {
public String unmarkOutlier( Collection ids ) {
return taskRunningService.submitTaskCommand( new BioAssayOutlierProcessingTaskCommand( ids, true ) );
}
-
- @RequestMapping(value = { "/showBioAssay.html", "/" }, method = { RequestMethod.GET, RequestMethod.HEAD })
- public ModelAndView show( @RequestParam("id") Long id ) {
- BioAssay bioAssay = bioAssayService.load( id );
- if ( bioAssay == null ) {
- throw new EntityNotFoundException( id + " not found" );
- }
- bioAssay = bioAssayService.thaw( bioAssay );
- return new ModelAndView( "bioAssay.detail" )
- .addObject( "bioAssay", new BioAssayValueObject( bioAssay, false ) );
- }
-
- @RequestMapping(value = "/showAllBioAssays.html", method = { RequestMethod.GET, RequestMethod.HEAD })
- public ModelAndView showAllBioAssays( @RequestParam(value = "id", required = false) String sId ) {
- Collection bioAssays = new ArrayList<>();
- if ( StringUtils.isBlank( sId ) ) {
- /*
- * Probably not desirable ... there are >380,000 of them
- */
- bioAssays = bioAssayService.loadAll();
- } else {
- String[] idList = StringUtils.split( sId, ',' );
- for ( String anIdList : idList ) {
- Long id = Long.parseLong( anIdList );
- BioAssay bioAssay = bioAssayService.load( id );
- if ( bioAssay == null ) {
- throw new EntityNotFoundException( id + " not found" );
- }
- bioAssay = bioAssayService.thaw( bioAssay );
- bioAssays.add( bioAssay );
- }
- }
- return new ModelAndView( "bioAssays" ).addObject( "bioAssays", bioAssays );
- }
-
}
diff --git a/gemma-web/src/main/java/ubic/gemma/web/controller/expression/biomaterial/BioMaterialController.java b/gemma-web/src/main/java/ubic/gemma/web/controller/expression/biomaterial/BioMaterialController.java
index 91d7792e34..a4b4a72863 100644
--- a/gemma-web/src/main/java/ubic/gemma/web/controller/expression/biomaterial/BioMaterialController.java
+++ b/gemma-web/src/main/java/ubic/gemma/web/controller/expression/biomaterial/BioMaterialController.java
@@ -24,24 +24,22 @@
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
-import ubic.gemma.core.ontology.OntologyService;
import ubic.gemma.model.common.description.AnnotationValueObject;
import ubic.gemma.model.expression.bioAssay.BioAssay;
+import ubic.gemma.model.expression.bioAssayData.BioAssayDimension;
import ubic.gemma.model.expression.biomaterial.BioMaterial;
import ubic.gemma.model.expression.experiment.ExperimentalFactor;
import ubic.gemma.model.expression.experiment.ExpressionExperiment;
import ubic.gemma.model.expression.experiment.FactorValue;
import ubic.gemma.model.expression.experiment.FactorValueValueObject;
+import ubic.gemma.persistence.service.expression.bioAssayData.BioAssayDimensionService;
import ubic.gemma.persistence.service.expression.biomaterial.BioMaterialService;
import ubic.gemma.persistence.service.expression.experiment.ExpressionExperimentService;
import ubic.gemma.persistence.service.expression.experiment.FactorValueService;
import ubic.gemma.web.remote.EntityDelegator;
import ubic.gemma.web.util.EntityNotFoundException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Set;
+import java.util.*;
import java.util.stream.Collectors;
/**
@@ -54,11 +52,11 @@ public class BioMaterialController {
@Autowired
private BioMaterialService bioMaterialService;
@Autowired
- private OntologyService ontologyService;
- @Autowired
private ExpressionExperimentService expressionExperimentService;
@Autowired
private FactorValueService factorValueService;
+ @Autowired
+ private BioAssayDimensionService bioAssayDimensionService;
/**
* AJAX
@@ -158,11 +156,39 @@ public Collection getFactorValues( EntityDelegator getBioMaterialHierarchy( BioMaterial bioMaterial, Long dimensionId ) {
+ if ( dimensionId == null ) {
+ return Collections.emptyMap();
+ }
+ BioAssayDimension dim = bioAssayDimensionService.loadOrFail( dimensionId, EntityNotFoundException::new );
+ Set sharedBMs = new HashSet<>();
+ for ( BioAssay ba : dim.getBioAssays() ) {
+ sharedBMs.add( ba.getSampleUsed() );
+ }
+ List siblings = bioMaterialService.findSiblings( bioMaterial ).stream()
+ .filter( sharedBMs::contains )
+ .sorted( Comparator.comparing( BioMaterial::getName ) )
+ .collect( Collectors.toList() );
+ List children = bioMaterialService.findSubBioMaterials( bioMaterial, true )
+ .stream()
+ .filter( sharedBMs::contains )
+ .sorted( Comparator.comparing( BioMaterial::getName ) )
+ .collect( Collectors.toList() );
+ Map results = new HashMap<>();
+ results.put( "dimension", dim );
+ results.put( "parent", bioMaterial.getSourceBioMaterial() );
+ results.put( "children", children );
+ results.put( "siblings", siblings );
+ return results;
}
}
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 551f0d599b..322d29ae8b 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
@@ -20,6 +20,7 @@
import gemma.gsec.SecurityService;
import gemma.gsec.util.SecurityUtil;
+import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.StopWatch;
import org.apache.commons.logging.Log;
@@ -62,6 +63,8 @@
import ubic.gemma.model.expression.arrayDesign.ArrayDesign;
import ubic.gemma.model.expression.arrayDesign.TechnologyType;
import ubic.gemma.model.expression.bioAssay.BioAssay;
+import ubic.gemma.model.expression.bioAssayData.BioAssayDimension;
+import ubic.gemma.model.expression.bioAssayData.DataVector;
import ubic.gemma.model.expression.biomaterial.BioMaterial;
import ubic.gemma.model.expression.experiment.*;
import ubic.gemma.model.genome.Taxon;
@@ -71,8 +74,10 @@
import ubic.gemma.persistence.service.common.auditAndSecurity.AuditEventService;
import ubic.gemma.persistence.service.common.auditAndSecurity.AuditTrailService;
import ubic.gemma.persistence.service.common.description.BibliographicReferenceService;
+import ubic.gemma.persistence.service.common.quantitationtype.QuantitationTypeService;
import ubic.gemma.persistence.service.expression.arrayDesign.ArrayDesignService;
import ubic.gemma.persistence.service.expression.bioAssay.BioAssayService;
+import ubic.gemma.persistence.service.expression.bioAssayData.BioAssayDimensionService;
import ubic.gemma.persistence.service.expression.biomaterial.BioMaterialService;
import ubic.gemma.persistence.service.expression.experiment.*;
import ubic.gemma.persistence.service.genome.taxon.TaxonService;
@@ -97,6 +102,7 @@
import java.text.NumberFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
import static ubic.gemma.core.analysis.preprocess.batcheffects.BatchEffectUtils.getBatchEffectStatistics;
import static ubic.gemma.core.analysis.preprocess.batcheffects.BatchEffectUtils.getBatchEffectType;
@@ -173,6 +179,10 @@ public class ExpressionExperimentController {
private BuildInfo buildInfo;
@Autowired
private WebEntityUrlBuilder entityUrlBuilder;
+ @Autowired
+ private BioAssayDimensionService bioAssayDimensionService;
+ @Autowired
+ private QuantitationTypeService quantitationTypeService;
/**
* AJAX call for remote paging store security isn't incorporated in db query, so paging needs to occur at higher
@@ -885,37 +895,27 @@ public ModelAndView showAllLinkSummaries() {
@RequestMapping(value = { "/showBioAssaysFromExpressionExperiment.html", "/bioAssays" }, method = { RequestMethod.GET, RequestMethod.HEAD })
public ModelAndView showBioAssays( @RequestParam("id") Long id ) {
ExpressionExperiment expressionExperiment = getExperimentById( id, true );
- ModelAndView mv = new ModelAndView( "bioAssays" ).addObject( "bioAssays", bioAssayService.thaw( expressionExperiment.getBioAssays() ) );
- this.addQCInfo( expressionExperiment, mv );
- mv.addObject( "expressionExperiment", expressionExperiment );
- return mv;
+ return new ModelAndView( "expressionExperiment.bioAssays" )
+ .addObject( "expressionExperiment", expressionExperiment )
+ .addObject( "keywords", getKeywords( expressionExperiment ) )
+ .addAllObjects( addQCInfo( expressionExperiment ) );
}
@RequestMapping(value = { "/showBioMaterialsFromExpressionExperiment.html", "/bioMaterials" }, method = { RequestMethod.GET, RequestMethod.HEAD })
public ModelAndView showBioMaterials( @RequestParam("id") Long id ) {
ExpressionExperiment expressionExperiment = getExperimentById( id, true );
+ return new ModelAndView( "expressionExperiment.bioMaterials" )
+ .addObject( "expressionExperiment", expressionExperiment )
+ .addObject( "keywords", getKeywords( expressionExperiment ) )
+ .addObject( "bioMaterials", getBioMaterials( expressionExperiment ) )
+ .addAllObjects( addQCInfo( expressionExperiment ) );
+ }
- Collection bioAssays = expressionExperiment.getBioAssays();
- Collection bioMaterials = new ArrayList<>();
- for ( BioAssay assay : bioAssays ) {
- BioMaterial material = assay.getSampleUsed();
- if ( material != null ) {
- bioMaterials.add( material );
- }
- }
-
- ModelAndView mav = new ModelAndView( "bioMaterials" );
- if ( ExpressionExperimentController.AJAX ) {
- mav.addObject( "bioMaterialIdList", bioMaterialService.getBioMaterialIdList( bioMaterials ) );
- }
-
- Integer numBioMaterials = bioMaterials.size();
- mav.addObject( "numBioMaterials", numBioMaterials );
- mav.addObject( "bioMaterials", bioMaterialService.thaw( bioMaterials ) );
-
- this.addQCInfo( expressionExperiment, mav );
-
- return mav;
+ private Collection getBioMaterials( ExpressionExperiment ee ) {
+ return bioMaterialService.thaw( ee.getBioAssays().stream()
+ .map( BioAssay::getSampleUsed )
+ .filter( Objects::nonNull )
+ .collect( Collectors.toSet() ) );
}
@RequestMapping(value = { "/showExpressionExperiment.html", "/", "/show" }, params = { "id" }, method = { RequestMethod.GET, RequestMethod.HEAD })
@@ -940,21 +940,101 @@ public ModelAndView showExpressionExperimentByShortName( @RequestParam(value = "
private ModelAndView showExpressionExperiment( ExpressionExperiment ee ) {
return new ModelAndView( "expressionExperiment.detail" )
.addObject( "expressionExperiment", ee )
- .addObject( "eeId", ee.getId() )
- .addObject( "eeClass", ee.getClass() );
+ .addObject( "keywords", getKeywords( ee ) );
+ }
+
+ private String getKeywords( ExpressionExperiment ee ) {
+ return expressionExperimentService.getAnnotations( ee ).stream()
+ .map( AnnotationValueObject::getTermName )
+ .collect( Collectors.joining( "," ) );
+ }
+
+ @RequestMapping(value = { "/showAllExpressionExperimentSubSets.html", "/showSubsets" }, method = { RequestMethod.GET, RequestMethod.HEAD }, params = { "id" })
+ public ModelAndView showAllSubSets( @RequestParam("id") Long id ) {
+ return showAllSubSets( getExperimentById( id, true ) );
+ }
+
+ @RequestMapping(value = { "/showAllExpressionExperimentSubSets.html", "/showSubsets" }, method = { RequestMethod.GET, RequestMethod.HEAD }, params = { "shortName" })
+ public ModelAndView showAllSubSets( @RequestParam("shortName") String shortName ) {
+ return showAllSubSets( getExperimentByShortName( shortName, true ) );
+ }
+
+ private ModelAndView showAllSubSets( ExpressionExperiment ee ) {
+ Map> subsetsByDimension = expressionExperimentService.getSubSetsByDimension( ee );
+ Map> quantitationTypesByDimension = new LinkedHashMap<>();
+ for ( BioAssayDimension bad : subsetsByDimension.keySet() ) {
+ List qts = quantitationTypeService.findByExpressionExperimentAndDimension( ee, bad ).stream()
+ .sorted( Comparator.comparing( QuantitationType::getName ) )
+ .collect( Collectors.toList() );
+ quantitationTypesByDimension.put( bad, qts );
+ }
+ Set qts = quantitationTypesByDimension.values().stream()
+ .flatMap( List::stream )
+ .collect( Collectors.toSet() );
+ Map> vectorTypes = quantitationTypeService.getDataVectorTypes( qts );
+ Map> subsetsByDimensionSorted = subsetsByDimension.entrySet().stream()
+ .sorted( Map.Entry.comparingByKey( Comparator
+ // show dimension with vectors first
+ .comparing( ( BioAssayDimension d ) -> quantitationTypesByDimension.get( d ).size(), Comparator.reverseOrder() )
+ .thenComparing( BioAssayDimension::getName )
+ .thenComparing( BioAssayDimension::getId ) ) )
+ .collect( Collectors.toMap( Map.Entry::getKey, e -> e.getValue().stream().sorted( Comparator.comparing( ExpressionExperimentSubSet::getName ) ).collect( Collectors.toList() ), ( a, b ) -> b, LinkedHashMap::new ) );
+ return new ModelAndView( "expressionExperiment.subSets" )
+ .addObject( "expressionExperiment", ee )
+ .addObject( "subSetsByDimension", subsetsByDimensionSorted )
+ .addObject( "quantitationTypesByDimension", quantitationTypesByDimension )
+ .addObject( "vectorTypes", vectorTypes )
+ .addObject( "keywords", getKeywords( ee ) );
}
/**
* Shows a list of BioAssays for an expression experiment subset.
*/
@RequestMapping(value = { "/showExpressionExperimentSubSet.html", "/showSubset" }, method = { RequestMethod.GET, RequestMethod.HEAD })
- public ModelAndView showSubSet( @RequestParam("id") Long id ) {
- ExpressionExperimentSubSet subset = expressionExperimentSubSetService.load( id );
+ public ModelAndView showSubSet( @RequestParam("id") Long id, @RequestParam(value = "dimension", required = false) Long dimensionId ) {
+ ExpressionExperimentSubSet subset = expressionExperimentSubSetService.loadWithBioAssays( id );
if ( subset == null ) {
throw new EntityNotFoundException( "No experiment subset with ID " + id + "." );
}
- // request.setAttribute( "id", id );
- return new ModelAndView( "bioAssays" ).addObject( "bioAssays", subset.getBioAssays() );
+ BioAssayDimension dimension;
+ Collection possibleDimensions = bioAssayDimensionService.findByBioAssayContainsAll( subset.getBioAssays() );
+ if ( dimensionId != null ) {
+ dimension = bioAssayDimensionService.loadOrFail( dimensionId, EntityNotFoundException::new );
+ if ( !CollectionUtils.containsAll( dimension.getBioAssays(), subset.getBioAssays() ) ) {
+ throw new IllegalArgumentException( dimension + " is not applicable to the requested subset." );
+ }
+ possibleDimensions = Collections.emptySet();
+ } else if ( possibleDimensions.size() == 1 ) {
+ dimension = possibleDimensions.iterator().next();
+ } else {
+ // either no dimension or multiple dimensions, one must be picked
+ dimension = null;
+ }
+ Collection otherSubSets;
+ List bioAssays;
+ if ( dimension != null ) {
+ otherSubSets = expressionExperimentSubSetService.findByBioAssayIn( dimension.getBioAssays() ).stream()
+ .filter( ss -> !ss.equals( subset ) )
+ .sorted( Comparator.comparing( ExpressionExperimentSubSet::getName ) )
+ .collect( Collectors.toList() );
+ bioAssays = subset.getBioAssays().stream().sorted( Comparator.comparing( BioAssay::getName ) )
+ .filter( ba -> dimension.getBioAssays().contains( ba ) )
+ .collect( Collectors.toList() );
+ } else {
+ otherSubSets = Collections.emptySet();
+ bioAssays = Collections.emptyList();
+ }
+ Set annotations = expressionExperimentService.getAnnotations( subset );
+ return new ModelAndView( "expressionExperimentSubSet.detail" )
+ .addObject( "subSet", subset )
+ .addObject( "dimension", dimension )
+ .addObject( "possibleDimensions", possibleDimensions )
+ .addObject( "otherSubSets", otherSubSets )
+ .addObject( "bioAssays", bioAssays )
+ .addObject( "annotations", annotations )
+ .addObject( "keywords", annotations.stream()
+ .map( AnnotationValueObject::getTermName )
+ .collect( Collectors.joining( "," ) ) );
}
/**
@@ -1264,20 +1344,22 @@ private void setPreferredAndReprocessed( ExpressionExperimentDetailsValueObject
finalResult.setReprocessedFromRawData( dataReprocessedFromRaw );
}
- private void addQCInfo( ExpressionExperiment expressionExperiment, ModelAndView mav ) {
- mav.addObject( "hasCorrMat", sampleCoexpressionAnalysisService.hasAnalysis( expressionExperiment ) );
- mav.addObject( "hasPvalueDist", ExpressionExperimentQCUtils.hasPvalueDistFiles( expressionExperiment ) );
- mav.addObject( "hasPCA", svdService.hasPca( expressionExperiment ) );
- mav.addObject( "hasMeanVariance", expressionExperiment.getMeanVarianceRelation() != null );
+ private Map addQCInfo( ExpressionExperiment expressionExperiment ) {
+ Map result = new HashMap<>();
+ result.put( "hasCorrMat", sampleCoexpressionAnalysisService.hasAnalysis( expressionExperiment ) );
+ result.put( "hasPvalueDist", ExpressionExperimentQCUtils.hasPvalueDistFiles( expressionExperiment ) );
+ result.put( "hasPCA", svdService.hasPca( expressionExperiment ) );
+ result.put( "hasMeanVariance", expressionExperiment.getMeanVarianceRelation() != null );
// FIXME don't store in a file.
- mav.addObject( "hasNodeDegreeDist", ExpressionExperimentQCUtils.hasNodeDegreeDistFile( expressionExperiment ) );
+ result.put( "hasNodeDegreeDist", ExpressionExperimentQCUtils.hasNodeDegreeDistFile( expressionExperiment ) );
- mav.addObject( "numFactors", ExpressionExperimentQCUtils.numFactors( expressionExperiment ) );
- mav.addObject( "hasCorrDist", true ); // FIXME
+ result.put( "numFactors", ExpressionExperimentQCUtils.numFactors( expressionExperiment ) );
+ result.put( "hasCorrDist", true ); // FIXME
- mav.addObject( "numPossibleOutliers", this.numPossibleOutliers( expressionExperiment ) );
- mav.addObject( "numOutliersRemoved", this.numOutliersRemoved( expressionExperiment ) );
+ result.put( "numPossibleOutliers", this.numPossibleOutliers( expressionExperiment ) );
+ result.put( "numOutliersRemoved", this.numOutliersRemoved( expressionExperiment ) );
+ return result;
}
/**
@@ -1705,4 +1787,16 @@ private ExpressionExperiment getExperimentById( Long id, boolean thawLite ) thro
EntityNotFoundException::new, "No experiment with ID " + id + "." );
}
}
+
+
+ /**
+ * Load an {@link ExpressionExperiment} by short name, optionally thawing it with {@link ExpressionExperimentService#thawLite}.
+ */
+ private ExpressionExperiment getExperimentByShortName( String shortName, boolean thawLite ) throws EntityNotFoundException {
+ ExpressionExperiment ee = this.expressionExperimentService.findByShortName( shortName );
+ if ( ee == null ) {
+ throw new EntityNotFoundException( "No experiment with short name " + shortName + "." );
+ }
+ return thawLite ? expressionExperimentService.thawLite( ee ) : ee;
+ }
}
diff --git a/gemma-web/src/main/java/ubic/gemma/web/controller/expression/experiment/ExpressionExperimentSetController.java b/gemma-web/src/main/java/ubic/gemma/web/controller/expression/experiment/ExpressionExperimentSetController.java
index b23d25f10b..0f4c2a7281 100644
--- a/gemma-web/src/main/java/ubic/gemma/web/controller/expression/experiment/ExpressionExperimentSetController.java
+++ b/gemma-web/src/main/java/ubic/gemma/web/controller/expression/experiment/ExpressionExperimentSetController.java
@@ -27,6 +27,7 @@
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import ubic.gemma.model.analysis.expression.ExpressionExperimentSet;
import ubic.gemma.model.expression.experiment.ExpressionExperimentDetailsValueObject;
@@ -39,7 +40,6 @@
import ubic.gemma.web.persistence.SessionListManager;
import ubic.gemma.web.util.EntityNotFoundException;
-import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
@@ -343,22 +343,17 @@ public Collection removeUserAndSessionGroups
}
@RequestMapping(value = "/showExpressionExperimentSet.html", method = { RequestMethod.GET, RequestMethod.HEAD })
- public ModelAndView showExpressionExperimentSet( HttpServletRequest request ) {
-
- ModelAndView mav = new ModelAndView( "expressionExperimentSet.detail" );
- StopWatch timer = new StopWatch();
- timer.start();
-
- ExpressionExperimentSetValueObject eesvo = this.getExpressionExperimentSetFromRequest( request );
-
- mav.addObject( "eeSetId", eesvo.getId() );
- mav.addObject( "eeSetName", eesvo.getName() );
-
+ public ModelAndView showExpressionExperimentSet( @RequestParam("id") Long id ) {
+ StopWatch timer = StopWatch.createStarted();
+ ExpressionExperimentSetValueObject eesvo = expressionExperimentSetService.loadValueObjectById( id );
+ if ( eesvo == null ) {
+ throw new EntityNotFoundException( "No experiment set with ID " + id );
+ }
if ( timer.getTime() > 200 ) {
log.info( "Show experiment set was slow: id=" + eesvo.getId() + " " + timer.getTime() + "ms" );
}
-
- return mav;
+ return new ModelAndView( "expressionExperimentSet.detail" )
+ .addObject( "eeSet", eesvo );
}
/**
@@ -454,31 +449,6 @@ private ExpressionExperimentSet create( ExpressionExperimentSetValueObject obj )
return expressionExperimentSetValueObjectHelper.create( obj );
}
- /**
- * @throws IllegalArgumentException if a matching EE can't be loaded
- */
- private ExpressionExperimentSetValueObject getExpressionExperimentSetFromRequest( HttpServletRequest request ) {
-
- ExpressionExperimentSetValueObject set;
- Long id;
-
- if ( request.getParameter( "id" ) != null ) {
- try {
- id = Long.parseLong( request.getParameter( "id" ) );
- } catch ( NumberFormatException e ) {
- throw new IllegalArgumentException( "You must provide a valid numerical identifier" );
- }
- set = expressionExperimentSetService.loadValueObjectById( id );
-
- if ( set == null ) {
- throw new EntityNotFoundException( "Unable to access experiment set with id=" + id );
- }
- } else {
- throw new IllegalArgumentException( "You must provide an id" );
- }
- return set;
- }
-
/**
* Delete a EEset from the system.
*
diff --git a/gemma-web/src/main/java/ubic/gemma/web/controller/expression/experiment/TaxonController.java b/gemma-web/src/main/java/ubic/gemma/web/controller/expression/experiment/TaxonController.java
new file mode 100644
index 0000000000..c523950194
--- /dev/null
+++ b/gemma-web/src/main/java/ubic/gemma/web/controller/expression/experiment/TaxonController.java
@@ -0,0 +1,59 @@
+package ubic.gemma.web.controller.expression.experiment;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.servlet.ModelAndView;
+import ubic.gemma.model.genome.Taxon;
+import ubic.gemma.persistence.service.expression.experiment.ExpressionExperimentService;
+import ubic.gemma.persistence.service.genome.taxon.TaxonService;
+import ubic.gemma.web.util.EntityNotFoundException;
+
+import javax.annotation.Nullable;
+
+@Controller
+@RequestMapping("/taxon")
+public class TaxonController {
+
+ @Autowired
+ private TaxonService taxonService;
+
+ @Autowired
+ private ExpressionExperimentService expressionExperimentService;
+
+ @RequestMapping("/showAllTaxa.html")
+ public ModelAndView showAllTxa() {
+ return new ModelAndView( "taxa" )
+ .addObject( "taxa", taxonService.loadAll() );
+ }
+
+ @RequestMapping(value = "/showTaxon.html", params = { "id" })
+ public ModelAndView showTaxonById( @RequestParam("id") Long id ) {
+ return showTaxon( taxonService.load( id ), "ID", id.toString() );
+ }
+
+ @RequestMapping(value = "/showTaxon.html", params = { "ncbiId" })
+ public ModelAndView showTaxonByNcbiId( @RequestParam("ncbiId") Integer ncbiId ) {
+ return showTaxon( taxonService.findByNcbiId( ncbiId ), "NCBI ID", ncbiId.toString() );
+ }
+
+ @RequestMapping(value = "/showTaxon.html", params = { "commonName" })
+ public ModelAndView showTaxonByCommonName( @RequestParam("commonName") String name ) {
+ return showTaxon( taxonService.findByCommonName( name ), "common name", name );
+ }
+
+ @RequestMapping(value = "/showTaxon.html", params = { "scientificName" })
+ public ModelAndView showTaxonByScientificName( @RequestParam("scientificName") String name ) {
+ return showTaxon( taxonService.findByCommonName( name ), "scientific name", name );
+ }
+
+ private ModelAndView showTaxon( @Nullable Taxon taxon, String idType, String val ) {
+ if ( taxon == null ) {
+ throw new EntityNotFoundException( "No taxon found with " + idType + " " + val );
+ }
+ return new ModelAndView( "taxon.detail" )
+ .addObject( "taxon", taxon )
+ .addObject( "numberOfExperiments", expressionExperimentService.getPerTaxonCount().getOrDefault( taxon, 0L ) );
+ }
+}
diff --git a/gemma-web/src/main/java/ubic/gemma/web/controller/genome/gene/GeneController.java b/gemma-web/src/main/java/ubic/gemma/web/controller/genome/gene/GeneController.java
index 6c1197e451..fe87c2ff99 100644
--- a/gemma-web/src/main/java/ubic/gemma/web/controller/genome/gene/GeneController.java
+++ b/gemma-web/src/main/java/ubic/gemma/web/controller/genome/gene/GeneController.java
@@ -145,15 +145,8 @@ public ModelAndView show( HttpServletRequest request ) {
Long id = geneVO.getId();
assert id != null;
- ModelAndView mav = new ModelAndView( "gene.detail" );
- mav.addObject( "geneId", id );
- mav.addObject( "geneOfficialSymbol", geneVO.getOfficialSymbol() );
- mav.addObject( "geneOfficialName", geneVO.getOfficialName() );
- mav.addObject( "geneNcbiId", geneVO.getNcbiId() );
- mav.addObject( "geneTaxonCommonName", geneVO.getTaxonCommonName() );
- mav.addObject( "geneTaxonId", geneVO.getTaxonId() );
-
- return mav;
+ return new ModelAndView( "gene.detail" )
+ .addObject( "gene", geneVO );
}
@RequestMapping(value = "/downloadGeneList.html", method = { RequestMethod.GET, RequestMethod.HEAD })
diff --git a/gemma-web/src/main/java/ubic/gemma/web/controller/genome/gene/GeneSetController.java b/gemma-web/src/main/java/ubic/gemma/web/controller/genome/gene/GeneSetController.java
index cd03998444..63c25834af 100755
--- a/gemma-web/src/main/java/ubic/gemma/web/controller/genome/gene/GeneSetController.java
+++ b/gemma-web/src/main/java/ubic/gemma/web/controller/genome/gene/GeneSetController.java
@@ -26,15 +26,16 @@
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
-import ubic.gemma.model.genome.gene.SessionBoundGeneSetValueObject;
-import ubic.gemma.persistence.service.genome.gene.GeneSetService;
import ubic.gemma.core.search.ParseSearchException;
import ubic.gemma.core.search.SearchException;
import ubic.gemma.model.genome.TaxonValueObject;
import ubic.gemma.model.genome.gene.DatabaseBackedGeneSetValueObject;
import ubic.gemma.model.genome.gene.GeneSetValueObject;
import ubic.gemma.model.genome.gene.GeneValueObject;
+import ubic.gemma.model.genome.gene.SessionBoundGeneSetValueObject;
+import ubic.gemma.persistence.service.genome.gene.GeneSetService;
import ubic.gemma.web.persistence.SessionListManager;
import ubic.gemma.web.util.EntityNotFoundException;
@@ -357,20 +358,15 @@ public Collection removeUserAndSessionGroups( Collection
+ * The default is to generate an internal link.
+ */
+ private boolean external;
+
+ @Override
+ public int doStartTagInternal() throws JspException {
+ Assert.notNull( characteristic, "The characteristic attribute must be set." );
+ String gemBrowUrl = ( String ) getAppConfig().get( "gemma.gemBrow.url" );
+ TagWriter tagWriter = new TagWriter( pageContext );
+ if ( !category && characteristic.getValue() != null ) {
+ if ( characteristic.getValueUri() != null ) {
+ tagWriter.startTag( "a" );
+ if ( external ) {
+ tagWriter.writeAttribute( "href", characteristic.getValueUri() );
+ tagWriter.writeAttribute( "target", "_blank" );
+ tagWriter.writeAttribute( "rel", "noreferred noopener" );
+ } else {
+ tagWriter.writeAttribute( "href", gemBrowUrl + "/#/q/" + urlEncode( characteristic.getValueUri() ) );
+ }
+ tagWriter.writeOptionalAttributeValue( "title", characteristic.getCategory() );
+ }
+ tagWriter.startTag( "span" );
+ tagWriter.appendValue( characteristic.getValue() );
+ tagWriter.endTag();
+ if ( characteristic.getValueUri() != null ) {
+ tagWriter.endTag();
+ }
+ } else if ( characteristic.getCategory() != null ) {
+ if ( characteristic.getCategoryUri() != null ) {
+ tagWriter.startTag( "a" );
+ if ( external ) {
+ tagWriter.writeAttribute( "href", characteristic.getCategoryUri() );
+ tagWriter.writeAttribute( "target", "_blank" );
+ tagWriter.writeAttribute( "rel", "noreferred noopener" );
+ } else {
+ tagWriter.writeAttribute( "href", gemBrowUrl + "/#/q/" + urlEncode( characteristic.getCategoryUri() ) );
+ }
+ }
+ tagWriter.startTag( "span" );
+ tagWriter.appendValue( characteristic.getCategory() );
+ tagWriter.endTag();
+ if ( characteristic.getCategoryUri() != null ) {
+ tagWriter.endTag();
+ }
+ } else {
+ tagWriter.startTag( "i" );
+ tagWriter.appendValue( "Uncategorized" );
+ tagWriter.endTag();
+ }
+ return SKIP_BODY;
+ }
+
+ private Map getAppConfig() {
+ //noinspection unchecked
+ return ( Map ) requireNonNull( pageContext.getAttribute( Constants.CONFIG, PageContext.APPLICATION_SCOPE ) );
+ }
+
+ private String urlEncode( String s ) {
+ try {
+ return URLEncoder.encode( s, StandardCharsets.UTF_8.name() );
+ } catch ( UnsupportedEncodingException e ) {
+ throw new RuntimeException( e );
+ }
+ }
+}
diff --git a/gemma-web/src/main/java/ubic/gemma/web/taglib/DatabaseEntryTag.java b/gemma-web/src/main/java/ubic/gemma/web/taglib/DatabaseEntryTag.java
index 4f05ad5772..90bac70902 100644
--- a/gemma-web/src/main/java/ubic/gemma/web/taglib/DatabaseEntryTag.java
+++ b/gemma-web/src/main/java/ubic/gemma/web/taglib/DatabaseEntryTag.java
@@ -48,7 +48,7 @@ public int doStartTag() throws JspException {
StringBuilder buf = new StringBuilder();
if ( this.databaseEntry == null ) {
- buf.append( "No accession" );
+ buf.append( "No accession available " );
} else {
String accession = databaseEntry.getAccession();
@@ -58,12 +58,12 @@ public int doStartTag() throws JspException {
accession = accession.replaceAll( "\\.[1-9]$", "" );
buf.append( accession ).append( " " );
} else if ( databaseEntry.getExternalDatabase().getName().equalsIgnoreCase( "ArrayExpress" ) ) {
buf.append( accession ).append( " " );
} else {
diff --git a/gemma-web/src/main/java/ubic/gemma/web/taglib/EntityLinkTag.java b/gemma-web/src/main/java/ubic/gemma/web/taglib/EntityLinkTag.java
new file mode 100644
index 0000000000..1e9aa4964c
--- /dev/null
+++ b/gemma-web/src/main/java/ubic/gemma/web/taglib/EntityLinkTag.java
@@ -0,0 +1,63 @@
+package ubic.gemma.web.taglib;
+
+import org.springframework.web.servlet.tags.RequestContextAwareTag;
+import ubic.gemma.model.common.Identifiable;
+import ubic.gemma.web.util.WebEntityUrlBuilder;
+
+import javax.annotation.Nullable;
+import javax.servlet.jsp.JspException;
+import javax.servlet.jsp.JspTagException;
+
+import static org.apache.commons.text.StringEscapeUtils.escapeHtml4;
+
+/**
+ * Tag that generates an HTML link for a given {@link Identifiable} entity.
+ * @author poirigui
+ * @see WebEntityUrlBuilder
+ */
+public class EntityLinkTag extends RequestContextAwareTag {
+
+ private Identifiable entity;
+ private boolean external;
+ @Nullable
+ private String title;
+
+ @Override
+ protected int doStartTagInternal() throws Exception {
+ WebEntityUrlBuilder builder = getRequestContext().getWebApplicationContext().getBean( WebEntityUrlBuilder.class );
+ String uri;
+ if ( external ) {
+ uri = builder.fromHostUrl().entity( entity ).web().toUriString();
+ } else {
+ uri = builder.fromContextPath().entity( entity ).web().toUriString();
+ }
+ pageContext.getOut().write( "" );
+ return EVAL_BODY_INCLUDE;
+ }
+
+ @Override
+ public int doEndTag() throws JspException {
+ try {
+ pageContext.getOut().write( " " );
+ return EVAL_PAGE;
+ } catch ( Exception e ) {
+ throw new JspTagException( e );
+ }
+ }
+
+ public void setEntity( Identifiable entity ) {
+ this.entity = entity;
+ }
+
+ public void setTitle( @Nullable String title ) {
+ this.title = title;
+ }
+
+ public void setExternal( boolean external ) {
+ this.external = external;
+ }
+}
diff --git a/gemma-web/src/main/java/ubic/gemma/web/taglib/common/auditAndSecurity/ExceptionTag.java b/gemma-web/src/main/java/ubic/gemma/web/taglib/common/auditAndSecurity/ExceptionTag.java
index 10bf7903d2..f264f4c81b 100644
--- a/gemma-web/src/main/java/ubic/gemma/web/taglib/common/auditAndSecurity/ExceptionTag.java
+++ b/gemma-web/src/main/java/ubic/gemma/web/taglib/common/auditAndSecurity/ExceptionTag.java
@@ -18,12 +18,18 @@
*/
package ubic.gemma.web.taglib.common.auditAndSecurity;
+import lombok.Setter;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.springframework.security.access.AccessDecisionManager;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.security.access.SecurityConfig;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.web.servlet.tags.RequestContextAwareTag;
+import ubic.gemma.core.context.EnvironmentProfiles;
import javax.servlet.jsp.tagext.Tag;
-import javax.servlet.jsp.tagext.TagSupport;
import static org.apache.commons.text.StringEscapeUtils.escapeHtml4;
@@ -31,32 +37,51 @@
/**
* @author pavlidis
*/
-@SuppressWarnings("unused") // Frontend use
-public class ExceptionTag extends TagSupport {
+@Setter
+public class ExceptionTag extends RequestContextAwareTag {
private static final long serialVersionUID = 4323477499674966726L;
private static final Log log = LogFactory.getLog( ExceptionTag.class.getName() );
+ /**
+ * Exception to display.
+ */
private Exception exception;
- private Boolean showStackTrace = true;
+
+ /**
+ * Display the stacktrace.
+ *
+ * Note: the stack trace is never display to non-administrators.
+ */
+ private boolean showStackTrace = true;
@Override
- public int doStartTag() {
+ public int doStartTagInternal() {
try {
final StringBuilder buf = new StringBuilder();
+ buf.append( "
" );
if ( this.exception == null ) {
buf.append( "Error was not recovered" );
} else {
- if ( showStackTrace ) {
- buf.append( "
" );
- if ( exception.getStackTrace() != null ) {
- buf.append( escapeHtml4( ExceptionUtils.getStackTrace( exception ) ) );
- } else {
- buf.append( "There was no stack trace!" );
- }
+ buf.append( "
" ).append( escapeHtml4( exception.getMessage() ) ).append( "
" );
+ if ( showStackTrace && ( isDev() || isAdmin() ) ) {
+ buf.append( "
" );
+ buf.append( escapeHtml4( ExceptionUtils.getStackTrace( exception ) ) );
buf.append( "
" );
+ if ( exception.getCause() != null ) {
+ Throwable rootCause = ExceptionUtils.getRootCause( exception );
+ buf.append( "
Root cause " );
+ buf.append( "
" ).append( escapeHtml4( rootCause.getMessage() ) ).append( "
" );
+ buf.append( "
" );
+ buf.append( escapeHtml4( ExceptionUtils.getStackTrace( rootCause ) ) );
+ buf.append( "
" );
+ }
+ if ( isDev() && !isAdmin() ) {
+ buf.append( "
Note: You are in development mode, so you can see the stack trace. Otherwise only administrators can see this.
" );
+ }
}
}
+ buf.append( "
" );
pageContext.getOut().print( buf.toString() );
} catch ( Exception ex ) {
/*
@@ -75,15 +100,27 @@ public int doEndTag() {
return Tag.EVAL_PAGE;
}
- public void setException( Exception exception ) {
- this.exception = exception;
+ /**
+ * Check if the development profile is active.
+ */
+ private boolean isDev() {
+ return getRequestContext().getWebApplicationContext().getEnvironment()
+ .acceptsProfiles( EnvironmentProfiles.DEV );
}
/**
- * @param showStackTrace the showStackTrace to set
+ * Check if the current user is an administrator.
*/
- public void setShowStackTrace( Boolean showStackTrace ) {
- this.showStackTrace = showStackTrace;
+ private boolean isAdmin() {
+ // this bean is declared twice: once for method security in gemma-core and a second time for Web security
+ AccessDecisionManager accessDecisionManager = getRequestContext().getWebApplicationContext()
+ .getBean( "httpAccessDecisionManager", AccessDecisionManager.class );
+ try {
+ accessDecisionManager.decide( SecurityContextHolder.getContext().getAuthentication(), null,
+ SecurityConfig.createList( "GROUP_ADMIN" ) );
+ return true;
+ } catch ( AccessDeniedException e ) {
+ return false;
+ }
}
-
}
diff --git a/gemma-web/src/main/java/ubic/gemma/web/util/StaticAssetServer.java b/gemma-web/src/main/java/ubic/gemma/web/util/StaticAssetServer.java
new file mode 100644
index 0000000000..c44ebc42bd
--- /dev/null
+++ b/gemma-web/src/main/java/ubic/gemma/web/util/StaticAssetServer.java
@@ -0,0 +1,108 @@
+package ubic.gemma.web.util;
+
+import lombok.Getter;
+import lombok.extern.apachecommons.CommonsLog;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.core.env.Environment;
+import org.springframework.stereotype.Component;
+import org.springframework.util.Assert;
+import ubic.gemma.core.context.EnvironmentProfiles;
+import ubic.gemma.web.taglib.AbstractStaticAssetTag;
+
+import javax.servlet.ServletContext;
+import java.io.IOException;
+import java.net.ConnectException;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Arrays;
+
+/**
+ * Configuration for serving static assets externally.
+ * @author poirigui
+ * @see AbstractStaticAssetTag
+ */
+@Getter
+@Component
+@CommonsLog
+public class StaticAssetServer implements InitializingBean {
+
+ @Value("${gemma.staticAssetServer.enabled}")
+ private boolean enabled;
+
+ @Value("${gemma.staticAssetServer.baseUrl}")
+ private String baseUrl;
+
+ /**
+ * Resource directories that are allowed to be served.
+ */
+ @Value("${gemma.staticAssetServer.allowedDirs}")
+ private String[] allowedDirs;
+
+ @Autowired
+ private ServletContext servletContext;
+
+ @Autowired
+ private Environment environment;
+
+ @Override
+ public void afterPropertiesSet() {
+ for ( String allowedDir : allowedDirs ) {
+ Assert.isTrue( allowedDir.startsWith( "/" ) && allowedDir.endsWith( "/" ),
+ "An allowed resource directory must start and end with '/'." );
+ }
+ if ( enabled ) {
+ log.info( "Static assets will be served from " + baseUrl + " for the following paths:\n\t"
+ + String.join( "\n\t", allowedDirs ) );
+ if ( !isAlive() ) {
+ String message = "The static asset server does not appear to be running.";
+ if ( environment.acceptsProfiles( EnvironmentProfiles.DEV ) ) {
+ message += " You may start it with:\n\tnpm --prefix gemma-web/src/main/webapp run serve";
+ }
+ log.warn( message );
+ }
+ } else {
+ log.debug( "Static assets will be served from the webapp resources under the following paths:\n\t"
+ + String.join( "\n\t", allowedDirs ) );
+ }
+ }
+
+ /**
+ * Check if the static asset server is alive.
+ */
+ public boolean isAlive() {
+ if ( !enabled ) {
+ return false;
+ }
+ URLConnection connection = null;
+ try {
+ connection = new URL( baseUrl ).openConnection();
+ connection.connect();
+ return true;
+ } catch ( ConnectException e ) {
+ return false;
+ } catch ( IOException e ) {
+ throw new RuntimeException( "Failed to access the static asset server.", e );
+ } finally {
+ if ( connection instanceof HttpURLConnection ) {
+ ( ( HttpURLConnection ) connection ).disconnect();
+ }
+ }
+ }
+
+ /**
+ * Resolve a URL to a static asset.
+ */
+ public String resolveUrl( String path ) {
+ Assert.isTrue( Arrays.stream( allowedDirs ).anyMatch( path::startsWith ),
+ "Path for static asset must start with one of " + String.join( ",", allowedDirs ) + "." );
+ Assert.isTrue( path.startsWith( "/" ) );
+ if ( enabled ) {
+ return baseUrl + path;
+ } else {
+ return servletContext.getContextPath() + path;
+ }
+ }
+}
diff --git a/gemma-web/src/main/java/ubic/gemma/web/util/StaticServer.java b/gemma-web/src/main/java/ubic/gemma/web/util/StaticServer.java
deleted file mode 100644
index 51e4d06ee9..0000000000
--- a/gemma-web/src/main/java/ubic/gemma/web/util/StaticServer.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package ubic.gemma.web.util;
-
-import lombok.Getter;
-import lombok.extern.apachecommons.CommonsLog;
-import org.springframework.beans.factory.InitializingBean;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-import ubic.gemma.web.taglib.AbstractStaticAssetTag;
-
-/**
- * Configuration for serving static assets externally.
- * @author poirigui
- * @see AbstractStaticAssetTag
- */
-@Getter
-@Component
-@CommonsLog
-public class StaticServer implements InitializingBean {
-
- @Value("${gemma.staticServer.enabled}")
- private boolean enabled;
-
- @Value("${gemma.staticServer.baseUrl}")
- private String baseUrl;
-
- @Override
- public void afterPropertiesSet() {
- if ( enabled ) {
- log.info( "Static assets will be served from " + baseUrl + "." );
- }
- }
-}
diff --git a/gemma-web/src/main/resources/messages.properties b/gemma-web/src/main/resources/messages.properties
index fd0e38bfe8..fd5a4d5b82 100644
--- a/gemma-web/src/main/resources/messages.properties
+++ b/gemma-web/src/main/resources/messages.properties
@@ -552,4 +552,6 @@ ExpressionExperiment.experimentalDesign.experimentalFactors.description=experime
# those appear as "Tagged {}" in the search results
ExpressionExperiment.characteristics.valueUri=annotation
ExpressionExperiment.bioAssays.sampleUsed.characteristics.valueUri=sample annotation
-ExpressionExperiment.experimentalDesign.experimentalFactors.factorValues.characteristics.valueUri=factor value annotation
\ No newline at end of file
+ExpressionExperiment.experimentalDesign.experimentalFactors.factorValues.characteristics.valueUri=factor value annotation
+personDetail.title=Person Details
+personDetail.heading=Person Details
\ No newline at end of file
diff --git a/gemma-web/src/main/resources/messages_es.properties b/gemma-web/src/main/resources/messages_es.properties
index 02581ff73a..eef9b62f98 100644
--- a/gemma-web/src/main/resources/messages_es.properties
+++ b/gemma-web/src/main/resources/messages_es.properties
@@ -177,4 +177,5 @@ viewstream.heading=Stream Information
activeUsers.title=Usuarios Activos
activeUsers.heading=Usuarios Conectados
activeUsers.message=La siguiente lista es de los usuarios que han entrado y sus sesiones no han expirado.
-activeUsers.fullName=Nombre Completo
\ No newline at end of file
+activeUsers.fullName=Nombre Completo
+personDetail.heading=Person Details
\ No newline at end of file
diff --git a/gemma-web/src/main/resources/messages_fr.properties b/gemma-web/src/main/resources/messages_fr.properties
index 2e4617cb15..f50afa1eb4 100644
--- a/gemma-web/src/main/resources/messages_fr.properties
+++ b/gemma-web/src/main/resources/messages_fr.properties
@@ -4,21 +4,21 @@ user.status=Connect
user.logout=Déconnexion
# -- validator errors --
-errors.invalid={0} n'est pas valide.
+errors.invalid={0} n''est pas valide.
errors.maxlength={0} ne peut pas avoir plus de {1} caractères.
errors.minlength={0} ne peut pas avoir moins de {1} caractères.
-errors.range={0} n'est pas dans la plage de {1} à {2}.
+errors.range={0} n''est pas dans la plage de {1} à {2}.
errors.required={0} est un champ requis.
errors.byte={0} doit être un octet.
-errors.date={0} n'est pas une date.
+errors.date={0} n''est pas une date.
errors.double={0} doit être un nombre au format "double".
errors.float={0} doit être un nombre au format "float".
errors.integer={0} doit être un nombre.
errors.long={0} doit être un entier au format "long".
errors.short={0} doit être un entier au format "short".
-errors.email={0} n'est pas une adresse de courriel valide.
-errors.phone={0} n'est pas un numéro de téléphone valide.
-errors.zip={0} n'est pas un code postal (USA ZIP) valide.
+errors.email={0} n''est pas une adresse de courriel valide.
+errors.phone={0} n''est pas un numéro de téléphone valide.
+errors.zip={0} n''est pas un code postal (USA ZIP) valide.
# -- other errors --
errors.cancel=Opération annulée.
@@ -30,7 +30,7 @@ errors.password.mismatch=Identifiant ou mot de passe invalide(s). Veuillez r
errors.browser.warning=
Note : Le contenu de ce site est accessible à tous les navigateurs, quelle que soit leur version. Cependant, ce navigateur peut ne pas prendre en charge certains standards courants du Web, empêchant l'affichage de certaines parties du design de notre site. Nous soutenons les actions de standardisation du Web, cf.
campaign , en recommandant aux utilisateurs de mettre à jour leur navigateur.
errors.conversion=Une erreur est apparue pendant la conversion des valeurs Web en valeurs typées.
errors.twofields=Le champ {0} doit avoir la même valeur que le champ {1}.
-errors.existing.user=L'identifiant (
{0} ) ou l'adresse de courriel (
{1} ) existe déjà. Veuillez essayer un autre identifiant.
+errors.existing.user=L''identifiant (
{0} ) ou l''adresse de courriel (
{1} ) existe déjà. Veuillez essayer un autre identifiant.
# -- success messages --
user.added=Les informations utilisateur pour
{0} ont été ajoutées avec succès.
@@ -45,7 +45,8 @@ reload.succeeded=Les options de rechargement sont completees avec succes.
errorPage.title=Une erreur est apparue
errorPage.heading=Oups !
404.title=Page non trouvée
-404.message=La page que vous avez demandée n'a pas été trouvée. Vous pouvez essayer de retourner à
Main Menu . En attendant, pourquoi pas une belle image pour vous remonter le moral ?
+# single quote must be doubled for {0} placeholder to work
+404.message=La page que vous avez demandée n''a pas été trouvée. Vous pouvez essayer de retourner à
Main Menu . En attendant, pourquoi pas une belle image pour vous remonter le moral ?
403.title=Accès refusé
403.message=Votre rôle actuel ne vous permet pas de voir cette page. Veuillez contacter votre administrateur système si vous pensez en avoir les droits d'accès. Entre temps, pourquoi pas une belle image pour vous remonter le moral ?
@@ -56,7 +57,7 @@ login.rememberMe=Conserver ce mot de passe
login.signup=Pas encore membre ?
Demander un compte.
login.passwordHint=Passeport oublié ? Obtenez votre
mot de passe provisoire, envoyé par courriel .
login.passwordHint.sent=Le mot de passe provisoire pour
{0} a été envoyé à
{1} .
-login.passwordHint.error=L'utilisateur
{0} n'a pas été trouvé dans l'annuaire.
+login.passwordHint.error=L''utilisateur
{0} n''a pas été trouvé dans l''annuaire.
# -- welcome --
welcome.message=
@@ -179,6 +180,7 @@ activeUsers.title=Utilisateurs actifs
activeUsers.heading=Utilisateurs connectés
activeUsers.message=Ci-dessous une liste des utilisateurs qui sont connectés et dont la session n'a pas expiré.
activeUsers.fullName=Nom complet
+personDetail.heading=Person Details
diff --git a/gemma-web/src/main/resources/messages_nl.properties b/gemma-web/src/main/resources/messages_nl.properties
index cc62470be5..f49eb614af 100644
--- a/gemma-web/src/main/resources/messages_nl.properties
+++ b/gemma-web/src/main/resources/messages_nl.properties
@@ -176,4 +176,5 @@ viewstream.heading=Stream informatie
activeUsers.title=Actieve gebruikers
activeUsers.heading=Huidige gebruikers
activeUsers.message=De volgende gebruikers zijn ingelogd en hebben een geldige sessie.
-activeUsers.fullName=Volledige naam
\ No newline at end of file
+activeUsers.fullName=Volledige naam
+personDetail.heading=Person Details
\ No newline at end of file
diff --git a/gemma-web/src/main/resources/messages_pt_BR.properties b/gemma-web/src/main/resources/messages_pt_BR.properties
index f07ad34a74..cfab4aee26 100644
--- a/gemma-web/src/main/resources/messages_pt_BR.properties
+++ b/gemma-web/src/main/resources/messages_pt_BR.properties
@@ -177,4 +177,5 @@ activeUsers.title=Usu
activeUsers.heading=Usuários Corrente
activeUsers.message=O seguinte é uma lista de usuários que se registraram e as suas sessões não expiraram.
activeUsers.fullName=Todo Nome
+personDetail.heading=Person Details
diff --git a/gemma-web/src/main/webapp/WEB-INF/Gemma.tld b/gemma-web/src/main/webapp/WEB-INF/Gemma.tld
index 0f072d85fb..0d22ee9b87 100644
--- a/gemma-web/src/main/webapp/WEB-INF/Gemma.tld
+++ b/gemma-web/src/main/webapp/WEB-INF/Gemma.tld
@@ -1,16 +1,16 @@
+ xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-jsptaglibrary_2_0.xsd">
+
Custom tag library for Gemma
+ Gemma
1.0
Gemma
-
-
+ Display an exception
exception
- ubic.gemma.web.taglib.common.auditAndSecurity.ExceptionTag
-
+ ubic.gemma.web.taglib.common.auditAndSecurity.ExceptionTag
empty
exception
@@ -23,11 +23,9 @@
-
assayView
- ubic.gemma.web.taglib.expression.experiment.AssayViewTag
-
+ ubic.gemma.web.taglib.expression.experiment.AssayViewTag
empty
bioAssays
@@ -40,11 +38,10 @@
-
+ Display an array design group (subsumer/subsumees)
arrayDesignGrouping
- ubic.gemma.web.taglib.arrayDesign.ArrayDesignGroupingTag
-
+ ubic.gemma.web.taglib.arrayDesign.ArrayDesignGroupingTag
empty
subsumer
@@ -56,11 +53,10 @@
-
+ Display a citation
citation
- ubic.gemma.web.taglib.ShortBibliographicReferenceTag
-
+ ubic.gemma.web.taglib.ShortBibliographicReferenceTag
empty
citation
@@ -69,8 +65,6 @@
-
-
constants
ubic.gemma.web.taglib.ConstantsTag
@@ -90,13 +84,11 @@
-
+ Display QC information for the experiment
expressionQC
- ubic.gemma.web.taglib.expression.experiment.ExperimentQCTag
-
+ ubic.gemma.web.taglib.expression.experiment.ExperimentQCTag
empty
- Display QC information for the experiment
ID of the experiment
ee
@@ -150,10 +142,11 @@
true
+
+ Display a database entry
databaseEntry
- ubic.gemma.web.taglib.DatabaseEntryTag
-
+ ubic.gemma.web.taglib.DatabaseEntryTag
empty
databaseEntry
@@ -167,6 +160,45 @@
+
+ Display a characteristic
+ characteristic
+ ubic.gemma.web.taglib.CharacteristicTag
+ empty
+
+ characteristic
+ true
+ true
+
+
+ category
+ false
+ true
+
+
+
+
+ Display a link for any identifiable entity
+ entityLink
+ ubic.gemma.web.taglib.EntityLinkTag
+ JSP
+
+ entity
+ true
+ true
+
+
+ title
+ false
+ true
+
+
+ external
+ false
+ true
+
+
+
script
ubic.gemma.web.taglib.ScriptTag
@@ -224,4 +256,10 @@
true
+
+
+ urlEncode
+ java.net.URLEncoder
+ java.lang.String encode(java.lang.String, java.lang.String)
+
diff --git a/gemma-web/src/main/webapp/WEB-INF/web.xml b/gemma-web/src/main/webapp/WEB-INF/web.xml
index be197d337a..907ab4f233 100644
--- a/gemma-web/src/main/webapp/WEB-INF/web.xml
+++ b/gemma-web/src/main/webapp/WEB-INF/web.xml
@@ -221,10 +221,10 @@
default
*.js
-
*.js.map
*.css
-
*.css.map
+
+
*.map
*.png
*.jpg
@@ -242,6 +242,14 @@
/robots.txt
/sitemap.xml
+
+
+
+ *.jsp
+ utf-8
+ true
+
+
60
diff --git a/gemma-web/src/main/webapp/common/analytics.jsp b/gemma-web/src/main/webapp/common/analytics.jsp
index 1f5ea9b965..a3eb6c6773 100644
--- a/gemma-web/src/main/webapp/common/analytics.jsp
+++ b/gemma-web/src/main/webapp/common/analytics.jsp
@@ -1,4 +1,5 @@
<%@ include file="/common/taglibs.jsp" %>
+
diff --git a/gemma-web/src/main/webapp/common/dwr.jsp b/gemma-web/src/main/webapp/common/dwr.jsp
new file mode 100644
index 0000000000..758c1a9b64
--- /dev/null
+++ b/gemma-web/src/main/webapp/common/dwr.jsp
@@ -0,0 +1,15 @@
+
+
+<%-- for dwr creation of javascript objects to mirror java value objects; including one of these causes all the objects to be exposed.--%>
+
+<%-- We should use this as soon as we figure out how to set generateDtoClasses option to dtoall
+ script type="text/javascript" src="/Gemma/dwr/dtoall.js"> --%>
+<%-- log javascript errors --%>
+
\ No newline at end of file
diff --git a/gemma-web/src/main/webapp/common/exception.jsp b/gemma-web/src/main/webapp/common/exception.jsp
index 6e5ebf8f48..e275484508 100644
--- a/gemma-web/src/main/webapp/common/exception.jsp
+++ b/gemma-web/src/main/webapp/common/exception.jsp
@@ -1,26 +1,19 @@
-<%@ include file="/common/taglibs.jsp"%>
+<%@ include file="/common/taglibs.jsp" %>
-
-
-
-
+
-
-
-
- <%-- this is causing stackoverflow errors ... no idea why, since upgrading to spring 3.2 from 3.0.7 --%>
-
-
+ <%-- this is causing stackoverflow errors ... no idea why, since upgrading to spring 3.2 from 3.0.7 --%>
+
-
-
+
+
${fn:escapeXml(requestScope['javax.servlet.error.message'])}" />
+
-
\ No newline at end of file
diff --git a/gemma-web/src/main/webapp/common/header.inner.jsp b/gemma-web/src/main/webapp/common/header.inner.jsp
index 76de312d71..1d904ed851 100644
--- a/gemma-web/src/main/webapp/common/header.inner.jsp
+++ b/gemma-web/src/main/webapp/common/header.inner.jsp
@@ -1,6 +1,6 @@
<%@ include file="/common/taglibs.jsp"%>
-
+
in English
diff --git a/gemma-web/src/main/webapp/common/meta.jsp b/gemma-web/src/main/webapp/common/meta.jsp
deleted file mode 100644
index 7590c3c945..0000000000
--- a/gemma-web/src/main/webapp/common/meta.jsp
+++ /dev/null
@@ -1,41 +0,0 @@
-<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
-<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
"/>
-
-
-
diff --git a/gemma-web/src/main/webapp/common/taglibs.jsp b/gemma-web/src/main/webapp/common/taglibs.jsp
index e8e69e6a16..1059eeeb2a 100644
--- a/gemma-web/src/main/webapp/common/taglibs.jsp
+++ b/gemma-web/src/main/webapp/common/taglibs.jsp
@@ -1,5 +1,3 @@
-<%@ page language="java" errorPage="/pages/error/500.jsp" pageEncoding="UTF-8"
- contentType="text/html; charset=utf-8"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
<%@ taglib uri="http://www.springframework.org/security/tags" prefix="security"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
diff --git a/gemma-web/src/main/webapp/common/userStatusVariables.jsp b/gemma-web/src/main/webapp/common/userStatusVariables.jsp
index 29ab29fdaf..a8895ad415 100644
--- a/gemma-web/src/main/webapp/common/userStatusVariables.jsp
+++ b/gemma-web/src/main/webapp/common/userStatusVariables.jsp
@@ -1,35 +1,38 @@
-<%@ include file="/common/taglibs.jsp"%>
-
+<%@ include file="/common/taglibs.jsp" %>
+
<%-- Security fields used in Java script calls to hide or display information on pages, used to be in footer --%>
-
+
-
+
-
+
-
+
-
+
-
+
- " />
+ " />
-
+
<%-- dump some other useful settings --%>
-
-
-
+
+
+
diff --git a/gemma-web/src/main/webapp/decorators/default.jsp b/gemma-web/src/main/webapp/decorators/default.jsp
index d4432bdd95..bce14da43f 100644
--- a/gemma-web/src/main/webapp/decorators/default.jsp
+++ b/gemma-web/src/main/webapp/decorators/default.jsp
@@ -1,77 +1,43 @@
+<%@ include file="/common/taglibs.jsp" %>
+
-<%-- Include common set of tag library declarations for each layout --%>
-<%@ include file="/common/taglibs.jsp"%>
-
+
-<%-- Include common set of meta tags for each layout --%>
-<%@ include file="/common/meta.jsp"%>
-
-
+
+
|
-
+
+
" />
+
" />
+
-
-
-
-
-
-
-<%-- for dwr creation of javascript objects to mirror java value objects; including one of these causes all the objects to be exposed.--%>
-
-<%-- We should use this as soon as we figure out how to set generateDtoClasses option to dtoall
- script type='text/javascript' src='/Gemma/dwr/dtoall.js'> --%>
-
+
<%-- for registration, possible from any page--%>
-
-<%-- log javascript errors --%>
-
-
+
+
+
+
-
-
-
- >
-
-
-
-
-
-
-
-
-
-
-
- <%@ include file="/common/messages.jsp"%>
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+ <%@ include file="/common/messages.jsp" %>
+
+
+
+
-
-
+
\ No newline at end of file
diff --git a/gemma-web/src/main/webapp/error.jsp b/gemma-web/src/main/webapp/error.jsp
index 66705e1df2..0fe166a1d9 100644
--- a/gemma-web/src/main/webapp/error.jsp
+++ b/gemma-web/src/main/webapp/error.jsp
@@ -1,12 +1,12 @@
+<%@ page isErrorPage="true" %>
+
<%@ include file="/common/taglibs.jsp" %>
-
-
-<%@ page isErrorPage="true" %>
+--%>
@@ -38,7 +38,8 @@ If you can, avoid producing error this way and prefer raising an exception that
Unsupported Status Code
- There is no error page configured for the status code .
+ There is no error page configured for the status code .
<%@ include file="/common/exception.jsp" %>
diff --git a/gemma-web/src/main/webapp/pages/admin/activeUsers.jsp b/gemma-web/src/main/webapp/pages/admin/activeUsers.jsp
index 0b89e68687..d932eb7e32 100644
--- a/gemma-web/src/main/webapp/pages/admin/activeUsers.jsp
+++ b/gemma-web/src/main/webapp/pages/admin/activeUsers.jsp
@@ -1,44 +1,41 @@
-<%@ include file="/common/taglibs.jsp"%>
+<%@ include file="/common/taglibs.jsp" %>
+
-
-
-
-
-
Tasks
-
+
Tasks
+
-
+
-
-
-
-
+
+
+
+
:
Signed in: ?
-
-
-
- FIXME table of authenticated users should go here.
-
- System Stats
-
+
+
+
+ FIXME table of authenticated users should go here.
+
+ System Stats
+
Gemma version ${appConfig["gemma.version"] != null ? appConfig["gemma.version"] : "?"}
built
@@ -48,11 +45,11 @@
from ${appConfig["gemma.build.gitHash"]}
+ target="_blank" rel="noopener noreferrer">${appConfig["gemma.build.gitHash"]}
-
+
-
+
\ No newline at end of file
diff --git a/gemma-web/src/main/webapp/pages/admin/geoRecordBrowser.jsp b/gemma-web/src/main/webapp/pages/admin/geoRecordBrowser.jsp
index 472b625973..dfcf62130c 100644
--- a/gemma-web/src/main/webapp/pages/admin/geoRecordBrowser.jsp
+++ b/gemma-web/src/main/webapp/pages/admin/geoRecordBrowser.jsp
@@ -1,61 +1,56 @@
-<%@ include file="/common/taglibs.jsp"%>
+<%@ include file="/common/taglibs.jsp" %>
GEO Record browser
-
-
+
+
+
+
+
+
+
+
+ Displaying GEO records.
+
+
+
+
+
+
+
+
+ Note: Records are not shown for taxa not in the Gemma system. If you
+ choose to load an experiment, please be careful: experiments that
+ have two (or more) array designs should be loaded using the regular
+ load form if you need to suppress the sample-matching functions.
+ Click on a row to display more information about the dataset, if available
+ from GEO, including information about platforms. This information is
+ often not available for a day or two after the data sets becomes
+ publicly available.
+
+
+ To search GEO, type your query in the 'Search' field, e.g. Mus+musculus[ORGN]+AND+brain[ALL] .
+ For more information on how to construct queries, go to the
+ NCBI website .
+
+
+
-
-
-
-
-
-
-
-
-
-
- Displaying GEO records.
-
-
-
-
-
-
-
-
- Note: Records are not shown for taxa not in the Gemma system. If you
- choose to load an experiment, please be careful: experiments that
- have two (or more) array designs should be loaded using the regular
- load form if you need to suppress the sample-matching functions.
- Click on a row to display more information about the dataset, if available
- from GEO, including information about platforms. This information is
- often not available for a day or two after the data sets becomes
- publicly available.
-
-
- To search GEO, type your query in the 'Search' field, e.g. Mus+musculus[ORGN]+AND+brain[ALL] .
- For more information on how to construct queries, go to the
- NCBI website .
-
-
-
-
\ No newline at end of file
diff --git a/gemma-web/src/main/webapp/pages/admin/indexer.jsp b/gemma-web/src/main/webapp/pages/admin/indexer.jsp
index 14b49246b4..22b6f21aa7 100644
--- a/gemma-web/src/main/webapp/pages/admin/indexer.jsp
+++ b/gemma-web/src/main/webapp/pages/admin/indexer.jsp
@@ -1,31 +1,25 @@
-<%@ include file="/common/taglibs.jsp"%>
+<%@ include file="/common/taglibs.jsp" %>
-
Index Gemma
-
-
-
-
+
Manage Search Indexes
+
-
-
-
-
-
- Choose the indexing options that are appropriate and then click
- index.
-
-
-
-
-
-
-
-
-
-
+
+
Manage Search Indexes
+
+
+ Choose the indexing options that are appropriate and then click
+ index.
+
+
+
+
+
+
+
+
diff --git a/gemma-web/src/main/webapp/pages/admin/loadExpressionExperimentForm.jsp b/gemma-web/src/main/webapp/pages/admin/loadExpressionExperimentForm.jsp
index c53d71e14b..b1fd679b37 100644
--- a/gemma-web/src/main/webapp/pages/admin/loadExpressionExperimentForm.jsp
+++ b/gemma-web/src/main/webapp/pages/admin/loadExpressionExperimentForm.jsp
@@ -1,181 +1,177 @@
-<%@ include file="/common/taglibs.jsp"%>
+<%@ include file="/common/taglibs.jsp" %>
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
+
+
+
-
+
+
+
diff --git a/gemma-web/src/main/webapp/pages/admin/maintenanceMode.jsp b/gemma-web/src/main/webapp/pages/admin/maintenanceMode.jsp
index 312b8be282..0704885602 100644
--- a/gemma-web/src/main/webapp/pages/admin/maintenanceMode.jsp
+++ b/gemma-web/src/main/webapp/pages/admin/maintenanceMode.jsp
@@ -1,13 +1,19 @@
-<%@ include file="/common/taglibs.jsp"%>
+<%@ include file="/common/taglibs.jsp" %>
-
- Maintenance mode simply puts a notice on every page that things might
- be broken.
-
-
\ No newline at end of file
+
+
+ Maintenance mode simply puts a notice on every page that things might
+ be broken.
+
+
+
\ No newline at end of file
diff --git a/gemma-web/src/main/webapp/pages/admin/reIndexOntologies.jsp b/gemma-web/src/main/webapp/pages/admin/reIndexOntologies.jsp
index 5962a8d1e0..a9c928e533 100755
--- a/gemma-web/src/main/webapp/pages/admin/reIndexOntologies.jsp
+++ b/gemma-web/src/main/webapp/pages/admin/reIndexOntologies.jsp
@@ -2,10 +2,7 @@
Index Gemma
-
-
-
diff --git a/gemma-web/src/main/webapp/pages/admin/systemStats.jsp b/gemma-web/src/main/webapp/pages/admin/systemStats.jsp
index 8c61429684..3782ba9f5c 100644
--- a/gemma-web/src/main/webapp/pages/admin/systemStats.jsp
+++ b/gemma-web/src/main/webapp/pages/admin/systemStats.jsp
@@ -1,7 +1,6 @@
<%@ include file="/common/taglibs.jsp"%>
-
System stats
-
+
System Stats
+
+
EE Page
+
-
EE Page
-
+
ComboBoxes
+
DatasetGroup combo
+
-
ComboBoxes
-
DatasetGroup combo
-
+
DatasetGroupComboPanel
+
+
TaxonCombo
+
-
DatasetGroupComboPanel
-
-
TaxonCombo
-
+
FactorValueCombo
+
-
FactorValueCombo
-
+
Dataset search field
+
+
-
Dataset search field
-
-
+
CharacteristicCombo
+
+
Gene combo
+
-
CharacteristicCombo
-
+
Gene Group Combo
+
-
Gene combo
-
-
Gene Group Combo
-
+
MGEDCombo
+
+
ArrayDesignCombo
+
+
Panels
-
ArrayDesignCombo
-
+
GeneChooserPanel
+
-
Panels
-
GeneChooserPanel
-
+
DatasetGroupGridPanel with DatasetGroupEditToolbar
+
+
ExpressionExperiment Grid
+
+
AuditTrailGrid
+
-
DatasetGroupGridPanel with DatasetGroupEditToolbar
-
-
ExpressionExperiment Grid
-
+
FilesUpload
+
+
Visualization
+
-
AuditTrailGrid
-
+
ProgressWidget
+
-
FilesUpload
-
+
AnalysisResultsSearch
+
+
+
+
-
Visualization
-
+
Widget
+
-
ProgressWidget
-
+
Font-awesome test
+
+ fa-camera-retro
+
+
+
diff --git a/gemma-web/src/main/webapp/pages/analysesResultsSearch.jsp b/gemma-web/src/main/webapp/pages/analysesResultsSearch.jsp
index 1a810bc9c5..ace50307af 100755
--- a/gemma-web/src/main/webapp/pages/analysesResultsSearch.jsp
+++ b/gemma-web/src/main/webapp/pages/analysesResultsSearch.jsp
@@ -1,34 +1,23 @@
+<%@ include file="/common/taglibs.jsp" %>
-
-
-
Search Analyses Results
-
-
-
-
-
-
+
+
Search Analyses Results
+
+
+
-
-
+
-
-
-
+Ext.onReady( function() {
+ Ext.QuickTips.init();
-
-
+ new Gemma.GemmaViewPort( {
+ centerPanelConfig : new Gemma.AnalysisResultsSearch()
+ } );
+} );
+
diff --git a/gemma-web/src/main/webapp/pages/arrayDesign.detail.jsp b/gemma-web/src/main/webapp/pages/arrayDesign.detail.jsp
index 17c80a31dc..8dfc0a0132 100644
--- a/gemma-web/src/main/webapp/pages/arrayDesign.detail.jsp
+++ b/gemma-web/src/main/webapp/pages/arrayDesign.detail.jsp
@@ -1,32 +1,27 @@
-<%@ include file="/common/taglibs.jsp"%>
-
+<%@ include file="/common/taglibs.jsp" %>
-
+
${fn:escapeXml(arrayDesign.shortName)} - ${fn:escapeXml(arrayDesign.name)}
+
+
+
+
+
+
-
-
${arrayDesignShortName} - ${arrayDesignName }
-
-
-
-
-
-
-
-
diff --git a/gemma-web/src/main/webapp/pages/arrayDesign.edit.jsp b/gemma-web/src/main/webapp/pages/arrayDesign.edit.jsp
index b3b92f5341..fed57c8c02 100644
--- a/gemma-web/src/main/webapp/pages/arrayDesign.edit.jsp
+++ b/gemma-web/src/main/webapp/pages/arrayDesign.edit.jsp
@@ -1,6 +1,8 @@
-<%@ include file="/common/taglibs.jsp"%>
+<%@ include file="/common/taglibs.jsp" %>
-
Edit Array Design ${arrayDesign.name}
+
+
Edit ${fn:escapeXml(arrayDesign.name)}
+
@@ -16,70 +18,73 @@
" id="arrayDesignForm"
- onsubmit="return validateArrayDesign(this)">
+ onsubmit="return validateArrayDesign(this)">
-
diff --git a/gemma-web/src/main/webapp/pages/arrayDesign.jsp b/gemma-web/src/main/webapp/pages/arrayDesign.jsp
deleted file mode 100644
index c6c14e0968..0000000000
--- a/gemma-web/src/main/webapp/pages/arrayDesign.jsp
+++ /dev/null
@@ -1,14 +0,0 @@
-<%@ include file="/common/taglibs.jsp"%>
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/gemma-web/src/main/webapp/pages/arrayDesigns.jsp b/gemma-web/src/main/webapp/pages/arrayDesigns.jsp
index 6c400b92b9..78fb8ed733 100644
--- a/gemma-web/src/main/webapp/pages/arrayDesigns.jsp
+++ b/gemma-web/src/main/webapp/pages/arrayDesigns.jsp
@@ -1,23 +1,16 @@
-
-<%@ include file="/common/taglibs.jsp"%>
-
+
Platforms
+
+
-
-
-
-
Platforms
-
diff --git a/gemma-web/src/main/webapp/pages/bibRefAdd.jsp b/gemma-web/src/main/webapp/pages/bibRefAdd.jsp
new file mode 100644
index 0000000000..90c0c07d02
--- /dev/null
+++ b/gemma-web/src/main/webapp/pages/bibRefAdd.jsp
@@ -0,0 +1,22 @@
+<%@ include file="/common/taglibs.jsp" %>
+
+
+
Import ${fn:escapeXml(bibliographicReference.pubAccession.accession)}
+ from ${fn:escapeXml(bibliographicReference.pubAccession.externalDatabase.name)}
+
+
+
+
+
Import ${fn:escapeXml(bibliographicReference.pubAccession.accession)}
+ from ${fn:escapeXml(bibliographicReference.pubAccession.externalDatabase.name)}
+
+ This reference was obtained from PubMed; it is not in the Gemma system.
+
+
+ ">
+
+
+
+
+
diff --git a/gemma-web/src/main/webapp/pages/bibRefList.jsp b/gemma-web/src/main/webapp/pages/bibRefList.jsp
index dc48534389..d4e066aa2a 100644
--- a/gemma-web/src/main/webapp/pages/bibRefList.jsp
+++ b/gemma-web/src/main/webapp/pages/bibRefList.jsp
@@ -1,15 +1,14 @@
-<%@ include file="/common/taglibs.jsp"%>
+<%@ include file="/common/taglibs.jsp" %>
-
+
Bibliographic References
+
-
Bibliographic References
-
diff --git a/gemma-web/src/main/webapp/pages/bibRefView.jsp b/gemma-web/src/main/webapp/pages/bibRefView.jsp
index 4ca6da852f..bbf108b94d 100644
--- a/gemma-web/src/main/webapp/pages/bibRefView.jsp
+++ b/gemma-web/src/main/webapp/pages/bibRefView.jsp
@@ -1,54 +1,25 @@
-<%@ include file="/common/taglibs.jsp"%>
-
+<%@ include file="/common/taglibs.jsp" %>
<%-- Shows the results of a search for pubmed references. --%>
-
-
-
Bibliographic Reference
-
-
-
Bibliographic Reference record
-
-
-
-
-
- This reference was obtained from PubMed; it is not in the Gemma
- system. You can add it to Gemma by clicking the button on the bottom
- of the page, or do a ">new search.
-
-
-
-
- The entry is incomplete. You can attempt to complete it from
- pubmed by clicking the 'add' button below.
-
- ">
-
-
-
-
-
-
-
+
+
${fn:escapeXml(bibliographicReference.pubAccession.accession)}
+ from ${fn:escapeXml(bibliographicReference.pubAccession.externalDatabase.name)}
+
+
+Ext.namespace( 'Gemma' );
+Ext.onReady( function() {
+ Ext.QuickTips.init();
+ var detailPanel = new Gemma.BibliographicReference.DetailsPanel( {
+ //loadBibRefId : ${bibliographicReference.id}
+ //height: 400,
+ //width: 400,
+ renderTo : 'detailPanel'
+ } );
+
+ detailPanel.loadFromId( ${bibliographicReference.id} );
+} );
+
\ No newline at end of file
diff --git a/gemma-web/src/main/webapp/pages/bioAssay.detail.jsp b/gemma-web/src/main/webapp/pages/bioAssay.detail.jsp
index c00b37e60f..9d068711ce 100644
--- a/gemma-web/src/main/webapp/pages/bioAssay.detail.jsp
+++ b/gemma-web/src/main/webapp/pages/bioAssay.detail.jsp
@@ -1,45 +1,148 @@
-<%@ include file="/common/taglibs.jsp"%>
-
-
-
-
-
-
-
-
+<%@ include file="/common/taglibs.jsp" %>
+
+
${fn:escapeXml(bioAssay.name)}
+
+
+
+
+
+
+
+
+
+
+
+
${fn:escapeXml(bioAssay.name)}
+
+
+ :
+
+
+
+
+
+
+ (inherited)
+
+
+ No external identifier available
+
+
+
+
+
+
+ :
+
+
+
+ ${fn:escapeXml(bioAssay.description)}
+
+
+ ${fn:escapeXml(singleParent.description)} (inherited)
+
+ No description available
+
+
+
+
+
+
+ Experiments used in:
+
+
+
+ ${fn:escapeXml(bioAssaySet.name)}
+
+
+
+
+
+
+
+ Sample:
+
+
+ ${fn:escapeXml(bioAssay.sampleUsed.name)}
+
+
+
+
+ Platform:
+
+
+ ${fn:escapeXml(bioAssay.arrayDesignUsed.shortName)}
+
+
+
+
+
+
+
+ Original Platform:
+
+ ${bioAssay.originalPlatform.shortName}
+ ${fn:escapeXml(bioAssay.originalPlatform.name)}
+
+
+
+
+
+ Original Platform:
+
+ ${singleParent.originalPlatform.shortName}
+ ${fn:escapeXml(singleParent.originalPlatform.name)} (inherited)
+
+
+
+
+
+
+
+
+
+
+
+ Hierarchy for ${fn:escapeXml(dimension.name)}
+
+ <%-- Having more than one parent would be very unusual, but the data model allows it --%>
+ ${parents.size() > 1 ? 'Parents' : 'Parent'}:
+
+
+
+ Siblings:
+
+
+
+ Children:
+
+
+
+
\ No newline at end of file
diff --git a/gemma-web/src/main/webapp/pages/bioAssays.jsp b/gemma-web/src/main/webapp/pages/bioAssays.jsp
deleted file mode 100644
index bceb3a40c5..0000000000
--- a/gemma-web/src/main/webapp/pages/bioAssays.jsp
+++ /dev/null
@@ -1,57 +0,0 @@
-<%@ include file="/common/taglibs.jsp" %>
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/gemma-web/src/main/webapp/pages/bioMaterial.detail.jsp b/gemma-web/src/main/webapp/pages/bioMaterial.detail.jsp
index 0979a0e43d..8c46d8fea4 100644
--- a/gemma-web/src/main/webapp/pages/bioMaterial.detail.jsp
+++ b/gemma-web/src/main/webapp/pages/bioMaterial.detail.jsp
@@ -1,152 +1,208 @@
-<%@ include file="/common/taglibs.jsp"%>
-
+<%@ include file="/common/taglibs.jsp" %>
-
-
+
${fn:escapeXml(bioMaterial.name)}
+
+
+
+
+
+
+
+ Description not available
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Description not available
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Taxon not available
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- No external identifier
-
-
-
-
-
-
- Assays used in
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Annotations
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
${fn:escapeXml(bioMaterial.name)}
+
+
+
+
+ :
+
+
+
+
+
+
+ (inherited)
+
+ Description not available
+
+
+
+
+
+ :
+
+
+
+ ${bioMaterial.sourceTaxon.scientificName}
+
+ Taxon not available
+
+
+
+
+
+ :
+
+
+
+
+
+
+
+ (inherited)
+
+ No external identifier available
+
+
+
+
+
+ Assays used in:
+
+
+
+
+
+
+ Experiments used in
+
+
+
+ ${ba2bm.value.shortName}
+
+ (via ${e.key.name} →
+ ${ba2bm.key.name} )
+
+
+
+
+
+
+
+
+
+
+
+
+ Hierarchy for ${fn:escapeXml(dimension.name)}
+
+
+
+ Parent:
+ ${parent.name}
+
+
+
+ Siblings:
+
+
+
+ Children:
+
+
+
+
+
+
+
+
+
+
+
+
+ Name
+ Description
+ Order Applied
+
+
+
+
+ ${fn:escapeXml(treatment.name)}
+ ${fn:escapeXml(treatment.description)}
+ ${treatment.orderApplied}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Annotations
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gemma-web/src/main/webapp/pages/characteristics.jsp b/gemma-web/src/main/webapp/pages/characteristics.jsp
index c0494148c9..f635376e00 100644
--- a/gemma-web/src/main/webapp/pages/characteristics.jsp
+++ b/gemma-web/src/main/webapp/pages/characteristics.jsp
@@ -1,19 +1,13 @@
-<%@ include file="/common/taglibs.jsp"%>
+<%@ include file="/common/taglibs.jsp" %>
-
-
-
-
-
+
+
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/gemma-web/src/main/webapp/pages/compositeSequence.detail.jsp b/gemma-web/src/main/webapp/pages/compositeSequence.detail.jsp
index 771974cfd2..68b5f26b69 100644
--- a/gemma-web/src/main/webapp/pages/compositeSequence.detail.jsp
+++ b/gemma-web/src/main/webapp/pages/compositeSequence.detail.jsp
@@ -1,93 +1,60 @@
-<%@ include file="/common/taglibs.jsp" %>
-
-
- ${ compositeSequence.name}
-
- <%-- deprecated. We should replace this with something tidier --%>
-
-
-
-
- :
-
-
+ :
+ title="Description for the probe, usually provided by the manufacturer. It might not match the sequence annotation!">
- ${compositeSequence.description}
- No description available
+
+ ${fn:escapeXml(compositeSequence.description)}
+
+ No description available
-
- Taxon :
-
+ Taxon:
-
+
${compositeSequence.biologicalCharacteristic.taxon.commonName}
- [Taxon missing]
+ No taxon available
-
- Sequence Type :
-
+ Sequence type:
+ title="The type of this sequence as recorded in our system">
@@ -101,91 +68,86 @@
- [Not available]
+ No sequence type available
-
- Sequence name :
-
+ Sequence name:
+ title='Name of the sequence in our system.'>
- ${ compositeSequence.biologicalCharacteristic.name}
- No name available
+
+ ${fn:escapeXml(compositeSequence.biologicalCharacteristic.name)}
+
+
+ No sequence name available
+
-
- Sequence description :
-
+ Sequence description:
+ title='Description of the sequence in our system.'>
-
- ${ compositeSequence.biologicalCharacteristic.description}
+
+ ${fn:escapeXml(compositeSequence.biologicalCharacteristic.description)}
- No description available
+
+ No sequence description available
+
-
- Sequence accession :
-
+ Sequence accession:
+ title='External accession for this sequence, if known'>
- ${ compositeSequence.biologicalCharacteristic.sequenceDatabaseEntry.accession}
- No accession
+ ${compositeSequence.biologicalCharacteristic.sequenceDatabaseEntry.accession}
+
+ No accession available
-
- Sequence :
-
+ Sequence:
+ title='Sequence, if known'>
-
- No sequence
+
+ No sequence available
-
- Sequence length :
-
+ Sequence length:
-
+
${fn:length(compositeSequence.biologicalCharacteristic.sequence)}
- No sequence available
+ No sequence available
@@ -196,6 +158,30 @@
Alignment information
-
-
+
+<%-- deprecated. We should replace this with something tidier --%>
+
diff --git a/gemma-web/src/main/webapp/pages/contactUs.jsp b/gemma-web/src/main/webapp/pages/contactUs.jsp
index 5b490387c9..5602d05c00 100644
--- a/gemma-web/src/main/webapp/pages/contactUs.jsp
+++ b/gemma-web/src/main/webapp/pages/contactUs.jsp
@@ -1,33 +1,26 @@
-
-<%-- Decorator for the home page --%>
-
-
-<%-- Include common set of tag library declarations for each layout --%>
-<%@ include file="/common/taglibs.jsp"%>
-
+<%@ include file="/common/taglibs.jsp" %>
+
Contact Us
-
-
\ No newline at end of file
diff --git a/gemma-web/src/main/webapp/pages/dataUpload.jsp b/gemma-web/src/main/webapp/pages/dataUpload.jsp
index 46d0278695..7764a29c7d 100644
--- a/gemma-web/src/main/webapp/pages/dataUpload.jsp
+++ b/gemma-web/src/main/webapp/pages/dataUpload.jsp
@@ -1,32 +1,34 @@
-<%@ include file="/common/taglibs.jsp"%>
+<%@ include file="/common/taglibs.jsp" %>
+Upload Expression Data
+
- Expression data upload
-
-
-
-
-
-
+
+
+
-
-
-
-
-
+
+
Upload Expression Data
+
+
+
+
+
+
-
-
-
- Sorry, to upload data you must
- login or
- register .
-
-
+
+
+
+ Sorry, to upload data you must
+ login or
+ register .
+
+
+
diff --git a/gemma-web/src/main/webapp/pages/error/403.jsp b/gemma-web/src/main/webapp/pages/error/403.jsp
index 303c221631..0a783e0b4b 100644
--- a/gemma-web/src/main/webapp/pages/error/403.jsp
+++ b/gemma-web/src/main/webapp/pages/error/403.jsp
@@ -1,26 +1,24 @@
<%@ include file="/common/taglibs.jsp" %>
-
+
-
-
-
+
-
+
-
+
diff --git a/gemma-web/src/main/webapp/pages/error/404.jsp b/gemma-web/src/main/webapp/pages/error/404.jsp
index 3101a1311b..88282178cc 100644
--- a/gemma-web/src/main/webapp/pages/error/404.jsp
+++ b/gemma-web/src/main/webapp/pages/error/404.jsp
@@ -1,13 +1,11 @@
<%@ include file="/common/taglibs.jsp" %>
-
+
-
-
-
+
-
+
diff --git a/gemma-web/src/main/webapp/pages/experimentalDesign.detail.jsp b/gemma-web/src/main/webapp/pages/experimentalDesign.detail.jsp
index 3ba5e16f0d..4774844788 100644
--- a/gemma-web/src/main/webapp/pages/experimentalDesign.detail.jsp
+++ b/gemma-web/src/main/webapp/pages/experimentalDesign.detail.jsp
@@ -1,175 +1,176 @@
-<%@ include file="/common/taglibs.jsp"%>
+<%@ include file="/common/taglibs.jsp" %>
+ class="ubic.gemma.model.expression.experiment.ExperimentalDesign" />
+ class="ubic.gemma.model.expression.experiment.ExpressionExperiment" />
${expressionExperiment.shortName} |
-
-
-
+ value="${expressionExperiment.id}" />
+ value="${experimentalDesign.id}" />
+ value="${currentUserCanEdit}" />
-
-
- for
-
-
-
-
-
-
- This experiment does not have any experimental
- design details filled in.
-
-
-
- Download design File:
- Click
- to start download
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- (Name not available)
-
-
-
-
-
-
-
-
-
-
-
-
-
- (Description not available)
-
-
-
-
-
-
-
-
-
-
-
-
-
- (Database entry not available)
-
-
-
-
-
-
-
-
-
-
-
-
-
- (Primary publication not available)
-
-
-
-
-
+
+
+ for
+
+
+
+
+
+
+
+ This experiment does not have any experimental
+ design details filled in.
+
+
+
+ Download design File:
+ Click
+ to start download
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (Name not available)
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (Description not available)
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (Database entry not available)
+
+
+
+
+
+
+
+
+
+
+
+
+
+ (Primary publication not available)
+
+
+
+
+
-
-
-
-
- Use the form below to populate the experimental design details.
- Alternatively you can
- upload
- a design description file. Instructions are
- here
- . If you want to use the upload method, you can get a blank
- template
- file
- to get started.
-
-
-
-
-
-
-
- This experimental design needs attention, check in the tables below for more details.
-
-
-
- Here's another experimental design that needs attention:
- ${randomExperimentalDesignThatNeedsAttentionShortName}
-
-
-
-
-
-
- <%-- This form element is needed for the checkboxes in the factor value panel --%>
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+
+ Use the form below to populate the experimental design details.
+ Alternatively you can
+ upload
+ a design description file. Instructions are
+ here
+ . If you want to use the upload method, you can get a blank
+ template
+ file
+ to get started.
+
+
+
+
+
+
+
+ This experimental design needs attention, check in the tables below for more details.
+
+
+
+ Here's another experimental design that needs attention:
+ ${randomExperimentalDesignThatNeedsAttentionShortName}
+
+
+
+
+
+
+ <%-- This form element is needed for the checkboxes in the factor value panel --%>
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/gemma-web/src/main/webapp/pages/expressionExperiment.bioAssays.jsp b/gemma-web/src/main/webapp/pages/expressionExperiment.bioAssays.jsp
new file mode 100644
index 0000000000..c1746f9e88
--- /dev/null
+++ b/gemma-web/src/main/webapp/pages/expressionExperiment.bioAssays.jsp
@@ -0,0 +1,55 @@
+<%@ include file="/common/taglibs.jsp" %>
+
+
+
for ${expressionExperiment.shortName}
+
+
+
+
+
+
+
diff --git a/gemma-web/src/main/webapp/pages/expressionExperiment.bioMaterials.jsp b/gemma-web/src/main/webapp/pages/expressionExperiment.bioMaterials.jsp
new file mode 100644
index 0000000000..d78d45b32e
--- /dev/null
+++ b/gemma-web/src/main/webapp/pages/expressionExperiment.bioMaterials.jsp
@@ -0,0 +1,46 @@
+<%@ include file="/common/taglibs.jsp" %>
+
+
+
Biomaterials for ${fn:escapeXml(expressionExperiment.shortName)}
+
+
+
+
+
+
+ Biomaterials for
+ ${fn:escapeXml(expressionExperiment.shortName)}
+
+
${fn:escapeXml(expressionExperiment.name)}
+
+
+
+ View the experimental design
+
+
+
+
+
+ Name
+ Description
+
+
+
+
+ ${bioMaterial.name}
+
+
+
+
+ ${fn:escapeXml(bioMaterial.description)}
+
+
+ No description available
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/gemma-web/src/main/webapp/pages/expressionExperiment.detail.jsp b/gemma-web/src/main/webapp/pages/expressionExperiment.detail.jsp
index b60869cd18..eda291de97 100644
--- a/gemma-web/src/main/webapp/pages/expressionExperiment.detail.jsp
+++ b/gemma-web/src/main/webapp/pages/expressionExperiment.detail.jsp
@@ -1,36 +1,38 @@
-<%@ include file="/common/taglibs.jsp"%>
+<%@ include file="/common/taglibs.jsp" %>
-
${expressionExperiment.shortName} Details
-
+
${fn:escapeXml(expressionExperiment.shortName)} - ${fn:escapeXml(expressionExperiment.name)}
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/gemma-web/src/main/webapp/pages/expressionExperiment.edit.jsp b/gemma-web/src/main/webapp/pages/expressionExperiment.edit.jsp
index f2ec4313da..386df65e09 100644
--- a/gemma-web/src/main/webapp/pages/expressionExperiment.edit.jsp
+++ b/gemma-web/src/main/webapp/pages/expressionExperiment.edit.jsp
@@ -1,24 +1,26 @@
<%@ include file="/common/taglibs.jsp" %>
+
+
+
-
-
+
Edit ${expressionExperiment.shortName}
+
-
-
-
+
+
-
${expressionExperiment.shortName}
+
${expressionExperiment.shortName}
">
@@ -50,50 +52,50 @@
+ step="1">
"
- value=" "/>
+ value=" " />
"
- value=" "/>
+ value=" " />
checked="checked" />
+ checked="checked" />
">
checked="checked" />
+ checked="checked" />
">
checked="checked" />
+ checked="checked" />
">
checked="checked" />
+ checked="checked" />
">
checked="checked" />
+ checked="checked" />
">
checked="checked" />
+ checked="checked" />
">
checked="checked" />
+ checked="checked" />
">
@@ -152,15 +154,15 @@
+ value="Unmatch all bioassays" />
-
+
- "/>
- "/>
+ " />
+ " />
diff --git a/gemma-web/src/main/webapp/pages/expressionExperiment.subSets.jsp b/gemma-web/src/main/webapp/pages/expressionExperiment.subSets.jsp
new file mode 100644
index 0000000000..da801eeafd
--- /dev/null
+++ b/gemma-web/src/main/webapp/pages/expressionExperiment.subSets.jsp
@@ -0,0 +1,83 @@
+<%@ include file="/common/taglibs.jsp" %>
+
+
+Subsets of ${expressionExperiment.shortName} - ${expressionExperiment.name}
+
+
+
+
+
+
+ Subsets of ${expressionExperiment.shortName}
+ - ${expressionExperiment.name}
+
+
+
+ Description:
+ ${expressionExperiment.description}
+
+
+ Accession:
+
+
+
+ Publication:
+
+
+
+
+
+
+
+
+
+
+
+ Dimension:
+ ${fn:escapeXml(e.key.name)}
+
+
+
+ Quantitation types:
+
+
+
+
+
+
+ Subsets:
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/gemma-web/src/main/webapp/pages/expressionExperimentLinkSummary.jsp b/gemma-web/src/main/webapp/pages/expressionExperimentLinkSummary.jsp
index b0586413db..3141b898c0 100644
--- a/gemma-web/src/main/webapp/pages/expressionExperimentLinkSummary.jsp
+++ b/gemma-web/src/main/webapp/pages/expressionExperimentLinkSummary.jsp
@@ -1,28 +1,24 @@
-<%@ include file="/common/taglibs.jsp"%>
+<%@ include file="/common/taglibs.jsp" %>
-
- Dataset manager
-
-
+Dataset manager
-
-
+
diff --git a/gemma-web/src/main/webapp/pages/expressionExperimentSet.detail.jsp b/gemma-web/src/main/webapp/pages/expressionExperimentSet.detail.jsp
index 98274ef77e..36da980a50 100644
--- a/gemma-web/src/main/webapp/pages/expressionExperimentSet.detail.jsp
+++ b/gemma-web/src/main/webapp/pages/expressionExperimentSet.detail.jsp
@@ -1,38 +1,37 @@
-<%@ include file="/common/taglibs.jsp"%>
+<%@ include file="/common/taglibs.jsp" %>
- ${eeSetName} Details
-
+${fn:escapeXml(eeSet.name)}
+
-
-
-
-
-
+
+
-
+
+
+
diff --git a/gemma-web/src/main/webapp/pages/expressionExperimentSetManager.jsp b/gemma-web/src/main/webapp/pages/expressionExperimentSetManager.jsp
index 6486565ebd..0c60b89bea 100644
--- a/gemma-web/src/main/webapp/pages/expressionExperimentSetManager.jsp
+++ b/gemma-web/src/main/webapp/pages/expressionExperimentSetManager.jsp
@@ -1,43 +1,40 @@
-<%@ include file="/common/taglibs.jsp"%>
+<%@ include file="/common/taglibs.jsp" %>
Dataset Group Manager
-
-
-
-
+
-
-
- Sorry, you must be logged in to use this tool.
+
+
+ Sorry, you must be logged in to use this tool.
-
-
-
-
-
+
+
+
+
+
diff --git a/gemma-web/src/main/webapp/pages/expressionExperimentSubSet.detail.jsp b/gemma-web/src/main/webapp/pages/expressionExperimentSubSet.detail.jsp
new file mode 100644
index 0000000000..d65057b915
--- /dev/null
+++ b/gemma-web/src/main/webapp/pages/expressionExperimentSubSet.detail.jsp
@@ -0,0 +1,165 @@
+<%@ include file="/common/taglibs.jsp" %>
+
+
+
+
+${subSet.name}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ${subSet.name}
+ (subset of ${subSet.sourceExperiment.shortName} ,
+ see
+ all subsets )
+
+
+
+ Annotations:
+
+
+
+ ${annotation.termName} ,
+
+
+
+
+ Description:
+
+
+
+ ${fn:escapeXml(fn:trim(subSet.description))}
+
+
+ ${fn:escapeXml(fn:trim(subSet.sourceExperiment.description))} (inherited)
+
+
+ No description available
+
+
+
+
+
+ Accession:
+
+
+
+
+
+
+ (inherited)
+
+ No accession available
+
+
+
+
+ Publication:
+
+
+
+
+
+
+ (inherited)
+
+ No publication/i>
+
+
+
+
+
+ Dimension:
+
+
+
+
+ ${fn:escapeXml(pd.name)}
+
+
+ ${fn:escapeXml(pd.name)}
+
+
+
+
+
+
+
+
+ Other subsets:
+
+
+
+
+
+
+
+
+ Assays
+
+
+
+ Name
+ Description
+
+
+
+
+
+
+ ${ba.name}
+
+
+
+
+ ${fn:escapeXml(ba.description)}
+
+ No description available
+
+
+
+
+
+
+
+
+
+ Annotations
+
+
+
+ Category
+ Value
+
+
+
+
+
+
+
+
+
+
+
+ (inherited)
+
+
+
+
+
diff --git a/gemma-web/src/main/webapp/pages/expressionExperimentsWithQC.jsp b/gemma-web/src/main/webapp/pages/expressionExperimentsWithQC.jsp
index 851201d8b4..86b335b0fa 100644
--- a/gemma-web/src/main/webapp/pages/expressionExperimentsWithQC.jsp
+++ b/gemma-web/src/main/webapp/pages/expressionExperimentsWithQC.jsp
@@ -1,31 +1,27 @@
-<%@ include file="/common/taglibs.jsp"%>
+<%@ include file="/common/taglibs.jsp" %>
Expression Experiments with QC Issues
-
-
-
-
+
+
-
+ new Gemma.GemmaViewPort( {
+ centerPanelConfig : new Gemma.ExpressionExperimentQCGrid( {
+ header : true,
+ experimentNameAsLink : true
+ } )
+ } );
-
-
-
\ No newline at end of file
+} );
+
diff --git a/gemma-web/src/main/webapp/pages/gene.detail.jsp b/gemma-web/src/main/webapp/pages/gene.detail.jsp
index c01f7a6b8a..1de543d0f8 100644
--- a/gemma-web/src/main/webapp/pages/gene.detail.jsp
+++ b/gemma-web/src/main/webapp/pages/gene.detail.jsp
@@ -1,45 +1,40 @@
-<%@ include file="/common/taglibs.jsp"%>
-
-
-
-
+<%@ include file="/common/taglibs.jsp" %>
+
-
- ${geneOfficialSymbol}
-
+
+${fn:escapeXml(gene.name)} - ${fn:escapeXml(gene.officialName)}
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
+
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/gemma-web/src/main/webapp/pages/geneGroupManager.jsp b/gemma-web/src/main/webapp/pages/geneGroupManager.jsp
index 860efc3cc7..9643bb2bc1 100644
--- a/gemma-web/src/main/webapp/pages/geneGroupManager.jsp
+++ b/gemma-web/src/main/webapp/pages/geneGroupManager.jsp
@@ -2,60 +2,52 @@
- Manage Gene Groups
-
-
+Manage Gene Groups
+
-
-
-
+
+
-
- Manage Gene Groups
-
+Manage Gene Groups
-
-
-
- Sorry, you must be logged in to use this tool.
-
-
+
+
+
+ Sorry, you must be logged in to use this tool.
+
+
-
-
-
- You can create a group of genes to be used in searches and analyses.
- This interface allows you to create gene groups, modify them, and
- control who else can see them.
-
+ } );
+
+
+ You can create a group of genes to be used in searches and analyses.
+ This interface allows you to create gene groups, modify them, and
+ control who else can see them.
+
-
-
-
-
-
-
-
+
+
+
+
diff --git a/gemma-web/src/main/webapp/pages/geneSet.detail.jsp b/gemma-web/src/main/webapp/pages/geneSet.detail.jsp
index 2033094bef..0c48cf2fce 100644
--- a/gemma-web/src/main/webapp/pages/geneSet.detail.jsp
+++ b/gemma-web/src/main/webapp/pages/geneSet.detail.jsp
@@ -1,39 +1,40 @@
-<%@ include file="/common/taglibs.jsp"%>
+<%@ include file="/common/taglibs.jsp" %>
+
- ${geneSetName} Details
-
+${fn:escapeXml(geneSet.name)} Details
+
-
-
-
-
-
+
+
-
+
+
+
+
diff --git a/gemma-web/src/main/webapp/pages/generalSearch.jsp b/gemma-web/src/main/webapp/pages/generalSearch.jsp
index 55feffbaf6..e9e7d456dd 100644
--- a/gemma-web/src/main/webapp/pages/generalSearch.jsp
+++ b/gemma-web/src/main/webapp/pages/generalSearch.jsp
@@ -1,27 +1,23 @@
-<%@ include file="/common/taglibs.jsp"%>
-
+<%@ include file="/common/taglibs.jsp" %>
-
-
-
-
-
+
-
+
+
diff --git a/gemma-web/src/main/webapp/pages/home.jsp b/gemma-web/src/main/webapp/pages/home.jsp
index d040fe14c2..c7540068ae 100755
--- a/gemma-web/src/main/webapp/pages/home.jsp
+++ b/gemma-web/src/main/webapp/pages/home.jsp
@@ -3,31 +3,9 @@
<%@ include file="/common/taglibs.jsp" %>
Home
-
-
<%-- --%>
-
-
<%-- jshowoff.css is included in the bundle --%>
@@ -152,7 +130,7 @@ $.getJSON( '${pageContext.request.contextPath}' + '/rest/v2/datasets/count', fun
Copyright © 2007-2024
@@ -161,4 +139,24 @@ $.getJSON( '${pageContext.request.contextPath}' + '/rest/v2/datasets/count', fun
src="https://i.creativecommons.org/l/by-nc/4.0/80x15.png" width="80" height="15" />
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/gemma-web/src/main/webapp/pages/invalidGeoAccession.jsp b/gemma-web/src/main/webapp/pages/invalidGeoAccession.jsp
deleted file mode 100644
index 3872bfc31b..0000000000
--- a/gemma-web/src/main/webapp/pages/invalidGeoAccession.jsp
+++ /dev/null
@@ -1,23 +0,0 @@
-<%@ include file="/common/taglibs.jsp"%>
-<%@ page language="java" isErrorPage="true"%>
-
-
-<%-- This is not being used. --%>
-
- Invalid GEO accession
-
-
-
- Invalid GEO accession
-
-
- « Back
-
-
-
-
- Either that accession does not exist in GEO, or if you entered a GDS number, Gemma could not locate a matching series
- (GSE) on the GEO web site. Please check the
- GEO web site to make sure you selected a valid accession.
-
-
diff --git a/gemma-web/src/main/webapp/pages/manageGroups.jsp b/gemma-web/src/main/webapp/pages/manageGroups.jsp
index 6d261c77c2..0107f3fcbd 100644
--- a/gemma-web/src/main/webapp/pages/manageGroups.jsp
+++ b/gemma-web/src/main/webapp/pages/manageGroups.jsp
@@ -1,38 +1,27 @@
-<%@ include file="/common/taglibs.jsp"%>
+<%@ include file="/common/taglibs.jsp" %>
- Manage groups
-
-
+Manage groups
+
-
-
-
-
- Manage groups
-
-
-
- A 'Group' is a set of Gemma users who have a common set of permissions. This page allows you to see what Groups you
- belong to, create groups, and change who is in groups you control.
-
-
-
- For additional controls on which groups can view or edit your data sets, visit the
- ">Data Manager. If
- you want to manage Gene Groups go to the
- ">Gene Group Manager. To manage Expression Dataset Groups go to
- the
- ">Dataset Group Manager.
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+Manage groups
+
+
+ A 'Group' is a set of Gemma users who have a common set of permissions. This page allows you to see what Groups you
+ belong to, create groups, and change who is in groups you control.
+
+
+
+ For additional controls on which groups can view or edit your data sets, visit the
+ ">Data Manager. If
+ you want to manage Gene Groups go to the
+ ">Gene Group Manager. To manage Expression Dataset Groups go to
+ the
+ ">Dataset Group Manager.
+
+
+
+
\ No newline at end of file
diff --git a/gemma-web/src/main/webapp/pages/metaAnalysisManager.jsp b/gemma-web/src/main/webapp/pages/metaAnalysisManager.jsp
index 2d7bbce84c..4edd9efcc7 100644
--- a/gemma-web/src/main/webapp/pages/metaAnalysisManager.jsp
+++ b/gemma-web/src/main/webapp/pages/metaAnalysisManager.jsp
@@ -1,27 +1,24 @@
-<%@ include file="/common/taglibs.jsp"%>
+<%@ include file="/common/taglibs.jsp" %>
Meta-analysis Manager
-
-
-
-
-
<%-- The function fetchDiffExpressionData(analysisId) in eeDataFetch.js requires "messages" to be defined. --%>
+
+
diff --git a/gemma-web/src/main/webapp/pages/metaheatmap.jsp b/gemma-web/src/main/webapp/pages/metaheatmap.jsp
index d3817fb302..40b03e1d4f 100644
--- a/gemma-web/src/main/webapp/pages/metaheatmap.jsp
+++ b/gemma-web/src/main/webapp/pages/metaheatmap.jsp
@@ -1,59 +1,59 @@
-<%@ include file="/common/taglibs.jsp"%>
+<%@ include file="/common/taglibs.jsp" %>
-
-
-
-
-
-
+Meta-analysis Heatmap
+
+
-Start a new search
-
\ No newline at end of file
+
+Start a new search
+
+
+
diff --git a/gemma-web/src/main/webapp/pages/passwordHint.jsp b/gemma-web/src/main/webapp/pages/passwordHint.jsp
index ddfe96732a..11b407696e 100644
--- a/gemma-web/src/main/webapp/pages/passwordHint.jsp
+++ b/gemma-web/src/main/webapp/pages/passwordHint.jsp
@@ -1,16 +1,8 @@
-<%--
-author: keshav
-
---%>
-
-<%@ include file="/common/taglibs.jsp"%>
-
+<%-- author: keshav --%>
+<%@ include file="/common/taglibs.jsp" %>
Password reset
-
-
+
-
-
diff --git a/gemma-web/src/main/webapp/pages/personForm.jsp b/gemma-web/src/main/webapp/pages/personForm.jsp
index bd43291bfe..83f9039c28 100644
--- a/gemma-web/src/main/webapp/pages/personForm.jsp
+++ b/gemma-web/src/main/webapp/pages/personForm.jsp
@@ -1,98 +1,101 @@
-<%@ include file="/common/taglibs.jsp"%>
-
-
-
-
-
-
-
+<%@ include file="/common/taglibs.jsp" %>
+
+
+
+
+
">
diff --git a/gemma-web/src/main/webapp/pages/processProgress.jsp b/gemma-web/src/main/webapp/pages/processProgress.jsp
index dc4003a3b1..54f0c0b7a8 100644
--- a/gemma-web/src/main/webapp/pages/processProgress.jsp
+++ b/gemma-web/src/main/webapp/pages/processProgress.jsp
@@ -1,29 +1,26 @@
-<%@ include file="/common/taglibs.jsp"%>
+<%@ include file="/common/taglibs.jsp" %>
<%-- DEPRECATED, please use form-page-embedded ajaxified progress bar instead; see loadExpressionExperiment.js for some pointers. --%>
-
-
-
+
+
+
-
-
-
-
+
-
-
-
-
-
+
diff --git a/gemma-web/src/main/webapp/pages/register.jsp b/gemma-web/src/main/webapp/pages/register.jsp
index 96af384237..b3c3f8b868 100644
--- a/gemma-web/src/main/webapp/pages/register.jsp
+++ b/gemma-web/src/main/webapp/pages/register.jsp
@@ -2,6 +2,5 @@
Registration
-
\ No newline at end of file
diff --git a/gemma-web/src/main/webapp/pages/systemNotices.jsp b/gemma-web/src/main/webapp/pages/systemNotices.jsp
index 152c127c9c..a0a25cceb9 100644
--- a/gemma-web/src/main/webapp/pages/systemNotices.jsp
+++ b/gemma-web/src/main/webapp/pages/systemNotices.jsp
@@ -1,26 +1,14 @@
-<%@ include file="/common/taglibs.jsp"%>
+<%@ include file="/common/taglibs.jsp" %>
- System stats
+System stats
-
-
- Compute grid status
-
-
-
- This page has information about the status of the Gemma compute grid. Hit 'refresh' in your browser to see updated
- information.
-
-
-
-
-
-
-
-
+Compute grid status
+
+ This page has information about the status of the Gemma compute grid. Hit 'refresh' in your browser to see updated
+ information.
+
+
\ No newline at end of file
diff --git a/gemma-web/src/main/webapp/pages/taxa.jsp b/gemma-web/src/main/webapp/pages/taxa.jsp
new file mode 100644
index 0000000000..eacfa27374
--- /dev/null
+++ b/gemma-web/src/main/webapp/pages/taxa.jsp
@@ -0,0 +1,15 @@
+<%@ include file="/common/taglibs.jsp" %>
+
+Taxa
+
+
+
+
Taxa
+
+
+
+ ${taxon.commonName}
+
+
+
+
\ No newline at end of file
diff --git a/gemma-web/src/main/webapp/pages/taxon.detail.jsp b/gemma-web/src/main/webapp/pages/taxon.detail.jsp
new file mode 100644
index 0000000000..049d65f350
--- /dev/null
+++ b/gemma-web/src/main/webapp/pages/taxon.detail.jsp
@@ -0,0 +1,27 @@
+<%@ include file="/common/taglibs.jsp" %>
+
+
+${fn:escapeXml(taxon.commonName)}
+
+
+
+
${fn:escapeXml(taxon.commonName)}
+
+
+
+ NCBI ID:
+ ${taxon.ncbiId}
+
+
+
+ Scientific name:
+ ${fn:escapeXml(taxon.scientificName)}
+
+
+ Number of experiments:
+ ${numberOfExperiments}
+
+
+
\ No newline at end of file
diff --git a/gemma-web/src/main/webapp/pages/userProfile.jsp b/gemma-web/src/main/webapp/pages/userProfile.jsp
index 33be7024a0..7cd3f98c23 100644
--- a/gemma-web/src/main/webapp/pages/userProfile.jsp
+++ b/gemma-web/src/main/webapp/pages/userProfile.jsp
@@ -1,14 +1,15 @@
-<%@ include file="/common/taglibs.jsp"%>
-
+<%@ include file="/common/taglibs.jsp" %>
- Edit your profile
-
-
+Edit your profile
+
-
- Change your email address or password. You must enter your current password.
-
-
-
+
+
User Profile
+
+ Change your email address or password. You must enter your current password.
+
+
+
+
\ No newline at end of file
diff --git a/gemma-web/src/main/webapp/scripts/api/entities/analysis/differentialExpression/DifferentialExpressionAnalysesSummaryTree.js b/gemma-web/src/main/webapp/scripts/api/entities/analysis/differentialExpression/DifferentialExpressionAnalysesSummaryTree.js
index 9bba97b170..bcf3943bb8 100755
--- a/gemma-web/src/main/webapp/scripts/api/entities/analysis/differentialExpression/DifferentialExpressionAnalysesSummaryTree.js
+++ b/gemma-web/src/main/webapp/scripts/api/entities/analysis/differentialExpression/DifferentialExpressionAnalysesSummaryTree.js
@@ -472,7 +472,7 @@ Gemma.DifferentialExpressionAnalysesSummaryTree = Ext
linkText += '';
/* provide link for visualization. */
var tipText = "View top differentially expressed genes for "" + factorString + """;
- linkText += ' '
+ " ";
@@ -765,7 +765,7 @@ Ext.reg('differentialExpressionAnalysesSummaryTree', Gemma.DifferentialExpressio
* fix for now, should replace visualize 'button' with ext button that calls this function, and move function inside
* Gemma.DifferentialExpressionAnalysesSummaryTree
*/
-function visualizeDiffExpressionHandler(eeid, diffResultId, factorDetails, factorId) {
+Gemma.visualizeDiffExpressionHandler = function(eeid, diffResultId, factorDetails, factorId) {
var visDiffWindow = new Gemma.VisualizationWithThumbsWindow({
thumbnails: false,
diff --git a/gemma-web/src/main/webapp/scripts/api/entities/platform/ArrayDesignsNonPagingGrid.js b/gemma-web/src/main/webapp/scripts/api/entities/platform/ArrayDesignsNonPagingGrid.js
index 27c3216d09..cf6cc7e849 100755
--- a/gemma-web/src/main/webapp/scripts/api/entities/platform/ArrayDesignsNonPagingGrid.js
+++ b/gemma-web/src/main/webapp/scripts/api/entities/platform/ArrayDesignsNonPagingGrid.js
@@ -268,7 +268,7 @@ Gemma.ArrayDesignsNonPagingGrid = Ext
}
} );
} else if ( action === 'icon-refresh' ) {
- updateArrayDesignReport( record.id, grid ); // function in arrayDesign.js
+ Gemma.updateArrayDesignReport( record.id, grid ); // function in arrayDesign.js
}
},
// You can cancel the action by returning false from this
diff --git a/gemma-web/src/main/webapp/scripts/api/entities/platform/PlatformDetailsTab.js b/gemma-web/src/main/webapp/scripts/api/entities/platform/PlatformDetailsTab.js
index 23de27a88e..54fe37782b 100644
--- a/gemma-web/src/main/webapp/scripts/api/entities/platform/PlatformDetailsTab.js
+++ b/gemma-web/src/main/webapp/scripts/api/entities/platform/PlatformDetailsTab.js
@@ -117,7 +117,7 @@ Gemma.PlatformDetails = Ext
var updateT = '';
var isAdmin = Ext.get("hasAdmin").getValue() == 'true';
if (isAdmin) {
- updateT = ' ';
}
diff --git a/gemma-web/src/main/webapp/scripts/api/entities/platform/PlatformElementGrid.js b/gemma-web/src/main/webapp/scripts/api/entities/platform/PlatformElementGrid.js
index 8036f55080..38f5c03dfe 100644
--- a/gemma-web/src/main/webapp/scripts/api/entities/platform/PlatformElementGrid.js
+++ b/gemma-web/src/main/webapp/scripts/api/entities/platform/PlatformElementGrid.js
@@ -1,7 +1,7 @@
Ext.namespace( 'Gemma' );
/**
- *
+ *
* @class Gemma.PlatformElementGrid
* @extends Ext.grid.GridPanel
*/
@@ -26,7 +26,7 @@ Gemma.PlatformElementGrid = Ext
/**
* Show first batch of data.
- *
+ *
* @param {Object}
* isArrayDesign
* @param {Object}
@@ -168,6 +168,9 @@ Gemma.PlatformElementGrid = Ext
header : "Element Name",
width : 130,
dataIndex : "compositeSequenceName",
+ renderer : ( data, metadata, record ) => {
+ return '' + data + ' ';
+ },
tooltip : "Element or probe name"
},
{
@@ -269,7 +272,7 @@ Gemma.PlatformElementGrid = Ext
/**
* Event handler for searches. Update the lower grid.
- *
+ *
* @param {Object}
* event
*/
diff --git a/gemma-web/src/main/webapp/scripts/api/entities/platform/arrayDesign.js b/gemma-web/src/main/webapp/scripts/api/entities/platform/arrayDesign.js
index 3e91a24902..8fd27e9059 100755
--- a/gemma-web/src/main/webapp/scripts/api/entities/platform/arrayDesign.js
+++ b/gemma-web/src/main/webapp/scripts/api/entities/platform/arrayDesign.js
@@ -105,6 +105,8 @@ function updateArrayDesignReport( id, callerScope ) {
ArrayDesignController.updateReport.apply( this, callParams );
}
+Gemma.updateArrayDesignReport = updateArrayDesignReport;
+
function remove( id ) {
alert( "Are you sure?" );
}
diff --git a/gemma-web/src/main/webapp/scripts/lib/sprintf.js b/gemma-web/src/main/webapp/scripts/lib/sprintf.js
index 212ed71974..c64d7701a5 100644
--- a/gemma-web/src/main/webapp/scripts/lib/sprintf.js
+++ b/gemma-web/src/main/webapp/scripts/lib/sprintf.js
@@ -169,4 +169,6 @@ function sprintf() {
};
return format.replace(regex, doFormat);
-}
\ No newline at end of file
+}
+
+window.sprintf = sprintf;
\ No newline at end of file
diff --git a/gemma-web/src/main/webapp/styles/antisense/typo.css b/gemma-web/src/main/webapp/styles/antisense/typo.css
index 84cea426b9..3e892e1d2f 100644
--- a/gemma-web/src/main/webapp/styles/antisense/typo.css
+++ b/gemma-web/src/main/webapp/styles/antisense/typo.css
@@ -114,10 +114,26 @@ h6 {
font-size: 1.5em;
}
-#main h2, #main h3, #main h4, #main h5, #main h6 {
+#main h2 {
font-size: 1.25em;
}
+#main h3 {
+ font-size: 1.0em;
+}
+
+#main h4 {
+ font-size: 0.75em;
+}
+
+#main h5 {
+ font-size: 0.5em;
+}
+
+#main h6 {
+ font-size: 0.25em;
+}
+
/* END HEADINGS */ /* TEXT */
p {
margin-bottom: 1em;
@@ -232,9 +248,6 @@ dl dd {
}
/* END LISTS */ /* TABLE */
-td {
- font-weight: normal;
-}
/* this can interfere with EXT.js tables. */
table {
@@ -246,10 +259,14 @@ table {
}
+td {
+ font-weight: normal;
+ vertical-align: baseline;
+}
+
td.label {
font-weight: bold;
text-align: right;
- vertical-align: top;
padding-right: 8px;
padding-top: 4px;
}
diff --git a/gemma-web/src/test/java/ubic/gemma/web/util/StaticAssetServerTest.java b/gemma-web/src/test/java/ubic/gemma/web/util/StaticAssetServerTest.java
new file mode 100644
index 0000000000..430e0ab390
--- /dev/null
+++ b/gemma-web/src/test/java/ubic/gemma/web/util/StaticAssetServerTest.java
@@ -0,0 +1,89 @@
+package ubic.gemma.web.util;
+
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.mock.web.MockPageContext;
+import org.springframework.test.context.ContextConfiguration;
+import ubic.gemma.core.context.TestComponent;
+import ubic.gemma.core.util.test.TestPropertyPlaceholderConfigurer;
+import ubic.gemma.web.taglib.ImageTag;
+import ubic.gemma.web.taglib.ScriptTag;
+import ubic.gemma.web.taglib.StyleTag;
+
+import javax.servlet.ServletContext;
+import javax.servlet.jsp.JspException;
+import java.io.UnsupportedEncodingException;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+@ContextConfiguration
+public class StaticAssetServerTest extends BaseWebTest {
+
+ @Configuration
+ @TestComponent
+ static class StaticAssetServerTestContextConfiguration {
+
+ @Bean
+ public static TestPropertyPlaceholderConfigurer propertyPlaceholderConfigurer() {
+ return new TestPropertyPlaceholderConfigurer(
+ "gemma.staticAssetServer.enabled=true",
+ "gemma.staticAssetServer.baseUrl=http://localhost:8082",
+ "gemma.staticAssetServer.allowedDirs=/bundles/,/fonts/,/images/,/scripts/,/styles/" );
+ }
+
+ @Bean
+ public StaticAssetServer staticAssetServer() {
+ return new StaticAssetServer();
+ }
+ }
+
+ @Autowired
+ private StaticAssetServer staticAssetServer;
+
+ @Autowired
+ private ServletContext servletContext;
+
+ @Test
+ public void test() {
+ assertThat( staticAssetServer.resolveUrl( "/bundles/include.js" ) )
+ .isEqualTo( "http://localhost:8082/bundles/include.js" );
+ assertThatThrownBy( () -> staticAssetServer.resolveUrl( "/include.js" ) )
+ .isInstanceOf( IllegalArgumentException.class );
+ }
+
+ @Test
+ public void testScriptTag() throws JspException, UnsupportedEncodingException {
+ MockPageContext pageContext = new MockPageContext( servletContext );
+ ScriptTag tag = new ScriptTag();
+ tag.setPageContext( pageContext );
+ tag.setSrc( "/bundles/include.js" );
+ tag.doStartTag();
+ tag.doEndTag();
+ assertThat( pageContext.getContentAsString() ).isEqualTo( "" );
+ }
+
+ @Test
+ public void testStyleTag() throws JspException, UnsupportedEncodingException {
+ MockPageContext pageContext = new MockPageContext( servletContext );
+ StyleTag tag = new StyleTag();
+ tag.setPageContext( pageContext );
+ tag.setHref( "/bundles/gemma-all.css" );
+ tag.doStartTag();
+ tag.doEndTag();
+ assertThat( pageContext.getContentAsString() ).isEqualTo( " " );
+ }
+
+ @Test
+ public void testImageTags() throws JspException, UnsupportedEncodingException {
+ MockPageContext pageContext = new MockPageContext( servletContext );
+ ImageTag tag = new ImageTag();
+ tag.setPageContext( pageContext );
+ tag.setSrc( "/images/test.png" );
+ tag.doStartTag();
+ tag.doEndTag();
+ assertThat( pageContext.getContentAsString() ).isEqualTo( " " );
+ }
+}
\ No newline at end of file