Created
January 31, 2026 14:23
-
-
Save CodingBash/2ac7e305c747ff220d44d0909dc4a71d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package edu.columbia.biology.service; | |
| import org.springframework.security.core.Authentication; | |
| import edu.columbia.biology.model.FitDetails; | |
| public interface FitService { | |
| /** | |
| * Given fitId, retrieve the fitDetails | |
| * | |
| * @return | |
| */ | |
| public FitDetails retrieveFitDetails(int fitId, boolean isSiteAdmin); | |
| public String retrieveFitScoringJson(int fitId); | |
| /** | |
| * Determine if fit is user accessible | |
| * | |
| * @param principal | |
| * @param fitId | |
| * @return | |
| */ | |
| public boolean isFitUserAccessible(Authentication authentication, int fitId); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package edu.columbia.biology.service; | |
| import java.util.Arrays; | |
| import java.util.Collection; | |
| import java.util.LinkedList; | |
| import java.util.List; | |
| import java.util.stream.Collectors; | |
| import org.springframework.beans.factory.annotation.Autowired; | |
| import org.springframework.beans.factory.annotation.Qualifier; | |
| import org.springframework.security.core.Authentication; | |
| import org.springframework.stereotype.Service; | |
| import edu.columbia.biology.mapper.FitsRepositoryMapper; | |
| import edu.columbia.biology.model.FitDetails; | |
| import edu.columbia.biology.model.FitsMetadataInformation; | |
| import edu.columbia.biology.model.PostprocContainerTO; | |
| import edu.columbia.biology.model.PostprocEntryTO; | |
| import edu.columbia.biology.model.PostprocItem; | |
| import edu.columbia.biology.processor.CellxPrincipalProcessor; | |
| import edu.columbia.biology.processor.PostprocProcessor; | |
| import edu.columbia.biology.repository.CellxGlobalFitCurationCommentRepository; | |
| import edu.columbia.biology.repository.FitsRepository; | |
| import edu.columbia.biology.view_model.PostprocComponent; | |
| @Service | |
| public class FitServiceImpl implements FitService { | |
| @Autowired | |
| private PostprocProcessor postprocProcessor; | |
| @Autowired | |
| private CellxPrincipalProcessor cellxPrincipalProcessor; | |
| @Autowired | |
| private FitsRepository fitsRepository; | |
| @Autowired | |
| private FitsRepositoryMapper fitsRepositoryMapper; | |
| @Autowired | |
| private StudyService studyService; | |
| @Autowired | |
| private PostprocService postprocService; | |
| @Qualifier("publicAccessiblePostprocs") | |
| @Autowired | |
| private List<String> publicAccessiblePostprocs; | |
| /** | |
| * TODO: The code here could be optimized for faster loading. Also perhaps | |
| * postprocs could be loaded asyncronously by sending the postproc entries to | |
| * the page, then asyncronosuly loading the postproc on expand? Therefore, it | |
| * could also be cacheable? | |
| */ | |
| @Override | |
| public FitDetails retrieveFitDetails(int fitId, boolean isSiteAdmin) { | |
| FitsMetadataInformation fitsMetadataInformation = retrieveFitsMetadataInformation(fitId); | |
| List<PostprocItem> postprocItems = postprocService.retrievePostprocItems(fitId); | |
| // Non site admins only have access to basicModelViewer and resourceMotif | |
| if (!isSiteAdmin) { | |
| postprocItems = postprocItems.stream() | |
| .filter(postprocItem -> publicAccessiblePostprocs.contains(postprocItem.getPostMethodName())) | |
| .collect(Collectors.toList()); | |
| } | |
| return new FitDetails(fitsMetadataInformation, postprocItems); | |
| } | |
| @Override | |
| public boolean isFitUserAccessible(Authentication authentication, int fitId) { | |
| if (cellxPrincipalProcessor.isSiteAdmin(authentication)) { | |
| return true; | |
| } else { | |
| List<String> fitStudyNames = studyService.retrieveFitAssociatedStudies(fitId); | |
| List<String> userAccessibleStudies = studyService.retrieveUserAccessibleStudies(authentication); | |
| return userAccessibleStudies.containsAll(fitStudyNames); | |
| } | |
| } | |
| @Override | |
| public String retrieveFitScoringJson(int fitId) { | |
| return fitsRepository.retrieveFitScoringJson(fitId); | |
| } | |
| public boolean isFitGlobalAccessible(Authentication authentication, int fitId) { | |
| if (cellxPrincipalProcessor.isSiteAdmin(authentication)) { | |
| return true; | |
| } else { | |
| List<String> fitStudyNames = studyService.retrieveFitAssociatedStudies(fitId); | |
| List<String> userAccessibleStudies = studyService.retrieveUserAccessibleStudies(authentication); | |
| return userAccessibleStudies.containsAll(fitStudyNames); | |
| } | |
| } | |
| /** | |
| * Given the fitId, retrieve the fit's metadata information | |
| * | |
| * @param fitId | |
| * @return | |
| */ | |
| private FitsMetadataInformation retrieveFitsMetadataInformation(int fitId) { | |
| return fitsRepositoryMapper.retrieveFitMetadataMapper(fitsRepository.retrieveFitMetadata(fitId)); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package edu.columbia.biology.repository; | |
| import org.springframework.transaction.annotation.Transactional; | |
| import java.util.Collection; | |
| import java.util.List; | |
| import org.springframework.data.jpa.repository.JpaRepository; | |
| import org.springframework.data.jpa.repository.JpaSpecificationExecutor; | |
| import org.springframework.data.jpa.repository.Query; | |
| import org.springframework.stereotype.Repository; | |
| import edu.columbia.biology.entity.Fits; | |
| /** | |
| * Generated by Spring Data Generator on 14/01/2019 | |
| */ | |
| @Repository | |
| @Transactional | |
| public interface FitsRepository extends JpaRepository<Fits, Integer>, JpaSpecificationExecutor<Fits> { | |
| // TODO: [CONVENIENT] All added queries and repository methods somehow needs to | |
| // be externalized to a properties/yaml file. | |
| @Query("SELECT f from edu.columbia.biology.entity.Fits f WHERE f.regressorId = ?1") | |
| Collection<Fits> findAllByRegressorId(Integer regressorId); | |
| /** | |
| * Retrieve every fit - used for administrator view | |
| * | |
| * TODO: Is this method still used? 3/12/21 YES I believe for admins? | |
| * | |
| * @deprecated | |
| */ | |
| @Deprecated | |
| @Query(value = "SELECT fits.fit_id, cellx_global_fit_curation.curated," | |
| + "CAST(ARRAY_AGG(DISTINCT experiment.study_name) AS text) AS study_name_list, " | |
| + "CAST(ARRAY_AGG(DISTINCT study.study_display_name) AS text) AS study_display_name_list,\r\n" | |
| + "CAST(ARRAY_AGG(DISTINCT experiment.experiment_name) AS text) AS experiment_name_list, " | |
| + "CAST(ARRAY_AGG(DISTINCT factor.gene_symbol) AS text) AS gene_symbol_list, " | |
| + "CAST(ARRAY_AGG(DISTINCT factor.factor_id) AS text) AS factor_id_list, " | |
| + "CAST(ARRAY_AGG(DISTINCT factor.tax_id) AS text) AS tax_id_list FROM fits, " | |
| + "INNER JOIN count_fit ON fits.fit_id = count_fit.fit_id " | |
| + "INNER JOIN count_table ON count_fit.count_table_id = count_table.count_table_id " | |
| + "INNER JOIN experiment ON count_table.study_name = experiment.study_name AND count_table.experiment_name = experiment.experiment_name " | |
| + "INNER JOIN factor_complex ON experiment.complex_id = factor_complex.complex_id " | |
| + "INNER JOIN factor ON factor_complex.factor_id = factor.factor_id " | |
| + "LEFT JOIN cellx_global_fit_curation ON fits.fit_id = cellx_global_fit_curation.fit_id " | |
| + "WHERE fits.iscomplete=TRUE " | |
| + "GROUP BY fits.fit_id, cellx_global_fit_curation.curated ", nativeQuery = true) | |
| Collection<Object[]> retrieveAllFits(); | |
| /** | |
| * Retrieve every fit in a public study - used for administrator view | |
| */ | |
| @Query(value = "SELECT fits.fit_id, fits.fit_path, cellx_global_fit_curation.curated,\r\n " | |
| + "CAST(ARRAY_AGG(DISTINCT cellx_global_fit_curation_tag.tag) AS text) AS tag_list,\r\n" | |
| + "CAST(ARRAY_AGG(DISTINCT experiment.study_name) AS text) AS study_name_list,\r\n" | |
| + "CAST(ARRAY_AGG(DISTINCT study.study_display_name) AS text) AS study_display_name_list,\r\n" | |
| + "CAST(ARRAY_AGG(DISTINCT experiment.experiment_name) AS text) AS experiment_name_list, " | |
| + "CAST(ARRAY_AGG(DISTINCT factor.gene_symbol) AS text) AS gene_symbol_list, " | |
| + "CAST(ARRAY_AGG(DISTINCT factor.factor_id) AS text) AS factor_id_list, " | |
| + "CAST(ARRAY_AGG(DISTINCT factor.tax_id) AS text) AS tax_id_list, " + "fits.ranking_score, " | |
| + "fit_group_curated.group_id AS pipeline_group_id, " + "fit_group_curated.metric AS pipeline_metric, " | |
| + "fit_group_curated.metric_value AS pipeline_metric_value, " | |
| + "fit_group_curated.iscurated AS pipeline_curated FROM fits " | |
| + "INNER JOIN fit_group_curated ON fits.fit_id = fit_group_curated.fit_id " | |
| + "INNER JOIN count_fit ON fits.fit_id = count_fit.fit_id " | |
| + "INNER JOIN count_table ON count_fit.count_table_id = count_table.count_table_id " | |
| + "INNER JOIN experiment ON count_table.study_name = experiment.study_name AND count_table.experiment_name = experiment.experiment_name " | |
| + "INNER JOIN study ON study.study_name = experiment.study_name " | |
| + "INNER JOIN factor_complex ON experiment.complex_id = factor_complex.complex_id " | |
| + "INNER JOIN factor ON factor_complex.factor_id = factor.factor_id " | |
| + "LEFT JOIN cellx_global_fit_curation ON fits.fit_id = cellx_global_fit_curation.fit_id " | |
| + "LEFT JOIN cellx_global_fit_curation_tag ON fits.fit_id = cellx_global_fit_curation_tag.fit_id " | |
| + "WHERE fits.iscomplete=TRUE " + "GROUP BY fits.fit_id, fits.fit_path, cellx_global_fit_curation.curated, " | |
| + "fit_group_curated.group_id, fit_group_curated.metric, fit_group_curated.metric_value, fit_group_curated.iscurated " | |
| + "HAVING NOT true=any(ARRAY_AGG(DISTINCT study.isembargoed))", nativeQuery = true) | |
| Collection<Object[]> retrievePublicFits(); | |
| /** | |
| * Retrieve every fit in a public study that is also curated - for users | |
| */ | |
| @Query(value = "SELECT fits.fit_id, fits.fit_path, cellx_global_fit_curation.curated, \r\n" | |
| + "CAST(ARRAY_AGG(DISTINCT cellx_global_fit_curation_tag.tag) AS text) AS tag_list,\r\n" | |
| + "CAST(ARRAY_AGG(DISTINCT experiment.study_name) AS text) AS study_name_list,\r\n" | |
| + "CAST(ARRAY_AGG(DISTINCT study.study_display_name) AS text) AS study_display_name_list,\r\n" | |
| + "CAST(ARRAY_AGG(DISTINCT experiment.experiment_name) AS text) AS experiment_name_list, " | |
| + "CAST(ARRAY_AGG(DISTINCT factor.gene_symbol) AS text) AS gene_symbol_list, " | |
| + "CAST(ARRAY_AGG(DISTINCT factor.factor_id) AS text) AS factor_id_list, " | |
| + "CAST(ARRAY_AGG(DISTINCT factor.tax_id) AS text) AS tax_id_list, " + "fits.ranking_score, " | |
| + "fit_group_curated.group_id AS pipeline_group_id, " + "fit_group_curated.metric AS pipeline_metric, " | |
| + "fit_group_curated.metric_value AS pipeline_metric_value, " | |
| + "fit_group_curated.iscurated AS pipeline_curated FROM fits " | |
| + "INNER JOIN fit_group_curated ON fits.fit_id = fit_group_curated.fit_id " | |
| + "INNER JOIN count_fit ON fits.fit_id = count_fit.fit_id " | |
| + "INNER JOIN count_table ON count_fit.count_table_id = count_table.count_table_id " | |
| + "INNER JOIN experiment ON count_table.study_name = experiment.study_name AND count_table.experiment_name = experiment.experiment_name " | |
| + "INNER JOIN study ON study.study_name = experiment.study_name " | |
| + "INNER JOIN factor_complex ON experiment.complex_id = factor_complex.complex_id " | |
| + "INNER JOIN factor ON factor_complex.factor_id = factor.factor_id " | |
| + "LEFT JOIN cellx_global_fit_curation ON fits.fit_id = cellx_global_fit_curation.fit_id " | |
| + "LEFT JOIN cellx_global_fit_curation_tag ON fits.fit_id = cellx_global_fit_curation_tag.fit_id " | |
| + "WHERE ((fits.iscomplete=TRUE) AND (cellx_global_fit_curation.curated IS NOT FALSE) AND ((cellx_global_fit_curation.curated IS TRUE) OR ((cellx_global_fit_curation.curated IS NULL) AND (fit_group_curated.iscurated IS TRUE)))) " | |
| + "GROUP BY fits.fit_id, fits.fit_path, cellx_global_fit_curation.curated, " | |
| + "fit_group_curated.group_id, fit_group_curated.metric, fit_group_curated.metric_value, fit_group_curated.iscurated " | |
| + "HAVING NOT true=any(ARRAY_AGG(DISTINCT study.isembargoed)) AND ARRAY_AGG(DISTINCT cellx_global_fit_curation_tag.tag) @> '{\"GOOD\"}'", nativeQuery = true) | |
| Collection<Object[]> retrievePublicCuratedFits(); | |
| // TODO: Replace the cellx tables with the new version in celldb-devtest version | |
| /** | |
| * Retrieve every fit that a user has access to | |
| * | |
| * @Deprecated - method not yet used | |
| */ | |
| @Deprecated | |
| @Query(value = "SELECT fits.fit_id, fits.fit_path, postproc.postproc_id, postproc.output_string, " | |
| + "CAST(ARRAY_AGG(DISTINCT experiment.study_name) AS text) AS study_name_list, " | |
| + "CAST(ARRAY_AGG(DISTINCT study.study_display_name) AS text) AS study_display_name_list,\r\n" | |
| + "CAST(ARRAY_AGG(DISTINCT experiment.experiment_name) AS text) AS experiment_name_list, " | |
| + "CAST(ARRAY_AGG(DISTINCT factor.gene_symbol) AS text) AS gene_symbol_list, " | |
| + "CAST(ARRAY_AGG(DISTINCT factor.factor_id) AS text) AS factor_id_list, " | |
| + "CAST(ARRAY_AGG(DISTINCT factor.tax_id) AS text) AS tax_id_list FROM fits " | |
| + "INNER JOIN count_fit ON fits.fit_id = count_fit.fit_id " | |
| + "INNER JOIN count_table ON count_fit.count_table_id = count_table.count_table_id " | |
| + "INNER JOIN experiment ON count_table.study_name = experiment.study_name AND count_table.experiment_name = experiment.experiment_name " | |
| + "INNER JOIN study ON study.study_name = experiment.study_name " | |
| + "LEFT JOIN cellx_group_study ON study.study_name = cellx_group_study.study_name " | |
| + "LEFT JOIN cellx_group ON cellx_group_study.group_id = cellx_group.group_id " | |
| + "LEFT JOIN cellx_group_user ON cellx_group.group_id = cellx_group_user.group_id " | |
| + "INNER JOIN factor_complex ON experiment.complex_id = factor_complex.complex_id " | |
| + "INNER JOIN factor ON factor_complex.factor_id = factor.factor_id " | |
| + "INNER JOIN fit_post ON fits.fit_id = fit_post.fit_id " | |
| + "INNER JOIN postproc ON fit_post.postproc_id = postproc.postproc_id " | |
| + "WHERE postproc.post_method_name='summaryQC' AND fits.iscomplete=TRUE AND (cellx_group_user.user_id = ?1 OR cellx_group_user.user_id IS NULL)" | |
| + "GROUP BY fits.fit_id, postproc.postproc_id, postproc.output_string " | |
| + "HAVING NOT false=any(ARRAY_AGG(DISTINCT CASE WHEN study.isembargoed = false OR cellx_group_user.user_id = ?1 THEN true ELSE false END))", nativeQuery = true) | |
| Collection<Object[]> retrieveUserAccessibleFits(Integer userId); | |
| /** | |
| * Retrieve studies associated with a fit | |
| */ | |
| @Query("SELECT DISTINCT countTable.studyName FROM edu.columbia.biology.entity.Fits fits " | |
| + "INNER JOIN edu.columbia.biology.entity.CountFit countFit ON fits.fitId = countFit.fitId " | |
| + "INNER JOIN edu.columbia.biology.entity.CountTable countTable ON countFit.countTableId = countTable.countTableId " | |
| + "WHERE fits.fitId = ?1") | |
| Collection<String> retrieveFitStudies(Integer fitId); | |
| @Query("SELECT fits.scoringJson FROM edu.columbia.biology.entity.Fits fits WHERE fits.fitId = ?1") | |
| String retrieveFitScoringJson(Integer fitId); | |
| /** | |
| * Retrieve fit metadata | |
| */ | |
| @Query(value = "SELECT fits.fit_id, fits.fit_path,\r\n" | |
| + "CAST(ARRAY_AGG(DISTINCT experiment.study_name) AS text) AS study_name_list,\r\n" | |
| + "CAST(ARRAY_AGG(DISTINCT study.study_display_name) AS text) AS study_display_name_list,\r\n" | |
| + "CAST(ARRAY_AGG(DISTINCT experiment.experiment_name) AS text) AS experiment_name_list,\r\n" | |
| + "CAST(ARRAY_AGG(DISTINCT factor.gene_symbol) AS text) AS gene_symbol_list, \r\n" | |
| + "CAST(ARRAY_AGG(DISTINCT factor.factor_id) AS text) AS factor_id_list, \r\n" | |
| + "CAST(ARRAY_AGG(DISTINCT factor.tax_id) AS text) AS tax_id_list \r\n" + "FROM fits\r\n" | |
| + "INNER JOIN count_fit ON fits.fit_id = count_fit.fit_id\r\n" | |
| + "INNER JOIN count_table ON count_fit.count_table_id = count_table.count_table_id \r\n" | |
| + "INNER JOIN experiment ON count_table.study_name = experiment.study_name AND count_table.experiment_name = experiment.experiment_name \r\n" | |
| + "INNER JOIN study ON experiment.study_name = study.study_name\r\n" | |
| + "INNER JOIN factor_complex ON experiment.complex_id = factor_complex.complex_id \r\n" | |
| + "INNER JOIN factor ON factor_complex.factor_id = factor.factor_id \r\n" + "WHERE fits.fit_id = ?1\r\n" | |
| + "GROUP BY fits.fit_id, fits.fit_path\r\n" + "LIMIT 1", nativeQuery = true) | |
| List<Object[]> retrieveFitMetadata(Integer fitId); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment