diff --git a/gemma-cli/src/main/java/ubic/gemma/core/apps/AclLinterCli.java b/gemma-cli/src/main/java/ubic/gemma/core/apps/AclLinterCli.java new file mode 100644 index 0000000000..adf70e8852 --- /dev/null +++ b/gemma-cli/src/main/java/ubic/gemma/core/apps/AclLinterCli.java @@ -0,0 +1,105 @@ +package ubic.gemma.core.apps; + +import gemma.gsec.acl.domain.AclObjectIdentity; +import gemma.gsec.model.Securable; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.Options; +import org.apache.commons.cli.ParseException; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import ubic.gemma.core.util.AbstractCLI; +import ubic.gemma.model.expression.arrayDesign.ArrayDesign; +import ubic.gemma.model.expression.bioAssay.BioAssay; +import ubic.gemma.model.expression.biomaterial.BioMaterial; +import ubic.gemma.model.expression.experiment.*; + +import javax.annotation.Nullable; +import java.util.List; + +@Component +public class AclLinterCli extends AbstractCLI { + + @Autowired + private SessionFactory sessionFactory; + + @Override + protected void buildOptions( Options options ) { + + } + + @Override + protected void processOptions( CommandLine commandLine ) throws ParseException { + + } + + @Override + protected void doWork() throws Exception { + Session session = sessionFactory.openSession(); + try { + warnEntitiesLackingObjectIdentity( session, ArrayDesign.class ); + warnEntitiesLackingObjectIdentity( session, ExpressionExperiment.class ); + warnEntitiesLackingObjectIdentity( session, ExpressionExperimentSubSet.class ); + warnEntitiesLackingObjectIdentity( session, BioMaterial.class ); + warnEntitiesLackingObjectIdentity( session, BioAssay.class ); + warnEntitiesLackingObjectIdentity( session, ExperimentalDesign.class ); + warnEntitiesLackingObjectIdentity( session, ExperimentalFactor.class ); + warnEntitiesLackingObjectIdentity( session, FactorValue.class ); + + warnEntitiesWhoseParentObjectIsMissing( session, ExpressionExperimentSubSet.class, ExpressionExperiment.class ); + warnEntitiesWhoseParentObjectIsMissing( session, BioAssay.class, ExpressionExperiment.class ); + warnEntitiesWhoseParentObjectIsMissing( session, ExperimentalDesign.class, ExpressionExperiment.class ); + warnEntitiesWhoseParentObjectIsMissing( session, ExperimentalFactor.class, ExpressionExperiment.class ); + warnEntitiesWhoseParentObjectIsMissing( session, FactorValue.class, ExpressionExperiment.class ); + } finally { + session.close(); + } + } + + private void warnEntitiesLackingObjectIdentity( Session session, Class clazz ) { + //language=HQL + //noinspection unchecked + List list = session + .createQuery( "select e from " + clazz.getName() + " e " + + "where e.id not in ( " + "select aoi.identifier from AclObjectIdentity aoi where aoi.type = :type" + ")" ) + .setParameter( "type", clazz.getName() ) + .list(); + for ( Securable ee : list ) { + addErrorObject( ee, String.format( "Object with ID %d lacks an ACL identity of type %s", ee.getId(), clazz.getName() ) ); + } + } + + private void warnEntitiesWhoseParentObjectIsMissing( Session session, Class clazz, Class parentType ) { + //noinspection unchecked + List list = session + .createQuery( "select e, aoi.parentObject from " + clazz.getName() + " e, AclObjectIdentity aoi " + + "where aoi.identifier = e.id and aoi.type = :type " + + "and aoi.parentObject is not null " + + "and aoi.parentObject.identifier not in (select p.id from " + parentType.getName() + " p)" ) + .setParameter( "type", clazz.getName() ) + .list(); + for ( Object[] ee : list ) { + Securable s = ( Securable ) ee[0]; + AclObjectIdentity parentAoi = ( AclObjectIdentity ) ee[1]; + addErrorObject( s, String.format( "Parent of object with ID %d does not exist; parent ACL identity is %s", s.getId(), parentAoi ) ); + } + } + + @Nullable + @Override + public String getCommandName() { + return "lintAcls"; + } + + @Nullable + @Override + public String getShortDesc() { + return null; + } + + @Override + public GemmaCLI.CommandGroup getCommandGroup() { + return GemmaCLI.CommandGroup.SYSTEM; + } +} diff --git a/gemma-cli/src/test/java/ubic/gemma/core/apps/AclLinterCliTest.java b/gemma-cli/src/test/java/ubic/gemma/core/apps/AclLinterCliTest.java new file mode 100644 index 0000000000..1d88d678be --- /dev/null +++ b/gemma-cli/src/test/java/ubic/gemma/core/apps/AclLinterCliTest.java @@ -0,0 +1,36 @@ +package ubic.gemma.core.apps; + +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.test.context.ContextConfiguration; +import ubic.gemma.core.util.test.BaseDatabaseTest; +import ubic.gemma.persistence.util.TestComponent; + +import static ubic.gemma.core.util.test.Assertions.assertThat; + +@ContextConfiguration +public class AclLinterCliTest extends BaseDatabaseTest { + + @Configuration + @TestComponent + static class AclLinterCliTestContextConfiguration extends BaseDatabaseTestContextConfiguration { + + @Bean + public AclLinterCli aclLinterCli() { + return new AclLinterCli(); + } + } + + @Autowired + private AclLinterCli aclLinterCli; + + @Test + public void test() { + assertThat( aclLinterCli ) + .withArguments() + .hasCommandName( "lintAcls" ) + .succeeds(); + } +} \ No newline at end of file diff --git a/gemma-cli/src/test/java/ubic/gemma/core/util/test/Assertions.java b/gemma-cli/src/test/java/ubic/gemma/core/util/test/Assertions.java new file mode 100644 index 0000000000..253bfb0e37 --- /dev/null +++ b/gemma-cli/src/test/java/ubic/gemma/core/util/test/Assertions.java @@ -0,0 +1,10 @@ +package ubic.gemma.core.util.test; + +import ubic.gemma.core.util.CLI; + +public class Assertions { + + public static CliAssert assertThat( CLI cli ) { + return new CliAssert( cli ); + } +} diff --git a/gemma-cli/src/test/java/ubic/gemma/core/util/test/CliAssert.java b/gemma-cli/src/test/java/ubic/gemma/core/util/test/CliAssert.java new file mode 100644 index 0000000000..21728d3e65 --- /dev/null +++ b/gemma-cli/src/test/java/ubic/gemma/core/util/test/CliAssert.java @@ -0,0 +1,30 @@ +package ubic.gemma.core.util.test; + +import org.assertj.core.api.AbstractAssert; +import ubic.gemma.core.util.CLI; + +/** + * AssertJ assertions for {@link CLI}. + */ +public class CliAssert extends AbstractAssert { + + private String[] args = {}; + + public CliAssert( CLI cli ) { + super( cli, CliAssert.class ); + } + + public CliAssert withArguments( String... args ) { + this.args = args; + return myself; + } + + public CliAssert hasCommandName( String commandName ) { + objects.assertEqual( info, commandName, actual.getCommandName() ); + return myself; + } + + public void succeeds() { + objects.assertEqual( info, 0, actual.executeCommand( args ) ); + } +} diff --git a/gemma-core/src/test/java/ubic/gemma/core/util/test/BaseDatabaseTest.java b/gemma-core/src/test/java/ubic/gemma/core/util/test/BaseDatabaseTest.java index c4de79b004..71d76de660 100644 --- a/gemma-core/src/test/java/ubic/gemma/core/util/test/BaseDatabaseTest.java +++ b/gemma-core/src/test/java/ubic/gemma/core/util/test/BaseDatabaseTest.java @@ -123,8 +123,8 @@ public DataSourceInitializer( DataSource dataSource ) { @Override public void afterPropertiesSet() { JdbcTestUtils.executeSqlScript( template, applicationContext.getResource( "/sql/init-acls.sql" ), false ); - JdbcTestUtils.executeSqlScript( template, applicationContext.getResource( "/sql/init-entities.sql" ), false ); - JdbcTestUtils.executeSqlScript( template, applicationContext.getResource( "/sql/init-indices.sql" ), false ); + JdbcTestUtils.executeSqlScript( template, applicationContext.getResource( "/sql/h2/init-entities.sql" ), false ); + JdbcTestUtils.executeSqlScript( template, applicationContext.getResource( "/sql/h2/init-indices.sql" ), false ); } } } diff --git a/gemma-core/src/test/resources/sql/init-entities.sql b/gemma-core/src/test/resources/sql/h2/init-entities.sql similarity index 100% rename from gemma-core/src/test/resources/sql/init-entities.sql rename to gemma-core/src/test/resources/sql/h2/init-entities.sql diff --git a/gemma-core/src/test/resources/sql/init-indices.sql b/gemma-core/src/test/resources/sql/h2/init-indices.sql similarity index 100% rename from gemma-core/src/test/resources/sql/init-indices.sql rename to gemma-core/src/test/resources/sql/h2/init-indices.sql