diff --git a/gemma-cli/src/main/config/fish/completions/gemma-cli-staging.fish b/gemma-cli/src/main/config/fish/completions/gemma-cli-staging.fish index 61297964dd..180b9d8363 100644 --- a/gemma-cli/src/main/config/fish/completions/gemma-cli-staging.fish +++ b/gemma-cli/src/main/config/fish/completions/gemma-cli-staging.fish @@ -2329,14 +2329,14 @@ complete -c gemma-cli-staging -n "not __fish_seen_subcommand_from $gemma_all_sub complete -c gemma-cli-staging -n '__fish_seen_subcommand_from ubic.gemma.apps.AclLinterCli' -f complete -c gemma-cli-staging -n '__fish_seen_subcommand_from ubic.gemma.apps.AclLinterCli' -s h -l help -f --description 'Print this message' complete -c gemma-cli-staging -n '__fish_seen_subcommand_from ubic.gemma.apps.AclLinterCli' -o type -l type -r -a '(echo -e "PLATFORM\t\nDATASET\t\nDATASET_SUBSET\t\nDATASET_GROUP\t\nEXTERNAL_DATABASE\t\nEXPERIMENTAL_FACTOR\t\nEXPERIMENTAL_DESIGN\t\nFACTOR_VALUE\t\nASSAY\t\nSAMPLE\t\nCOEXPRESSION_ANALYSIS\t\nSAMPLE_COEXPRESSION_ANALYSIS\t\nDIFFERENTIAL_EXPRESSION_ANALYSIS\t\nDIFFERENTIAL_EXPRESSION_ANALYSIS_RESULT_SET\t\nGENE_DIFFERENTIAL_EXPRESSION_META_ANALYSIS\t\nPRINCIPAL_COMPONENT_ANALYSIS\t\nUSER_GROUP\t\nPROTOCOL\t\nMEAN_VARIANCE_RELATION\t\nGENE_GROUP\t\nJOB_INFO\t" 2>/dev/null)' -f --description 'Type of securable entities to lint. Possible values are: PLATFORM, DATASET, DATASET_SUBSET, DATASET_GROUP, EXTERNAL_DATABASE, EXPERIMENTAL_FACTOR, EXPERIMENTAL_DESIGN, FACTOR_VALUE, ASSAY, SAMPLE, COEXPRESSION_ANALYSIS, SAMPLE_COEXPRESSION_ANALYSIS, DIFFERENTIAL_EXPRESSION_ANALYSIS, DIFFERENTIAL_EXPRESSION_ANALYSIS_RESULT_SET, GENE_DIFFERENTIAL_EXPRESSION_META_ANALYSIS, PRINCIPAL_COMPONENT_ANALYSIS, USER_GROUP, PROTOCOL, MEAN_VARIANCE_RELATION, GENE_GROUP, JOB_INFO.' -complete -c gemma-cli-staging -n '__fish_seen_subcommand_from ubic.gemma.apps.AclLinterCli' -o identifier -l identifier -r -f --description 'Identifier of the securable entity to lint. Requires the -type,--type option to be set.' +complete -c gemma-cli-staging -n '__fish_seen_subcommand_from ubic.gemma.apps.AclLinterCli' -o identifier -l identifier -r -f --description 'Identifier of the securable entity to lint. Requires the -type,--type option to be set. Entity ID, short name, name, NCBI ID, common name, scientific name, alternate name' complete -c gemma-cli-staging -n '__fish_seen_subcommand_from ubic.gemma.apps.AclLinterCli' -o lintPermissions -l lint-permissions -f --description 'Lint permissions.' complete -c gemma-cli-staging -n '__fish_seen_subcommand_from ubic.gemma.apps.AclLinterCli' -o applyFixes -l apply-fixes -f --description 'Apply fixes to ACLs' complete -c gemma-cli-staging -n "not __fish_seen_subcommand_from $gemma_all_subcommands" -f -a lintAcls complete -c gemma-cli-staging -n '__fish_seen_subcommand_from lintAcls' -f complete -c gemma-cli-staging -n '__fish_seen_subcommand_from lintAcls' -s h -l help -f --description 'Print this message' complete -c gemma-cli-staging -n '__fish_seen_subcommand_from lintAcls' -o type -l type -r -a '(echo -e "PLATFORM\t\nDATASET\t\nDATASET_SUBSET\t\nDATASET_GROUP\t\nEXTERNAL_DATABASE\t\nEXPERIMENTAL_FACTOR\t\nEXPERIMENTAL_DESIGN\t\nFACTOR_VALUE\t\nASSAY\t\nSAMPLE\t\nCOEXPRESSION_ANALYSIS\t\nSAMPLE_COEXPRESSION_ANALYSIS\t\nDIFFERENTIAL_EXPRESSION_ANALYSIS\t\nDIFFERENTIAL_EXPRESSION_ANALYSIS_RESULT_SET\t\nGENE_DIFFERENTIAL_EXPRESSION_META_ANALYSIS\t\nPRINCIPAL_COMPONENT_ANALYSIS\t\nUSER_GROUP\t\nPROTOCOL\t\nMEAN_VARIANCE_RELATION\t\nGENE_GROUP\t\nJOB_INFO\t" 2>/dev/null)' -f --description 'Type of securable entities to lint. Possible values are: PLATFORM, DATASET, DATASET_SUBSET, DATASET_GROUP, EXTERNAL_DATABASE, EXPERIMENTAL_FACTOR, EXPERIMENTAL_DESIGN, FACTOR_VALUE, ASSAY, SAMPLE, COEXPRESSION_ANALYSIS, SAMPLE_COEXPRESSION_ANALYSIS, DIFFERENTIAL_EXPRESSION_ANALYSIS, DIFFERENTIAL_EXPRESSION_ANALYSIS_RESULT_SET, GENE_DIFFERENTIAL_EXPRESSION_META_ANALYSIS, PRINCIPAL_COMPONENT_ANALYSIS, USER_GROUP, PROTOCOL, MEAN_VARIANCE_RELATION, GENE_GROUP, JOB_INFO.' -complete -c gemma-cli-staging -n '__fish_seen_subcommand_from lintAcls' -o identifier -l identifier -r -f --description 'Identifier of the securable entity to lint. Requires the -type,--type option to be set.' +complete -c gemma-cli-staging -n '__fish_seen_subcommand_from lintAcls' -o identifier -l identifier -r -f --description 'Identifier of the securable entity to lint. Requires the -type,--type option to be set. Entity ID, short name, name, NCBI ID, common name, scientific name, alternate name' complete -c gemma-cli-staging -n '__fish_seen_subcommand_from lintAcls' -o lintPermissions -l lint-permissions -f --description 'Lint permissions.' complete -c gemma-cli-staging -n '__fish_seen_subcommand_from lintAcls' -o applyFixes -l apply-fixes -f --description 'Apply fixes to ACLs' complete -c gemma-cli-staging -n "not __fish_seen_subcommand_from $gemma_all_subcommands" -f -a ubic.gemma.apps.ExternalFileGeneLoaderCLI --description 'loading genes from a non-NCBI files; only used for species like salmon' diff --git a/gemma-cli/src/main/config/fish/completions/gemma-cli.fish b/gemma-cli/src/main/config/fish/completions/gemma-cli.fish index 446ec8365d..d33afc9255 100644 --- a/gemma-cli/src/main/config/fish/completions/gemma-cli.fish +++ b/gemma-cli/src/main/config/fish/completions/gemma-cli.fish @@ -2329,14 +2329,14 @@ complete -c gemma-cli -n "not __fish_seen_subcommand_from $gemma_all_subcommands complete -c gemma-cli -n '__fish_seen_subcommand_from ubic.gemma.apps.AclLinterCli' -f complete -c gemma-cli -n '__fish_seen_subcommand_from ubic.gemma.apps.AclLinterCli' -s h -l help -f --description 'Print this message' complete -c gemma-cli -n '__fish_seen_subcommand_from ubic.gemma.apps.AclLinterCli' -o type -l type -r -a '(echo -e "PLATFORM\t\nDATASET\t\nDATASET_SUBSET\t\nDATASET_GROUP\t\nEXTERNAL_DATABASE\t\nEXPERIMENTAL_FACTOR\t\nEXPERIMENTAL_DESIGN\t\nFACTOR_VALUE\t\nASSAY\t\nSAMPLE\t\nCOEXPRESSION_ANALYSIS\t\nSAMPLE_COEXPRESSION_ANALYSIS\t\nDIFFERENTIAL_EXPRESSION_ANALYSIS\t\nDIFFERENTIAL_EXPRESSION_ANALYSIS_RESULT_SET\t\nGENE_DIFFERENTIAL_EXPRESSION_META_ANALYSIS\t\nPRINCIPAL_COMPONENT_ANALYSIS\t\nUSER_GROUP\t\nPROTOCOL\t\nMEAN_VARIANCE_RELATION\t\nGENE_GROUP\t\nJOB_INFO\t" 2>/dev/null)' -f --description 'Type of securable entities to lint. Possible values are: PLATFORM, DATASET, DATASET_SUBSET, DATASET_GROUP, EXTERNAL_DATABASE, EXPERIMENTAL_FACTOR, EXPERIMENTAL_DESIGN, FACTOR_VALUE, ASSAY, SAMPLE, COEXPRESSION_ANALYSIS, SAMPLE_COEXPRESSION_ANALYSIS, DIFFERENTIAL_EXPRESSION_ANALYSIS, DIFFERENTIAL_EXPRESSION_ANALYSIS_RESULT_SET, GENE_DIFFERENTIAL_EXPRESSION_META_ANALYSIS, PRINCIPAL_COMPONENT_ANALYSIS, USER_GROUP, PROTOCOL, MEAN_VARIANCE_RELATION, GENE_GROUP, JOB_INFO.' -complete -c gemma-cli -n '__fish_seen_subcommand_from ubic.gemma.apps.AclLinterCli' -o identifier -l identifier -r -f --description 'Identifier of the securable entity to lint. Requires the -type,--type option to be set.' +complete -c gemma-cli -n '__fish_seen_subcommand_from ubic.gemma.apps.AclLinterCli' -o identifier -l identifier -r -f --description 'Identifier of the securable entity to lint. Requires the -type,--type option to be set. Entity ID, short name, name, NCBI ID, common name, scientific name, alternate name' complete -c gemma-cli -n '__fish_seen_subcommand_from ubic.gemma.apps.AclLinterCli' -o lintPermissions -l lint-permissions -f --description 'Lint permissions.' complete -c gemma-cli -n '__fish_seen_subcommand_from ubic.gemma.apps.AclLinterCli' -o applyFixes -l apply-fixes -f --description 'Apply fixes to ACLs' complete -c gemma-cli -n "not __fish_seen_subcommand_from $gemma_all_subcommands" -f -a lintAcls complete -c gemma-cli -n '__fish_seen_subcommand_from lintAcls' -f complete -c gemma-cli -n '__fish_seen_subcommand_from lintAcls' -s h -l help -f --description 'Print this message' complete -c gemma-cli -n '__fish_seen_subcommand_from lintAcls' -o type -l type -r -a '(echo -e "PLATFORM\t\nDATASET\t\nDATASET_SUBSET\t\nDATASET_GROUP\t\nEXTERNAL_DATABASE\t\nEXPERIMENTAL_FACTOR\t\nEXPERIMENTAL_DESIGN\t\nFACTOR_VALUE\t\nASSAY\t\nSAMPLE\t\nCOEXPRESSION_ANALYSIS\t\nSAMPLE_COEXPRESSION_ANALYSIS\t\nDIFFERENTIAL_EXPRESSION_ANALYSIS\t\nDIFFERENTIAL_EXPRESSION_ANALYSIS_RESULT_SET\t\nGENE_DIFFERENTIAL_EXPRESSION_META_ANALYSIS\t\nPRINCIPAL_COMPONENT_ANALYSIS\t\nUSER_GROUP\t\nPROTOCOL\t\nMEAN_VARIANCE_RELATION\t\nGENE_GROUP\t\nJOB_INFO\t" 2>/dev/null)' -f --description 'Type of securable entities to lint. Possible values are: PLATFORM, DATASET, DATASET_SUBSET, DATASET_GROUP, EXTERNAL_DATABASE, EXPERIMENTAL_FACTOR, EXPERIMENTAL_DESIGN, FACTOR_VALUE, ASSAY, SAMPLE, COEXPRESSION_ANALYSIS, SAMPLE_COEXPRESSION_ANALYSIS, DIFFERENTIAL_EXPRESSION_ANALYSIS, DIFFERENTIAL_EXPRESSION_ANALYSIS_RESULT_SET, GENE_DIFFERENTIAL_EXPRESSION_META_ANALYSIS, PRINCIPAL_COMPONENT_ANALYSIS, USER_GROUP, PROTOCOL, MEAN_VARIANCE_RELATION, GENE_GROUP, JOB_INFO.' -complete -c gemma-cli -n '__fish_seen_subcommand_from lintAcls' -o identifier -l identifier -r -f --description 'Identifier of the securable entity to lint. Requires the -type,--type option to be set.' +complete -c gemma-cli -n '__fish_seen_subcommand_from lintAcls' -o identifier -l identifier -r -f --description 'Identifier of the securable entity to lint. Requires the -type,--type option to be set. Entity ID, short name, name, NCBI ID, common name, scientific name, alternate name' complete -c gemma-cli -n '__fish_seen_subcommand_from lintAcls' -o lintPermissions -l lint-permissions -f --description 'Lint permissions.' complete -c gemma-cli -n '__fish_seen_subcommand_from lintAcls' -o applyFixes -l apply-fixes -f --description 'Apply fixes to ACLs' complete -c gemma-cli -n "not __fish_seen_subcommand_from $gemma_all_subcommands" -f -a ubic.gemma.apps.ExternalFileGeneLoaderCLI --description 'loading genes from a non-NCBI files; only used for species like salmon' diff --git a/gemma-cli/src/main/java/ubic/gemma/apps/AclLinterCli.java b/gemma-cli/src/main/java/ubic/gemma/apps/AclLinterCli.java index 35b4ae9392..2262cae20c 100644 --- a/gemma-cli/src/main/java/ubic/gemma/apps/AclLinterCli.java +++ b/gemma-cli/src/main/java/ubic/gemma/apps/AclLinterCli.java @@ -3,11 +3,12 @@ import lombok.AllArgsConstructor; import lombok.Getter; import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; import org.apache.commons.cli.ParseException; import org.springframework.beans.factory.annotation.Autowired; import ubic.gemma.cli.util.AbstractAuthenticatedCLI; +import ubic.gemma.cli.util.EntityLocator; +import ubic.gemma.cli.util.EntityOptionsUtils; import ubic.gemma.cli.util.OptionsUtils; import ubic.gemma.core.security.authorization.acl.AclLinterConfig; import ubic.gemma.core.security.authorization.acl.AclLinterService; @@ -68,9 +69,12 @@ private enum SecurableType { @Autowired private AclLinterService aclLinterService; + @Autowired + private EntityLocator entityLocator; + private Class clazz; - private Long identifier; + private String identifier; private boolean lintPermissions; @@ -82,8 +86,8 @@ private enum SecurableType { @Override protected void buildOptions( Options options ) { OptionsUtils.addEnumOption( options, "type", "type", "Type of securable entities to lint.", SecurableType.class ); - options.addOption( Option.builder( "identifier" ).longOpt( "identifier" ).hasArg().type( Long.class ) - .desc( "Identifier of the securable entity to lint. Requires the -type,--type option to be set." ).get() ); + EntityOptionsUtils.addEntityOption( options, "identifier", "identifier", + "Identifier of the securable entity to lint. Requires the -type,--type option to be set." ); options.addOption( "lintPermissions", "lint-permissions", false, "Lint permissions." ); options.addOption( "applyFixes", "apply-fixes", false, "Apply fixes to ACLs" ); } @@ -92,7 +96,7 @@ protected void buildOptions( Options options ) { protected void processOptions( CommandLine commandLine ) throws ParseException { SecurableType st = OptionsUtils.getEnumOptionValue( commandLine, "type" ); this.clazz = st != null ? st.getClazz() : null; - this.identifier = getParsedOptionValue( commandLine, "identifier", + this.identifier = getOptionValue( commandLine, "identifier", requires( toBeSet( "type" ) ) ); this.lintPermissions = commandLine.hasOption( "lintPermissions" ); this.applyFixes = commandLine.hasOption( "applyFixes" ); @@ -111,7 +115,9 @@ protected void doAuthenticatedWork() throws Exception { .build(); Collection results; if ( identifier != null ) { - results = aclLinterService.lintAcls( clazz, identifier, config ); + Securable entity = entityLocator.locateEntity( clazz, identifier, true ); + assert entity.getId() != null; + results = aclLinterService.lintAcls( clazz, entity.getId(), config ); } else if ( clazz != null ) { results = aclLinterService.lintAcls( clazz, config ); } else { diff --git a/gemma-cli/src/main/java/ubic/gemma/cli/util/EntityLocator.java b/gemma-cli/src/main/java/ubic/gemma/cli/util/EntityLocator.java index 8e15eb3b80..2ff1edd25d 100644 --- a/gemma-cli/src/main/java/ubic/gemma/cli/util/EntityLocator.java +++ b/gemma-cli/src/main/java/ubic/gemma/cli/util/EntityLocator.java @@ -1,6 +1,7 @@ package ubic.gemma.cli.util; import ubic.gemma.model.analysis.expression.diff.DifferentialExpressionAnalysis; +import ubic.gemma.model.common.Identifiable; import ubic.gemma.model.common.protocol.Protocol; import ubic.gemma.model.common.quantitationtype.QuantitationType; import ubic.gemma.model.expression.arrayDesign.ArrayDesign; @@ -16,11 +17,13 @@ import java.util.Map; /** - * Locate various entities using identifiers supplied by the CLI. + * Locate various entities using identifiers. * @author poirigui */ public interface EntityLocator { + T locateEntity( Class clazz, String identifier, boolean useReferencesIfPossible ); + Taxon locateTaxon( String identifier ); ArrayDesign locateArrayDesign( String identifier ); diff --git a/gemma-cli/src/main/java/ubic/gemma/cli/util/EntityLocatorImpl.java b/gemma-cli/src/main/java/ubic/gemma/cli/util/EntityLocatorImpl.java index 8a1a3fd793..ac434f07a9 100644 --- a/gemma-cli/src/main/java/ubic/gemma/cli/util/EntityLocatorImpl.java +++ b/gemma-cli/src/main/java/ubic/gemma/cli/util/EntityLocatorImpl.java @@ -3,6 +3,7 @@ import lombok.extern.apachecommons.CommonsLog; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.Pair; +import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.util.Assert; @@ -52,6 +53,38 @@ public class EntityLocatorImpl implements EntityLocator { private SingleCellExpressionExperimentService singleCellExpressionExperimentService; @Autowired private DifferentialExpressionAnalysisService differentialExpressionAnalysisService; + @Autowired + private SessionFactory sessionFactory; + + @Override + @SuppressWarnings("unchecked") + public T locateEntity( Class clazz, String identifier, boolean useReferencesIfPossible ) { + // if a match by ID is possible, prefer it so we can apply useReferencesIfPossible for anything + try { + Long id = Long.parseLong( identifier ); + if ( useReferencesIfPossible ) { + return ( T ) sessionFactory.getCurrentSession().load( clazz, id ); + } else { + return ( T ) requireNonNull( sessionFactory.getCurrentSession().get( clazz, id ), + "No " + clazz.getSimpleName() + " found with ID " + id + "." ); + } + } catch ( NumberFormatException e ) { + // ignore + } + // this is a non-ID lookup, so delegate to the appropriate locator + if ( Taxon.class.isAssignableFrom( clazz ) ) { + return ( T ) locateTaxon( identifier ); + } else if ( Protocol.class.isAssignableFrom( clazz ) ) { + return ( T ) locateProtocol( identifier ); + } else if ( ArrayDesign.class.isAssignableFrom( clazz ) ) { + return ( T ) locateArrayDesign( identifier ); + } else if ( ExpressionExperiment.class.isAssignableFrom( clazz ) ) { + return ( T ) locateExpressionExperiment( identifier, useReferencesIfPossible ); + } else { + // all the other locator in this class require an experiment context, so we cannot support them here. + throw new UnsupportedOperationException( "Cannot locate an entity of type " + clazz.getSimpleName() + "." ); + } + } @Override public Taxon locateTaxon( String identifier ) { diff --git a/gemma-cli/src/main/java/ubic/gemma/cli/util/EntityOptionsUtils.java b/gemma-cli/src/main/java/ubic/gemma/cli/util/EntityOptionsUtils.java index 1e7fb410a0..ed5fb57264 100644 --- a/gemma-cli/src/main/java/ubic/gemma/cli/util/EntityOptionsUtils.java +++ b/gemma-cli/src/main/java/ubic/gemma/cli/util/EntityOptionsUtils.java @@ -2,6 +2,7 @@ import org.apache.commons.cli.Option; import org.apache.commons.cli.Options; +import org.apache.commons.lang3.Strings; import ubic.gemma.cli.completion.CompletionType; import ubic.gemma.cli.completion.CompletionUtils; @@ -11,6 +12,19 @@ */ public class EntityOptionsUtils { + + /** + * @see EntityLocator#locateEntity(Class, String, boolean) + */ + public static void addEntityOption( Options options, String optionName, String longOpt, String description ) { + options.addOption( Option.builder( optionName ) + .longOpt( longOpt ) + .hasArg() + .argName( "ID, short name, name, NCBI ID, common name, scientific name, alternate name" ) + .desc( Strings.CS.appendIfMissing( description, "." ) + " Entity ID, short name, name, NCBI ID, common name, scientific name, alternate name" ) + .get() ); + } + /** * Add an option for supplying a dataset. */